Update.
[elisp.git] / emacs.el
1 ;; -*- mode: Emacs-Lisp; mode: rainbow; -*-
2
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4 ;; This program is free software; you can redistribute it and/or         ;;
5 ;; modify it under the terms of the GNU General Public License as        ;;
6 ;; published by the Free Software Foundation; either version 3, or (at   ;;
7 ;; your option) any later version.                                       ;;
8 ;;                                                                       ;;
9 ;; This program is distributed in the hope that it will be useful, but   ;;
10 ;; WITHOUT ANY WARRANTY; without even the implied warranty of            ;;
11 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      ;;
12 ;; General Public License for more details.                              ;;
13 ;;                                                                       ;;
14 ;; You should have received a copy of the GNU General Public License     ;;
15 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.  ;;
16 ;;                                                                       ;;
17 ;; Written by and Copyright (C) Francois Fleuret                         ;;
18 ;; Contact <francois@fleuret.org> for comments & bug reports             ;;
19 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20
21 ;; It's better to set the preferences in the .Xresources so that the
22 ;; window is not first displayed with the wrong options
23
24 ;; Emacs.menuBar:            off
25 ;; Emacs.verticalScrollBars: off
26 ;; Emacs.toolBar:            off
27 ;; Emacs.internalBorder:     1
28 ;; Emacs.FontBackend: xft
29 ;; Xft.dpi: 96
30 ;; Xft.hinting: true
31 ;; Xft.antialias: true
32 ;; Xft.rgba: rgb
33
34 (set-default-font "Inconsolata 15")
35
36 ;; (set-default-font "Bitstream vera sans mono-12")
37 ;; (set-default-font "Liberation Mono-13")
38 ;; (set-default-font "DejaVu sans mono 15")
39 ;; (set-default-font "Droid sans mono 13")
40 ;; (set-default-font "Opensans 10")
41
42 (when (fboundp 'horizontal-scroll-bar-mode)
43   (horizontal-scroll-bar-mode -1))
44
45 ;; This is where I put most of my emacs-related files
46 (setq ff/emacs-dir "~/private/emacs")
47 (unless (file-exists-p ff/emacs-dir)
48   (mkdir ff/emacs-dir t))
49
50 ;; Give the focus to the emacs window if we are under a windowing
51 ;; system
52
53 (when window-system
54   ;; (x-focus-frame nil)
55   (set-mouse-pixel-position (selected-frame) 4 4))
56
57 ;; Where I keep my own scripts
58
59 (add-to-list 'load-path "~/sources/gpl/elisp")
60 (add-to-list 'load-path "~/sources/elisp")
61 (add-to-list 'load-path "~/local/elisp")
62
63 ;; No, I do not like menus
64 (menu-bar-mode -1)
65
66 ;; Nor fringes
67 ;; (when (functionp 'fringe-mode) (fringe-mode '(0 . 0)))
68 ;; (when (functionp 'fringe-mode) (fringe-mode '(0 . 1)))
69 (when (functionp 'fringe-mode) (fringe-mode 10))
70
71 ;; And I do not like scrollbar neither
72 (when (functionp 'scroll-bar-mode) (scroll-bar-mode -1))
73
74 ;; Make all "yes or no" prompts be "y or n" instead
75 (fset 'yes-or-no-p 'y-or-n-p)
76
77 ;; The space bar acting as "yes" has been several times really
78 ;; problematic.
79 (define-key query-replace-map (kbd "SPC") nil)
80
81 ;; Show the matching parenthesis and do it immediately, we are in a
82 ;; hurry
83 (setq show-paren-delay 0)
84 (show-paren-mode t)
85
86 ;; use colorization for all modes
87 (global-font-lock-mode t)
88
89 (setq font-lock-maximum-decoration 3
90       ;;'((latex-mode . 2) (t . 2))
91       )
92
93 ;; Activate the dynamic completion of buffer names
94 ;; (iswitchb-mode 1)
95 ;; (load "lcomplete")
96
97 ;; Save the minibuffer history
98 (setq savehist-file (concat ff/emacs-dir "/savehist"))
99 (when (functionp 'savehist-mode) (savehist-mode 1))
100
101 ;; And allow minibuffer recursion
102 (setq enable-recursive-minibuffers t)
103 (minibuffer-depth-indicate-mode 1)
104
105 ;; I do not like tooltips
106 (when (functionp 'tooltip-mode) (tooltip-mode nil))
107
108 ;; Activate the dynamic completion in the mini-buffer
109 (icomplete-mode 1)
110
111 ;; (setq highlight-current-line-globally t
112 ;; highlight-current-line-ignore-regexp "Faces\\|Colors\\| \\*Mini\\|\\*media\\|INBOX")
113
114 ;; (highlight-current-line-minor-mode 1)
115 ;; (highlight-current-line-set-bg-color "gray75")
116
117 (defun ff/compile-when-needed (name)
118   "Compiles the given file only if needed. Adds .el if required, and
119 uses `load-path' to find it."
120   (if (not (string-match "\.el$" name))
121       (ff/compile-when-needed (concat name ".el"))
122     (mapc (lambda (dir)
123             (let* ((src (concat dir "/" name)))
124               (when (file-newer-than-file-p src (concat src "c"))
125                 (if (let ((byte-compile-verbose nil))
126                       (condition-case nil
127                           (byte-compile-file src)
128                         (error nil)))
129                     (message (format "Compiled %s" src ))
130                   (message (format "Failed compilation of %s" src))))))
131           load-path)))
132
133 ;; This is useful when using the same .emacs in many places
134
135 (defun ff/load-or-alert (name &optional compile-when-needed)
136   "Tries to load the specified file and insert a warning message in a
137 load-warning buffer in case of failure."
138
139   (when compile-when-needed (ff/compile-when-needed name))
140
141   (if (load name t nil) t
142     (let ((buf (get-buffer-create "*loading warnings*")))
143       (display-buffer buf)
144       (set-buffer buf)
145       (insert (propertize "Warning:" 'face 'font-lock-warning-face) " could not load '" name "'\n")
146       (fit-window-to-buffer (get-buffer-window buf))
147       (set-buffer-modified-p nil))
148     nil))
149
150 ;; This is the default in emacs 22.1 and later
151 ;; (auto-compression-mode 1)
152
153 ;; make emacs use the clipboard so that copy/paste works for other
154 ;; x-programs. I have no clue how all that clipboard thing works.
155
156 ;; (setq x-select-enable-clipboard t)
157 ;; (setq interprogram-paste-function 'x-cut-buffer-or-selection-value)
158 ;; (setq x-select-enable-primary t)
159 ;; (setq x-select-enable-clipboard t)
160 ;; (global-set-key "\C-y" 'clipboard-yank)
161
162 (setq
163
164  message-log-max 1000
165
166  ;; avoid GC as much as possible
167  gc-cons-threshold 2500000
168
169  ;; no startup message
170  inhibit-startup-screen t
171
172  ;; no message in the scratch buffer
173  initial-scratch-message nil
174
175  ;; do not fill my buffers, you fool
176  next-line-add-newlines nil
177
178  ;; keep the window focused on the messages during compilation
179  compilation-scroll-output t
180
181  ;; Keep the highlight on the compilation error
182  next-error-highlight t
183
184  ;; blink the screen instead of beeping
185  ;; visible-bell t
186
187  ;; take the CR when killing a line
188  kill-whole-line t
189
190  ;; I prefer to move between lines as defined in the buffer, not
191  ;; visually
192  line-move-visual nil
193
194  ;; I comment empty lines, too (does not seem to work, though)
195  comment-empty-lines t
196
197  ;; We want long lines to be truncated instead of displayed on several lines
198  ;; truncate-lines t
199  ;; Show all lines, even if the window is not as large as the frame
200  ;; truncate-partial-width-windows nil
201  ;; truncate-partial-width-windows t
202
203  ;; Do not keep tracks of the autosaved files
204  auto-save-list-file-prefix nil
205
206  ;; Show me empty lines at the end of the buffer
207  default-indicate-empty-lines t
208
209  ;; Show me the region until I do something on it
210  transient-mark-mode t
211
212  ;; Do not color stuff which are clickable when hovering over it
213  mouse-highlight nil
214
215  ;; Don't bother me with questions even if "unsafe" local variables
216  ;; are set
217  enable-local-variables :all
218
219  ;; I have no problem with small windows
220  window-min-height 1
221
222  ;; I am not a fan of develock
223  develock-auto-enable nil
224
225  ;; I do not like women to open windows
226  woman-use-own-frame nil
227
228  ;; I am not that paranoid, contrary to what you think
229  epa-file-cache-passphrase-for-symmetric-encryption t
230  ;; And I like ascii files
231  epa-armor t
232
233  ;; tramp-default-method "ssh"
234  tramp-default-method "scp"
235
236  ;; I have no problem with files having their own local variables
237  enable-local-eval t
238
239  mail-from-style 'angles
240  browse-url-mozilla-program "firefox"
241  mc-encrypt-for-me t
242  mc-use-default-recipients t
243
244  ;; browse-url-new-window-flag t
245
246  ;; I do not like compilation to automatically split the active window
247  ;; vertically, even when the said window is very wide
248  split-height-threshold 0
249  split-width-threshold nil
250
251  )
252
253 ;; The backups
254
255 (setq
256  temporary-file-directory "/tmp/"
257  vc-make-backup-files t
258  backup-directory-alist '((".*" . "~/misc/emacs.backups/"))
259  version-control t ;; Use backup files with numbers
260  kept-new-versions 10
261  kept-old-versions 2
262  delete-old-versions t
263  backup-by-copying-when-linked t
264  )
265
266 (setq tramp-backup-directory-alist backup-directory-alist)
267
268 (setq user-emacs-directory "~/misc/emacs.d/")
269
270 (setq
271  abbrev-file-name (concat user-emacs-directory "abbrev_defs")
272  server-auth-dir (concat user-emacs-directory "server/")
273  custom-theme-directory user-emacs-directory
274  )
275
276 ;; Stop this crazy blinking cursor
277 (blink-cursor-mode 0)
278
279 ;; (setq blink-cursor-delay 0.05
280 ;; blink-cursor-blinks 0
281 ;; blink-cursor-interval 0.25)
282
283 ;; (set-terminal-coding-system 'utf-8)
284
285 ;; (unless window-system
286 ;; (xterm-mouse-mode 1)
287 ;;   (if (string= (getenv "TERM") "xterm-256color")
288 ;;       (ff/load-or-alert "xterm-256color" t))
289 ;; )
290
291 (setq-default
292
293  ;; Show white spaces at the end of lines
294  show-trailing-whitespace t
295
296  ;; Do not show the cursor in non-active window
297  cursor-in-non-selected-windows nil
298
299  use-dialog-box nil
300  use-file-dialog nil
301
302  ;; when on a TAB, the cursor has the TAB length
303  x-stretch-cursor t
304
305  ;; This is the default coding system when toggle-input-method is
306  ;; invoked (C-\)
307  default-input-method "latin-1-prefix"
308
309  ;; do not put tabs when indenting
310  indent-tabs-mode nil
311  ;; Stop indenting automatically, that's annoying
312  electric-indent-chars nil
313
314  ;; And yes, we have a fast display / connection / whatever
315  baud-rate 524288
316  ;; baud-rate 10
317
318  ;; To keep the cursor always visible when it moves (thanks
319  ;; snogglethrop!)
320  redisplay-dont-pause t
321
322  ;; I want to see the keys I type instantaneously
323  echo-keystrokes 0.1
324  )
325
326 ;; Show the column number
327 (column-number-mode 1)
328
329 ;; What modes for what file extentions
330 (add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode))
331
332 (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
333
334 (require 'org-table)
335
336 (add-to-list 'auto-mode-alist '("\\.txt\\'" . (lambda()
337                                                 (text-mode)
338                                                 (orgtbl-mode)
339                                                 ;; (auto-fill-mode)
340                                                 (flyspell-mode))))
341
342 (add-hook 'c++-mode-hook 'flyspell-prog-mode)
343 (add-hook 'log-edit-mode-hook 'flyspell-mode)
344
345 ;; I am a power-user
346
347 (put 'narrow-to-region 'disabled nil)
348 (put 'upcase-region 'disabled nil)
349 (put 'downcase-region 'disabled nil)
350 ;; (put 'scroll-left 'disabled nil)
351 ;; (put 'scroll-right 'disabled nil)
352
353 ;; My selector is clearer than that
354 ;; (when (load "ido" t) (ido-mode t))
355
356 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
357
358 ;; Makes buffer names more explicit then <2>, <3> etc. when there are
359 ;; several identical filenames
360
361 (when (load "uniquify" t)
362   (setq uniquify-buffer-name-style 'post-forward-angle-brackets))
363
364 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
365 ;; Appearance
366 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
367
368 (when (boundp 'x-display-name)
369
370   (setq-default
371
372    ;; If the display is :0.0, we make the assumption that we are
373    ;; running the emacs locally, and we do not show the
374    ;; hostname. Otherwise, show @host.
375
376    frame-title-format (concat "emacs" ;;invocation-name
377                               (unless (string= x-display-name ":0.0")
378                                 (concat "@" system-name))
379                               " (%b)")
380
381    ;; Use the same for the icone
382
383    icon-title-format frame-title-format
384    ))
385
386 ;; "tool" bar? Are you kidding?
387 (when (fboundp 'tool-bar-mode) (tool-bar-mode -1))
388
389 ;; ;; If my own letter icon is here, use it and change its color
390 ;; (when (file-exists-p "~/local/share/emacs/letter.xbm")
391 ;; (setq-default display-time-mail-icon
392 ;; (find-image
393 ;; '((:type xbm
394 ;; :file "~/local/share/emacs/letter.xbm"
395 ;; :ascent center)))))
396
397 ;; My funky setting of face colors. Basically, we switch to a sober
398 ;; look and darken a bit the colors which need to (because of the
399 ;; darker background)
400
401 (defun ff/configure-faces (fl)
402   "Set face attributes and create faces when necessary"
403   (mapc (lambda (f)
404           (unless (boundp (car f)) (make-empty-face (car f)))
405           (eval `(set-face-attribute (car f) nil ,@(cdr f))))
406         fl))
407
408 ;; Not the same in xterm (which is gray in my case) and in
409 ;; X-window
410
411 (when window-system
412   ;; (setq
413   ;; display-time-use-mail-icon t)
414
415   (ff/configure-faces
416    '(
417      ;; (escape-glyph :foreground "#c0c0c0" :weight 'bold)
418      (escape-glyph :foreground "green3" :weight 'bold)
419      (default :background "gray90" :foreground "black")
420      (cperl-array-face :background "gray90" :foreground "blue" :weight 'bold)
421      (cperl-hash-face :background "gray90" :foreground "purple" :weight 'bold)
422      (message-cited-text :foreground "red4")
423      (diff-mode :background "gray90" :weight 'bold)
424      (diff-added :background "gray90" :foreground "green4" :weight 'bold)
425      (diff-removed :background "gray90" :foreground "red2" :weight 'bold)
426      (diff-changed :background "gray90" :foreground "blue" :weight 'bold)
427      (diff-file-header :background "white" :foreground "black"
428                        :weight 'bold)
429      (diff-header :background "white" :foreground "black")
430      (diff-hunk-header :background "white" :foreground "black")
431      (font-lock-builtin-face :foreground "deeppink3")
432      (font-lock-string-face :foreground "dark olive green")
433      (font-lock-variable-name-face :foreground "sienna")
434      ;; (font-lock-function-name-face :foreground "blue" :weight 'bold)
435      (font-lock-function-name-face :foreground "blue")
436      ;; (font-lock-comment-delimiter-face :foreground "dark violet")
437      ;; (font-lock-comment-face :foreground "dark violet")
438      (flyspell-incorrect :background "#ff0000" :foreground "black")
439      (flyspell-duplicate :background "#ff9000" :foreground "black")
440      (hl-line :background "white")
441      (sh-heredoc :foreground "black" :background "#fff0f0")
442      (sh-heredoc-face :foreground "black" :background "#fff0f0")
443      (header-line :background "gray65")
444      (highlight :background "turquoise")
445      (message-cited-text-face :foreground "firebrick")
446      (isearch :background "yellow" :foreground "black")
447      (isearch-lazy-highlight-face' :background "yellow3" :foreground "black")
448      (region :background "#b8b8e0" :foreground "black")
449      ;; (region :background "plum" :foreground "black")
450      (show-paren-match-face :background "gold" :foreground "black")
451      (show-paren-mismatch-face :background "red" :foreground "black")
452      (trailing-whitespace :background "gray65")
453      (cursor :inverse-video t)
454      (enotes/list-title-face :foreground "blue" :weight 'bold)
455      (mode-line :background "#b0b0ff" :foreground "black" :box nil
456                 :inverse-video nil)
457      (header-line :background "cornflowerblue" :foreground "black" :box nil
458                   :inverse-video nil)
459      (mode-line-inactive :background "gray80" :foreground "black" :box nil
460                          :inverse-video nil)
461      ;; (fringe :background "black" :foreground "gray90")
462      (fringe :background "gray80")
463      (ff/date-info-face :foreground "white")
464      (ff/battery-info-face :foreground "white")
465      (ff/mail-alarm-face :foreground "white" :background "red2")
466      ;; (alarm-vc-face :foreground "black" :background "yellow" :weight 'normal)
467      (gui-button-face :background "green" :foreground "black")
468      ))
469   )
470
471 (unless window-system
472   ;; (xterm-mouse-mode 1)
473   (ff/configure-faces
474    '((italic :underline nil)
475      (info-title-2 :foreground "green")
476      (font-lock-comment-delimiter-face :foreground "green")
477      (font-lock-comment-face :foreground "green")
478      (cperl-array-face :background "gray90" :foreground "blue" :weight 'bold)
479      (cperl-hash-face :background "gray90" :foreground "purple" :weight 'bold)
480      (diff-added :background "gray90" :foreground "green4" :weight 'bold)
481      (diff-removed :background "gray90" :foreground "red2" :weight 'bold)
482      (diff-changed :background "gray90" :foreground "blue" :weight 'bold)
483      (diff-file-header-face :background "white" :foreground "black"
484                             :weight 'bold)
485      (diff-header-face :background "white" :foreground "black")
486      (diff-hunk-header-face :background "white" :foreground "black")
487      (diff-indicator-removed :foreground "red" :weight 'bold)
488      (diff-removed :foreground "red" :weight 'bold)
489      (diff-indicator-added :foreground "blue" :weight 'bold)
490      (diff-added :foreground "blue" :weight 'bold)
491      (font-lock-string-face :foreground "green")
492      (font-lock-variable-name-face :foreground "blue")
493      (font-lock-constant-face :foreground "blue")
494      (font-lock-preprocessor-face :foreground "green")
495      (font-lock-function-name-face :foreground "cyan")
496      (flyspell-incorrect :foreground "red2")
497      (flyspell-duplicate :foreground "OrangeRed2")
498      (hl-line :background "white")
499      (sh-heredoc :foreground "black" :background "#fff0f0")
500      (sh-heredoc-face :foreground "black" :background "#fff0f0")
501      (font-lock-keyword-face :foreground "blue")
502      (highlight :background "darkseagreen3")
503      (isearch :background "orange" :foreground "black")
504      (isearch-lazy-highlight-face' :background "yellow" :foreground "black")
505      ;; (display-time-mail-face :background "white")
506      (show-paren-match-face :background "gold" :foreground "black")
507      (show-paren-mismatch-face :background "red" :foreground "black")
508      (trailing-whitespace :background "white")
509      (mode-line :background "cornflowerblue" :foreground "black" :box nil
510                 :inverse-video nil)
511      (header-line :background "cornflowerblue" :foreground "black" :box nil
512                   :inverse-video nil)
513      (mode-line-inactive :background "gray60" :foreground "black" :box nil
514                          :inverse-video nil)
515      (region :background "white" :foreground "black")
516      (ff/date-info-face :foreground "white" :weight 'bold)
517      (ff/battery-info-face :foreground "white")
518      (ff/mail-alarm-face :foreground "red" :weight 'bold)
519      (selector/selection :background "yellow")
520      (gui-button-face :background "green" :foreground "white")
521      (enotes/information-face :foreground "cyan")
522
523      (file-name-shadow :foreground "black")
524      (shadow :foreground "black")
525      (warning :foreground "black" :background "red")
526      ))
527   )
528
529 ;; When we are root, put the modeline in red
530
531 (when (string= (user-real-login-name) "root")
532   (ff/configure-faces
533    '((mode-line :background "red3" :foreground "black" :box nil
534                 :inverse-video nil))
535    ))
536
537 ;; Why should I have to do this?
538 (add-hook 'sh-mode-hook
539           (lambda ()
540             (set-face-attribute 'sh-heredoc nil
541                                 :foreground "#604000"
542                                 :background "white"
543                                 :italic t)
544             (set-face-attribute 'sh-heredoc-face nil
545                                 :foreground "#604000"
546                                 :background "white"
547                                 :italic t)
548             ))
549
550 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
551 ;; Move the window on the buffer without moving the cursor
552 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
553
554 (defun ff/scroll-down ()
555   "Scroll the buffer down one line and keep the cursor at the same location."
556   (interactive)
557   (condition-case nil
558       (scroll-down 1)
559     (error nil)))
560
561 (defun ff/scroll-up ()
562   "Scroll the buffer up one line and keep the cursor at the same location."
563   (interactive)
564   (condition-case nil
565       (scroll-up 1)
566     (error nil)))
567
568 (defun ff/scroll-left ()
569   "Scroll the buffer left one column and keep the cursor at the same location."
570   (interactive)
571   (condition-case nil
572       (scroll-left 2)
573     (error nil)))
574
575 (defun ff/scroll-right ()
576   "Scroll the buffer right one column and keep the cursor at the same location."
577   (interactive)
578   (condition-case nil
579       (scroll-right 2)
580     (error nil)))
581
582 (define-key global-map [(meta up)] 'ff/scroll-down)
583 (define-key global-map [(meta down)] 'ff/scroll-up)
584
585 (define-key global-map [(meta shift up)]
586   (lambda () (interactive) (condition-case nil (scroll-down 10) (error nil))))
587
588 (define-key global-map [(meta shift down)]
589   (lambda () (interactive) (condition-case nil (scroll-up 10) (error nil))))
590
591 ;; (define-key global-map [(meta shift up)] (lambda () (interactive) (ff/scroll-down 10)))
592 ;; (define-key global-map [(meta shift down)] 'ff/scroll-up)
593
594 (define-key global-map [(meta p)] 'ff/scroll-down)
595 (define-key global-map [(meta n)] 'ff/scroll-up)
596 (define-key global-map [(meta right)] 'ff/scroll-left)
597 (define-key global-map [(meta left)] 'ff/scroll-right)
598
599 (defun ff/delete-trailing-whitespaces-and-indent ()
600   (interactive)
601   (delete-trailing-whitespace)
602   (indent-region (point-min) (point-max) nil))
603
604 (define-key global-map [(control c) (control q)] 'ff/delete-trailing-whitespaces-and-indent)
605
606 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
607 ;; Playing sounds
608 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
609
610 ;; (defun ff/esd-sound (file)
611 ;;   "Plays a sound with the Enlighted sound daemon."
612 ;;   (interactive)
613 ;;   (process-kill-without-query (start-process-shell-command "esdplay"
614 ;;                                                            nil
615 ;;                                                            "esdplay" file)))
616
617 (defun ff/alsa-sound (file)
618   "Plays a sound with ALSA."
619   (interactive)
620   (process-kill-without-query (start-process-shell-command "aplay"
621                                                            nil
622                                                            "aplay" "-q" file)))
623
624 (if (and (boundp 'x-display-name) (string= x-display-name ":0.0"))
625     (defalias 'ff/play-sound-async 'ff/alsa-sound)
626   (defalias 'ff/play-sound-async 'ding))
627
628 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
629 ;; I comment stuff often, let's be efficient. shift + down comments
630 ;; the current line and goes down, and shift + up uncomments the line
631 ;; and goes up (they are not the dual of each other, but moving and
632 ;; then uncommenting would be very counter-intuitive).
633 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
634
635 (defun ff/comment-and-go-down (arg)
636   "Comments and goes down ARG lines."
637   (interactive "p")
638   (condition-case nil
639       (comment-region (point-at-bol) (point-at-eol)) (error nil))
640   (next-line 1)
641   (if (> arg 1) (ff/comment-and-go-down (1- arg))))
642
643 (defun ff/uncomment-and-go-up (arg)
644   "Uncomments and goes up ARG lines."
645   (interactive "p")
646   (condition-case nil
647       (uncomment-region (point-at-bol) (point-at-eol)) (error nil))
648   (next-line -1)
649   (if (> arg 1) (ff/uncomment-and-go-up (1- arg))))
650
651 (define-key global-map [(shift down)] 'ff/comment-and-go-down)
652 (define-key global-map [(shift up)] 'ff/uncomment-and-go-up)
653
654 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
655 ;; Counting various entities in text
656 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
657
658 (defun ff/word-occurences ()
659   "Display in a new buffer the list of words sorted by number of
660 occurrences "
661   (interactive)
662
663   (let ((buf (get-buffer-create "*word counting*"))
664         (map (make-sparse-keymap))
665         (nb (make-hash-table))
666         (st (make-hash-table))
667         (result nil))
668
669     ;; Collects all words in a hash table
670
671     (save-excursion
672       (goto-char (point-min))
673       (while (re-search-forward "\\([\\-a-zA-Z\\\\]+\\)" nil t)
674         (let* ((s (downcase (match-string-no-properties 1)))
675                (k (sxhash s)))
676           (puthash k s st)
677           (puthash k (1+ (gethash k nb 0)) nb))))
678
679     ;; Creates the result buffer
680
681     (define-key map "q" 'kill-this-buffer)
682     (display-buffer buf)
683     (set-buffer buf)
684     (setq show-trailing-whitespace nil)
685     (erase-buffer)
686
687     ;; Builds a list from the hash table
688
689     (maphash
690      (lambda (key value)
691        (setq result (cons (cons value (gethash key st)) result)))
692      nb)
693
694     ;; Sort and display it
695
696     (mapc (lambda (x)
697             (if (and (> (car x) 3)
698                      ;; No leading backslash and at least four characters
699                      (string-match "^[^\\]\\{4,\\}" (cdr x))
700                      )
701                 (insert (number-to-string (car x)) " " (cdr x) "\n")))
702           (sort result (lambda (a b) (> (car a) (car b)))))
703
704     ;; Adjust the window size and stuff
705
706     (fit-window-to-buffer (get-buffer-window buf))
707     (use-local-map map)
708     (set-buffer-modified-p nil))
709   )
710
711 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
712 ;; Printing
713 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
714
715 (load "ps-print")
716
717 (setq ps-print-color-p nil
718       ps-paper-type 'letter
719       ;; ps-paper-type 'a4
720       ;; ps-top-margin (* 1.75 56.692)
721       ;; ps-left-margin 56.692
722       ;; ps-bottom-margin 56.692
723       ;; ps-right-margin 56.692
724
725       ;; Simple header. Remove that silly frame shadow.
726       ps-print-header nil
727       ps-print-header-frame nil
728       ps-header-line-pad 0.3
729       ps-header-font-family 'Courier
730       ps-header-title-font-size '(8.5 . 10)
731       ;; ps-header-font-size '(6 . 7)
732       ps-header-font-size '(10 . 12)
733       ps-font-size '(7 . 8)
734       )
735
736 (ps-put 'ps-header-frame-alist 'back-color 1.0)
737 (ps-put 'ps-header-frame-alist 'shadow-color 1.0)
738 (ps-put 'ps-header-frame-alist 'border-color 0.0)
739 (ps-put 'ps-header-frame-alist 'border-width 0.0)
740
741 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
742
743 ;; http://blog.tuxicity.se/elisp/emacs/2010/03/26/rename-file-and-buffer-in-emacs.htm
744
745 (defun rename-file-and-buffer ()
746   "Renames current buffer and file it is visiting."
747   (interactive)
748   (let ((name (buffer-name))
749         (filename (buffer-file-name)))
750     (if (not (and filename (file-exists-p filename)))
751         (message "Buffer '%s' is not visiting a file!" name)
752       (let ((new-name (read-file-name "New name: " filename)))
753         (cond ((get-buffer new-name)
754                (message "A buffer named '%s' already exists!" new-name))
755               (t
756                (rename-file name new-name 1)
757                (rename-buffer new-name)
758                (set-visited-file-name new-name)
759                (set-buffer-modified-p nil)))))))
760
761 (global-set-key (kbd "C-c r") 'rename-file-and-buffer)
762
763 (defun ff/non-existing-filename (dir prefix suffix)
764   "Returns a filename of the form DIR/PREFIX[.n].SUFFIX whose file does
765 not exist"
766   (let ((n 0)
767         (f (concat prefix suffix)))
768     (while (file-exists-p (concat dir "/" f))
769       (setq n (1+ n)
770             f (concat prefix "." (prin1-to-string n) suffix)))
771     f))
772
773 (defun ff/print-buffer-or-region-with-faces (&optional file)
774
775   ;; I am fed up with spell checking highlights
776   (when (and flyspell-mode
777              ;; (or ispell-minor-mode flyspell-mode)
778              (not (y-or-n-p "The spell checking is on, still print ? ")))
779     (error "Printing cancelled, the spell-checking is on"))
780
781   (unless
782       (condition-case nil
783           (ps-print-region-with-faces (region-beginning) (region-end) file)
784         (error nil))
785     (ps-print-buffer-with-faces file)))
786
787 (defun ff/print-to-file (file)
788   "Prints the region if selected or the whole buffer in postscript
789 into FILE."
790   (interactive
791    (list
792     (read-file-name
793      "PS file: " "/tmp/" nil nil
794      (ff/non-existing-filename
795       "/tmp"
796       (replace-regexp-in-string "[^a-zA-Z0-9_.-]" "_" (file-name-nondirectory
797                                                        (buffer-name)))
798       ".ps"))
799     ))
800   (ff/print-buffer-or-region-with-faces file))
801
802 (defun ff/print-to-printer ()
803   "Prints the region if selected or the whole buffer to a postscript
804 printer."
805   (interactive)
806   (message "Printing to '%s'" (getenv "PRINTER"))
807   (ff/print-buffer-or-region-with-faces))
808
809 ;; Can you believe it? There is a "print" key on PC keyboards ...
810
811 (define-key global-map [(print)] 'ff/print-to-file)
812 (define-key global-map [(shift print)] 'ff/print-to-printer)
813
814 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
815 ;; Dealing with the laptop battery
816 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
817
818 (defcustom ff/battery-dirs '("/sys/class/power_supply/BAT0"
819                              "/sys/class/power_supply/BAT1")
820   "*Where to gather the battery information")
821
822 (defcustom ff/temperature-files '("/sys/class/thermal/thermal_zone0/temp"
823                                   "/sys/class/thermal/thermal_zone1/temp")
824   "*Where to gather the thermal information")
825
826 (defun ff/file-first-line (file)
827   (with-temp-buffer
828     (insert-file-contents-literally file)
829     (buffer-substring (point-at-bol) (point-at-eol))))
830
831 (defun ff/battery-discharging (l)
832   (and l (or (string= (ff/file-first-line (concat (car l) "/status")) "Discharging")
833              (ff/battery-discharging (cdr l)))))
834
835 ;; If there is one "Discharging" among the states of all the
836 ;; batteries, the global state is 'discharging. Otherwise, if there is
837 ;; a "Charging", the state is 'charging. If none is true, it is
838 ;; 'unknown
839 (defun ff/battery-state (l)
840   (if l
841       (let ((u (ff/file-first-line (concat (car l) "/status"))))
842         (if (string= u "Discharging") 'discharging
843           (let ((s (ff/battery-state (cdr l))))
844             (if (eq s 'discharging) 'discharging
845               (if (or (eq s 'charging) (string= u "Charging"))
846                   'charging
847                 'unknown))
848             )
849           )
850         )
851     'unknown))
852
853 (defun ff/sum-values-from-files (list-files prefix)
854   (apply '+
855          (mapcar
856           (lambda (f)
857             (condition-case nil
858                 (string-to-number (ff/file-first-line (format "%s/%s" f prefix)))
859               (error 0))
860             )
861           list-files)))
862
863 (defun ff/battery-percent ()
864   (condition-case nil
865       (/ (* 100 (ff/sum-values-from-files ff/battery-dirs "energy_now"))
866          (ff/sum-values-from-files ff/battery-dirs "energy_full"))
867     (error -1))
868   )
869
870 (defun ff/temp-and-battery-info-string () (interactive)
871        (condition-case nil
872            (concat
873
874             ;; The temperature
875
876             (let ((temp (/
877                          (apply 'max (mapcar
878                                       (lambda (f) (string-to-number (ff/file-first-line f)))
879                                       ff/temperature-files))
880                          1000)))
881
882               (if (> temp 50)
883                   (let ((s (format "%dC " temp)))
884                     (if (> temp 70)
885                         (propertize s 'face 'font-lock-warning-face)
886                       s)
887                     )
888                 )
889               )
890
891             ;; The battery
892
893              (pcase (ff/battery-state ff/battery-dirs)
894                ;; (`charging (format "c%d%%" (ff/battery-percent)))
895                ;; (`discharging (format "d%d%%" (ff/battery-percent)))
896                ;; (`unknown "f")
897                (`charging (format "↑%d%%" (ff/battery-percent)))
898                (`discharging (format "↓%d%%" (ff/battery-percent)))
899                (`unknown "✱")
900                (_ "?"))
901
902             )
903
904          (error nil))
905        )
906
907 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
908
909 (defun ff/system-info () (interactive)
910
911        (let ((buf (get-buffer-create "*system info*"))
912              (map (make-sparse-keymap)))
913
914          (define-key map "q" 'kill-this-buffer)
915          (display-buffer buf)
916          (set-buffer buf)
917          (setq show-trailing-whitespace nil)
918          (erase-buffer)
919
920          (let ((highlight nil))
921
922            (mapc (lambda (x)
923                    (insert
924                     (if (setq highlight (not highlight))
925                         (propertize
926                          (with-temp-buffer (apply 'call-process x)
927                                            (buffer-string))
928                          'face '(:background "#d0d0ff"))
929                       (with-temp-buffer (apply 'call-process x)
930                                         (buffer-string))
931                       ))
932                    )
933
934                  '(
935                    ("hostname" nil t nil "-f")
936                    ("acpi" nil t)
937                    ("df" nil t nil "-h")
938                    ;; ("mount" nil t)
939                    ("ifconfig" nil t)
940                    ("ssh-add" nil t nil "-l")
941                    )))
942
943          (goto-char (point-min))
944          (while (re-search-forward "^$" nil t) (backward-delete-char 1))
945
946          (fit-window-to-buffer (get-buffer-window buf))
947          (use-local-map map)
948          (set-buffer-modified-p nil)
949          ))
950
951 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
952 ;; Make a sound when there is new mail
953 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
954
955 ;; I do not like sounds anymore
956
957 ;; (setq ff/already-boinged-for-mail nil)
958
959 ;; (defun ff/boing-if-new-mail ()
960 ;; (if mail (when (not ff/already-boinged-for-mail)
961 ;; ;; (ff/play-sound-async "~/local/sounds/boing1.wav")
962 ;; ;; (ff/show-unspooled-mails)
963 ;; (setq ff/already-boinged-for-mail t))
964 ;; (setq ff/already-boinged-for-mail nil))
965 ;; )
966
967 ;; (add-hook 'display-time-hook 'ff/boing-if-new-mail)
968
969 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
970 ;; Display time
971 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
972
973 (setq
974
975  display-time-interval 15 ;; Check every 15s
976
977  display-time-string-forms `(
978
979                              load " "
980
981                              (propertize
982                               (ff/temp-and-battery-info-string)
983                               'face 'ff/battery-info-face)
984
985                              (propertize
986                               (concat " <"
987                                       24-hours ":" minutes
988                                       " "
989                                       ;; dayname " "
990                                       monthname " " day
991                                       ">")
992                               'face 'ff/date-info-face)
993
994                              )
995
996  ;; display-time-format "%b %a %e %H:%M"
997  ;; display-time-mail-face nil
998  )
999
1000 ;; Show the time, mail and stuff
1001 (display-time)
1002
1003 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1004 ;; Moving through buffers
1005 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1006
1007 (defun ff/next-buffer ()
1008   "Switches to the next buffer in cyclic order."
1009   (interactive)
1010   (let ((buffer (current-buffer)))
1011     (switch-to-buffer (other-buffer buffer))
1012     (bury-buffer buffer)))
1013
1014 (defun ff/prev-buffer ()
1015   "Switches to the previous buffer in cyclic order."
1016   (interactive)
1017   (let ((list (nreverse (buffer-list)))
1018         found)
1019     (while (and (not found) list)
1020       (let ((buffer (car list)))
1021         (if (and (not (get-buffer-window buffer))
1022                  (not (string-match "\\` " (buffer-name buffer))))
1023             (setq found buffer)))
1024       (setq list (cdr list)))
1025     (switch-to-buffer found)))
1026
1027 ;; (define-key global-map [?\C-x right] 'ff/next-buffer)
1028 ;; (define-key global-map [?\C-x left] 'ff/prev-buffer)
1029 ;; (define-key global-map [?\M-\]] 'ff/next-buffer)
1030 ;; (define-key global-map [?\M-\[] 'ff/prev-buffer)
1031
1032 (define-key global-map [(meta right)] 'ff/next-buffer)
1033 (define-key global-map [(meta left)] 'ff/prev-buffer)
1034
1035 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1036 ;; There is actually a decent terminal emulator in emacs!
1037 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1038
1039 (load "term")
1040
1041 (defun ff/kill-associated-buffer (process str) (interactive)
1042        (let ((buffer (process-buffer process)))
1043          (kill-buffer buffer))
1044        (message "Process finished (%s)" (replace-regexp-in-string "\n$" "" str)))
1045
1046 (defun ff/kill-associated-buffer-and-delete-windows (process str) (interactive)
1047        (let ((buffer (process-buffer process)))
1048          (delete-windows-on buffer)
1049          (kill-buffer buffer))
1050        (message "Process finished (%s)" (replace-regexp-in-string "\n$" "" str)))
1051
1052 (defun ff/shell-new-buffer (buffername program &rest param)
1053   "Start a terminal-emulator in a new buffer with the shell PROGRAM,
1054 optionally invoked with the parameters PARAM. The process associated
1055 to the shell can be killed without query."
1056
1057   (interactive)
1058
1059   (let ((n 1)
1060         (bn buffername))
1061
1062     (while (get-buffer (concat "*" bn "*"))
1063       (setq n (1+ n)
1064             bn (format "%s<%d>" buffername n)))
1065
1066     (set-buffer (apply 'make-term (append (list bn program nil) param)))
1067
1068     (setq show-trailing-whitespace nil)
1069     (term-char-mode)
1070     (message "C-c C-k term-char-mode, C-c C-j term-line-mode. \
1071 In line mode: M-p previous line, M-n next line.")
1072
1073     ;; A standard setup of the face above is not enough, I have to
1074     ;; force them here. Since I have a gray90 background, I like
1075     ;; darker colors.
1076
1077     (when window-system
1078       (ff/configure-faces
1079        '((term-green :foreground "green3")
1080          (term-cyan :foreground "cyan3")
1081          (term-default-fg-inv :foreground "gray90" :background "black")
1082          )))
1083
1084     (term-set-escape-char ?\C-x)
1085
1086     ;; I like the shell buffer and windows to be deleted when the
1087     ;; shell process terminates. It's a bit of a mess to acheive this.
1088
1089     (let ((process (get-buffer-process (current-buffer))))
1090       (process-kill-without-query process)
1091       (set-process-sentinel process
1092                             ;; 'ff/kill-associated-buffer-and-delete-windows
1093                             'ff/kill-associated-buffer
1094                             ))
1095
1096     ;; (switch-to-buffer-other-window (concat "*" bn "*"))
1097     (switch-to-buffer (concat "*" bn "*"))
1098     ))
1099
1100 (defcustom ff/default-bash-commands '("ssh")
1101   "*List of commands to be used for completion when invoking a new
1102 bash shell with `ff/bash-new-buffer'.")
1103
1104 (defun ff/bash-new-buffer (universal)
1105   "Starts a bash in a new buffer. When invoked with a universal
1106 argument, asks for a command to execute in that bash shell. The list
1107 of commands in `ff/default-bash-commands' is used for auto-completion"
1108   (interactive "P")
1109
1110   (if universal
1111       (let ((cmd (completing-read
1112                   "Command: "
1113                   (mapcar (lambda (x) (cons x t)) ff/default-bash-commands))))
1114         (ff/shell-new-buffer cmd "/bin/bash" "-c" cmd))
1115
1116     (ff/shell-new-buffer "bash" "/bin/bash")))
1117
1118 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1119 ;; vc stuff for CVS
1120 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1121
1122 (setq ;; Always follow links if the file is under version control
1123  vc-follow-symlinks t
1124  )
1125
1126 (when (load "vc-git" nil t)
1127   (add-to-list 'vc-handled-backends 'GIT))
1128
1129 ;; alarm-vc.el is one of my own scripts, check my web page
1130
1131 (when (ff/load-or-alert "alarm-vc" t)
1132   (setq alarm-vc-mode-exceptions "^VM"))
1133
1134 (when (ff/load-or-alert "git")
1135   (setq git-show-unknown nil)
1136   )
1137
1138 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1139 ;; Makes .sh and others files executable automagically
1140 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1141
1142 ;; Please consider the security-related consequences of using it
1143
1144 ;; (defun ff/make-shell-scripts-executable (&optional filename)
1145 ;; (setq filename (or filename (buffer-name)))
1146 ;; (when (and (string-match "\\.sh$\\|\\.pl$\\|\\.rb" filename)
1147 ;; (not (file-executable-p filename))
1148 ;; )
1149 ;; (set-file-modes filename 493)
1150 ;; (message "Made %s executable" filename)))
1151
1152 ;; (add-hook 'after-save-hook 'ff/make-shell-scripts-executable)
1153
1154 (add-hook 'after-save-hook
1155           'executable-make-buffer-file-executable-if-script-p)
1156
1157 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1158 ;; Cool stuff to navigate in emacs-lisp sources
1159 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1160
1161 (load "find-func")
1162
1163 (defun ff/goto-function-definition (&optional goback)
1164   "Go directly to the definition of the function at point. With
1165 goback argument, go back where we were."
1166   (interactive "P")
1167   (if goback
1168       (if (not (and (boundp 'goto-function-history) goto-function-history))
1169           (error "We were nowhere, buddy")
1170         (message "Come back")
1171         (switch-to-buffer (car (car goto-function-history)))
1172         (goto-char (cdr (car goto-function-history)))
1173         (setq goto-function-history (cdr goto-function-history)))
1174
1175     (let ((function (function-called-at-point)))
1176       (when function
1177         (let ((location (find-function-search-for-symbol
1178                          function nil
1179                          (symbol-file function))))
1180           (setq goto-function-history
1181                 (cons (cons (current-buffer) (point))
1182                       (and (boundp 'goto-function-history)
1183                            goto-function-history)))
1184           (pop-to-buffer (car location))
1185           (goto-char (cdr location)))))))
1186
1187 (define-key global-map [(meta g)] 'ff/goto-function-definition)
1188 (define-key global-map [(meta G)] (lambda () (interactive)
1189                                     (ff/goto-function-definition t)))
1190
1191 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1192 ;; The big stuff (bbdb, mailcrypt, etc.)
1193 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1194
1195 ;; Failsafe version if we can't load bbdb
1196 (defun ff/explicit-name (email) email)
1197
1198 (load "vc-git")
1199
1200 (when (ff/load-or-alert "bbdb")
1201
1202   (setq
1203    ;; Stop asking (if not t or nil, will not ask)
1204    bbdb-offer-save 'never
1205    ;; I hate when bbdb decides to mess up my windows
1206    bbdb-use-pop-up nil
1207    ;; I have no problem with bbdb asking me if the sender email
1208    ;; does not match exactly the address we have in the database
1209    bbdb-quiet-about-name-mismatches 0
1210    ;; I have european friends, too
1211    bbdb-north-american-phone-numbers-p nil
1212    ;; To cycle through all possible addresses
1213    bbdb-complete-name-allow-cycling t
1214    ;; Cycle with full names only, not through all net-addresses alone too
1215    bbdb-dwim-net-address-allow-redundancy t
1216    ;; Do not add new addresses automatically
1217    bbdb-always-add-addresses nil
1218    )
1219
1220   (defface ff/known-address-face
1221     '((t (:foreground "blue2")))
1222     "The face to display known mail identities.")
1223
1224   (defface ff/unknown-address-face
1225     '((t (:foreground "gray50")))
1226     "The face to display unknown mail identities.")
1227
1228   (defun ff/explicit-name (email)
1229     "Returns a string identity for the first address in EMAIL. The
1230 identity is taken from bbdb if possible or from the address itself
1231 with mail-extract-address-components. The suffix \"& al.\" is added if
1232 there are more than one address.
1233
1234 If no bbdb record is found, the name is propertized with the face
1235 ff/unknown-address-face. If a record is found and contains a note
1236 'face, the associated face is used, otherwise
1237 ff/known-address-face is used."
1238
1239     (and email
1240          (let* ((data (mail-extract-address-components email))
1241                 (name (car data))
1242                 (net (cadr data))
1243                 (record (bbdb-search-simple nil net)))
1244
1245            (concat
1246
1247             (condition-case nil
1248                 (propertize (bbdb-record-name record)
1249                             'face
1250                             (or (cdr (assoc 'face
1251                                             (bbdb-record-raw-notes record)))
1252                                 'ff/known-address-face))
1253               (error
1254                (propertize (or (and data (concat "<" net ">"))
1255                                "*undefined*")
1256                            'face 'ff/unknown-address-face)
1257                ))
1258             (if (string-match "," (mail-strip-quoted-names email)) " & al.")
1259             )))
1260     )
1261
1262   (ff/configure-faces '((ff/robot-address-face :foreground "green4")
1263                         (ff/personal-address-face :foreground "dark magenta" :weight 'bold)
1264                         (ff/important-address-face :foreground "red3"
1265                                                    :weight 'bold
1266                                                    )))
1267
1268   )
1269
1270 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1271 ;; An encrypted file to put secure stuff (passwords, ...)
1272 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1273
1274 (when (ff/load-or-alert "mailcrypt")
1275   (mc-setversion "gpg")
1276   ;; Keep the passphrase for 10min
1277   (setq mc-passwd-timeout 600
1278         ff/secure-note-file "~/private/secure-notes.gpg")
1279   )
1280
1281 (defface ff/secure-date
1282   '((t (:background "white" :weight bold)))
1283   "The face to display the dates in the modeline.")
1284
1285 (defun ff/secure-note-add () (interactive)
1286
1287        (unless
1288            (let ((b (find-buffer-visiting ff/secure-note-file)))
1289              (and b (switch-to-buffer b)))
1290          (find-file ff/secure-note-file)
1291          ;; Adds a new entry (i.e. date and a bunch of empty lines)
1292          (goto-char (point-min))
1293          (insert "-- "
1294                  (format-time-string "%Y %b %d %H:%M:%S" (current-time))
1295                  " --\n\n")
1296          (previous-line 1)
1297          )
1298
1299        ;; Colorizes the dates
1300
1301        (save-excursion
1302          (goto-char (point-min))
1303          (while (re-search-forward
1304                  "^-- [0-9]+ [a-z]+ [0-9]+ [0-9]+:[0-9]+:[0-9]+ -+$"
1305                  nil t)
1306            (add-text-properties
1307             (match-beginning 0) (1+ (match-end 0))
1308             '(face ff/secure-date rear-nonsticky t))))
1309
1310        (set-buffer-modified-p nil)
1311        (setq buffer-undo-list nil)
1312        )
1313
1314 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1315 ;; Spelling
1316 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1317
1318 (setq ;; For french, aspell is far better than ispell
1319  ispell-program-name "aspell"
1320  ;; To avoid ispell errors in figure filenames, labels, references.
1321  ;;       ispell-tex-skip-alists
1322  ;;       (list
1323  ;;        (append (car ispell-tex-skip-alists)
1324  ;;                '(("\\\\citep"           ispell-tex-arg-end) ;; JMLR
1325  ;;                  ("\\\\cite"            ispell-tex-arg-end)
1326  ;;                  ("\\\\nocite"          ispell-tex-arg-end)
1327  ;;                  ("\\\\includegraphics" ispell-tex-arg-end)
1328  ;;                  ("\\\\author"          ispell-tex-arg-end)
1329  ;;                  ("\\\\ref"             ispell-tex-arg-end)
1330  ;;                  ("\\\\label"           ispell-tex-arg-end)
1331  ;;                  ))
1332  ;;        (cadr ispell-tex-skip-alists))
1333
1334  ;; So that reftex follows the text when moving in the summary
1335  reftex-toc-follow-mode nil
1336  ;; So that reftex visits files to follow
1337  reftex-revisit-to-follow t
1338  )
1339
1340 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1341 ;; Used in a \includegraphics runs xfig with the corresponding .fig
1342 ;; file or gimp with the corresponding bitmap picture
1343 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1344
1345 (defun ff/run-eps-edition (prefix rules &optional force)
1346   (if rules
1347       (let ((filename (concat prefix (car (car rules)))))
1348         (if (or force (file-exists-p filename))
1349             (start-process "latex-eps-editor" nil (cdr (car rules)) filename)
1350           (ff/run-eps-edition prefix (cdr rules) force)))
1351     (message "No original file found for %seps" prefix)))
1352
1353 (defcustom ff/xdvi-for-latex-options nil
1354   "*Options to pass to xdvi when invoking `ff/run-viewer'")
1355
1356 (defun ff/run-viewer (universal)
1357
1358   "Starts an editor for the .eps at point (either xfig or gimp,
1359 depending with the original file it can find), or starts xdvi for
1360 the current .tex if no .eps is found at point. When run with a
1361 universal argument starts xfig even if the .fig does not exist"
1362
1363   (interactive "P")
1364
1365   (if (and (save-excursion
1366              (and (re-search-backward "{" (point-at-bol) t)
1367                   (or (re-search-forward "{\\([^{}]*.\\)eps}" (point-at-eol) t)
1368                       (re-search-forward "{\\([^{}]*.\\)pdf}" (point-at-eol) t)
1369                       (re-search-forward "{\\([^{}]*.\\)pdf_t}" (point-at-eol) t)
1370                       (re-search-forward "{\\([^{}]*.\\)png}" (point-at-eol) t)
1371                       (re-search-forward "{\\([^{}]*.\\)jpg}" (point-at-eol) t)
1372                       )))
1373            (and (<= (match-beginning 1) (point))
1374                 (>= (match-end 1) (- (point) 2))))
1375
1376       (ff/run-eps-edition (match-string-no-properties 1)
1377                           '(("fig" . "xfig")
1378                             ("jpg" . "gimp" )
1379                             ("png" . "gimp") ("pgm" . "gimp") ("ppm" . "gimp")
1380                             ("jpg" . "xv"))
1381                           universal)
1382
1383     (if (not (and (buffer-file-name) (string-match "\\(.*\\)\.tex$"
1384                                                    (buffer-file-name))))
1385         (message "Not a latex file!")
1386       (condition-case nil (kill-process xdvi-process) (error nil))
1387       (let ((dvi-name (concat (match-string 1 (buffer-file-name)) ".dvi")))
1388         (if (not (file-exists-p dvi-name)) (error "Can not find %s !" dvi-name)
1389           (message "Starting xdvi with %s" dvi-name)
1390           (setq xdvi-process (apply 'start-process
1391                                     (append '("xdvi-for-latex" nil "xdvi")
1392                                             ff/xdvi-for-latex-options
1393                                             (list dvi-name))))
1394           (process-kill-without-query xdvi-process))))
1395     ))
1396
1397 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1398 ;; Tex mode
1399
1400 ;; When working on a tex file with other people, I can just change
1401 ;; ff/tex-command in the -*- part of the file so that I don't mess up
1402 ;; other's people configuration.
1403
1404 (defadvice tex-file (around ff/set-my-own-tex-command () activate)
1405   (let ((tex-command
1406          (or (and (boundp 'ff/tex-command)
1407                   ff/tex-command)
1408              tex-command)))
1409     ad-do-it))
1410
1411 ;; This is a bit hardcore, but really I can't bear the superscripts in
1412 ;; my emacs window and could not find another way to deactivate them.
1413
1414 (load "tex-mode")
1415 (defun tex-font-lock-suscript (pos) ())
1416
1417 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1418 ;; Prevents many errors from beeping and makes the others play a nifty
1419 ;; sound
1420 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1421
1422 (defun ff/ring-bell ()
1423   (unless (memq this-command
1424                 '(isearch-abort
1425                   abort-recursive-edit
1426                   exit-minibuffer
1427                   keyboard-quit
1428                   backward-delete-char-untabify
1429                   delete-backward-char
1430                   minibuffer-complete-and-exit
1431                   previous-line next-line
1432                   backward-char forward-char
1433                   scroll-up scroll-down
1434                   enlarge-window-horizontally shrink-window-horizontally
1435                   enlarge-window shrink-window
1436                   minibuffer-complete
1437                   ))
1438     ;; (message "command [%s]" (prin1-to-string this-command))
1439     ;; (ff/play-sound-async "~/local/sounds/short_la.wav")
1440     ))
1441
1442 (setq ring-bell-function 'ff/ring-bell)
1443
1444 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1445 ;; Past the content of the url currently in the kill-ring with
1446 ;; shift-click 2
1447 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1448
1449 (defun ff/insert-url (&optional url)
1450   "Downloads an URL with lynx and inserts it after the point."
1451   (interactive "MUrl: ")
1452   (when url
1453     (message "Inserting %s" url)
1454     (insert (concat "from: " url "\n\n"))
1455     ;; (call-process "lynx" nil t nil "-nolist" "-dump" url))
1456     (call-process "w3m" nil t nil "-dump" url))
1457   )
1458
1459 (define-key global-map [(shift mouse-2)]
1460   (lambda () (interactive) (ff/insert-url (current-kill 0))))
1461
1462 ;; lookup-dict is one of my own scripts, check my web page
1463
1464 (when (ff/load-or-alert "lookup-dict" t)
1465   (define-key global-map [(control \?)] 'lookup-dict))
1466
1467 ;; (defun ff/generate-password () (interactive)
1468 ;; (let ((c "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-"))
1469 ;; (nth (random (length c)) c))
1470
1471 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1472 ;; Automatization of things I do often
1473 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1474
1475 (defun ff/snip () (interactive)
1476        (let ((start (condition-case nil (region-beginning) (error (point))))
1477              (end (condition-case nil (region-end) (error (point)))))
1478          (goto-char end)
1479          (insert "----------------------------- snip snip -----------------------------\n")
1480          (goto-char start)
1481          (insert "----------------------------- snip snip -----------------------------\n")
1482          ))
1483
1484 (defun ff/start-latex ()
1485   "Adds all that stuff to start a new LaTeX document."
1486   (interactive)
1487   (goto-char (point-min))
1488   (insert "%% -*- mode: latex; mode: reftex; mode: flyspell; coding: utf-8; tex-command: \"pdflatex.sh\" -*-
1489
1490 \\documentclass[12pt,a4paper,twoside]{article}
1491 \\usepackage[a4paper,top=2.5cm,bottom=2cm,left=2.5cm,right=2.5cm]{geometry}
1492 \\usepackage[utf8]{inputenc}
1493 \\usepackage{amsmath}
1494 \\usepackage{amssymb}
1495 \\usepackage[pdftex]{graphicx}
1496 \\usepackage{microtype}
1497 \\usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue,citecolor=blue]{hyperref}
1498
1499 \\setlength{\\parindent}{0cm}
1500 \\setlength{\\parskip}{12pt}
1501 \\renewcommand{\\baselinestretch}{1.3}
1502
1503 \\def\\argmax{\\operatornamewithlimits{argmax}}
1504 \\def\\argmin{\\operatornamewithlimits{argmin}}
1505
1506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1507 %% Open sans font
1508 %%\\usepackage[default]{opensans}
1509 %%\\usepackage{cmbright}
1510 %%\\renewcommand{\\familydefault}{fos}
1511 %%\\renewcommand{\\seriesdefault}{l}
1512 %%\\renewcommand{\\bfdefault}{sb}
1513 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1514 %% The \\todo command
1515 \\newcounter{nbdrafts}
1516 \\setcounter{nbdrafts}{0}
1517 \\makeatletter
1518 \\newcommand{\\checknbdrafts}{
1519 \\ifnum \\thenbdrafts > 0
1520 \\@latex@warning@no@line{*WARNING* The document contains \\thenbdrafts \\space draft note(s)}
1521 \\fi}
1522 \\newcommand{\\todo}[1]{\\addtocounter{nbdrafts}{1}{\\color{red} #1}}
1523 \\makeatother
1524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1525
1526 \\begin{document}
1527
1528 ")
1529   (save-excursion
1530     (goto-char (point-max))
1531     (insert "
1532
1533 \\end{document}
1534 "))
1535   (latex-mode))
1536
1537 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1538
1539 (defun ff/add-copyrights ()
1540   "Adds two lines for the (C) at the beginning of current buffer."
1541   (interactive)
1542
1543   (let ((comment-style 'plain))
1544
1545     (goto-char (point-min))
1546
1547     ;; If this is a script, put the copyrights after the first line
1548
1549     (when (re-search-forward "^#!" nil t)
1550       (beginning-of-line)
1551       (next-line 1))
1552
1553     (let ((start (point))
1554           (comment-style 'box))
1555       (insert
1556        (concat
1557
1558         "\nSTART_IP_HEADER\n"
1559
1560         (when (boundp 'user-full-name)
1561           (concat "\nWritten by " user-full-name "\n"))
1562
1563         (when (boundp 'user-mail-address)
1564           (concat "Contact <" user-mail-address "> for comments & bug reports\n"))
1565
1566         "\nEND_IP_HEADER\n"
1567         ))
1568
1569       (comment-region start (point)))
1570
1571     ))
1572
1573 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1574
1575 (defun ff/remove-ip-header () (interactive)
1576        (save-excursion
1577          (goto-char (point-min))
1578          (when (and (re-search-forward "START_IP_HEADER" nil t)
1579                     (re-search-forward "END_IP_HEADER" nil t))
1580            (message "yep"))
1581          ))
1582
1583 (defun ff/add-gpl ()
1584   "Adds the GPL statements at the beginning of current buffer."
1585   (interactive)
1586   (let ((comment-style 'box)
1587         (gpl
1588          (concat
1589
1590           ;;           "
1591           ;; This program is free software; you can redistribute it and/or
1592           ;; modify it under the terms of the GNU General Public License
1593           ;; version 2 as published by the Free Software Foundation.
1594
1595           ;; This program is distributed in the hope that it will be useful, but
1596           ;; WITHOUT ANY WARRANTY\; without even the implied warranty of
1597           ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1598           ;; General Public License for more details.
1599           ;; "
1600
1601           "
1602 START_IP_HEADER
1603
1604 This program is free software: you can redistribute it and/or modify
1605 it under the terms of the version 3 of the GNU General Public License
1606 as published by the Free Software Foundation.
1607
1608 This program is distributed in the hope that it will be useful, but
1609 WITHOUT ANY WARRANTY; without even the implied warranty of
1610 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1611 General Public License for more details.
1612
1613 You should have received a copy of the GNU General Public License
1614 along with this program. If not, see <http://www.gnu.org/licenses/>.
1615
1616 "
1617           (when (boundp 'user-full-name)
1618             (concat "Written by and Copyright (C) " user-full-name "\n"))
1619
1620           (when (boundp 'user-mail-address)
1621             (concat "Contact <" user-mail-address "> for comments & bug reports\n"))
1622
1623           "
1624 END_IP_HEADER
1625 "
1626
1627           )))
1628
1629     (goto-char (point-min))
1630
1631     ;; If this is a script, put the gpl after the first line
1632     (when (re-search-forward "^#!" nil t)
1633       (beginning-of-line)
1634       (next-line 1))
1635
1636     (let ((start (point)))
1637       (insert gpl)
1638       (comment-region start (point)))
1639     ))
1640
1641 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1642
1643 (defun ff/start-c ()
1644   "Adds the header to start a C program."
1645   (interactive)
1646   ;;   (beginning-of-buffer)
1647   (insert
1648    "
1649 #include <stdio.h>
1650 #include <stdlib.h>
1651
1652 int main(int argc, char **argv) {
1653   exit(EXIT_SUCCESS);
1654 }
1655 ")
1656   (previous-line 2)
1657   )
1658
1659 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1660
1661 (defun ff/start-c++ ()
1662   "Adds the header to start a C++ program."
1663   (interactive)
1664   ;;   (beginning-of-buffer)
1665   (insert
1666    "
1667 #include <iostream>
1668 #include <fstream>
1669 #include <cmath>
1670 #include <stdio.h>
1671 #include <stdlib.h>
1672
1673 using namespace std;
1674
1675 int main(int argc, char **argv) {
1676
1677 }
1678 ")
1679   (previous-line 2)
1680   )
1681
1682 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1683
1684 (defun ff/headerize ()
1685   "Adds the #define HEADER_H, etc."
1686   (interactive)
1687   (let ((flag-name (replace-regexp-in-string
1688                     "[\. \(\)]" "_"
1689                     (upcase (file-name-nondirectory (buffer-file-name))))))
1690     (goto-char (point-max))
1691     (insert "\n#endif\n")
1692     (goto-char (point-min))
1693     (insert (concat "#ifndef " flag-name "\n"))
1694     (insert (concat "#define " flag-name "\n"))
1695     )
1696   )
1697
1698 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1699
1700 (defun ff/start-html ()
1701   "Adds all that stuff to start a new HTML file."
1702   (interactive)
1703   (goto-char (point-min))
1704   (insert "<?xml version=\"1.0\" encoding=\"utf-8\"?>
1705 <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
1706
1707 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
1708
1709 <head>
1710 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
1711 <title></title>
1712 <style type=\"text/css\">
1713 p {
1714  color:#009900;
1715 }
1716 </style>
1717 </head>
1718
1719 <body>
1720 ")
1721   (goto-char (point-max))
1722   (insert "
1723 </body>
1724
1725 </html>
1726 ")
1727   (html-mode))
1728
1729 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1730
1731 ;; Insert a line showing all the variables written on the current line
1732 ;; and separated by commas
1733
1734 (defun ff/cout-var (arg)
1735   "Invoked on a line with a list of variables names,
1736 it inserts a line which displays their values in cout, or cerr if
1737 the function is invoked with a universal arg"
1738   (interactive "P")
1739   (let ((line (if arg "cerr" "cout")))
1740     (goto-char (point-at-bol))
1741     ;; Regexp syntax sucks moose balls, honnest. To match '[', just
1742     ;; put it as the first char in the [...] ... This leads to some
1743     ;; obvious things like the following
1744     (while (re-search-forward "\\([][a-zA-Z0-9_.:\(\)]+\\)" (point-at-eol) t)
1745       (setq line
1746             (concat line " << \" "
1747                     (match-string 1) " = \" << " (match-string 1))))
1748     (goto-char (point-at-bol))
1749     (kill-line)
1750     (insert line " << endl\;\n")
1751     (indent-region (point-at-bol 0) (point-at-eol 0) nil)
1752     ))
1753
1754 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1755
1756 (defun ff/clean-article ()
1757   "Cleans up an article by removing the leading blanks on each line
1758 and refilling all the paragraphs."
1759   (interactive)
1760   (let ((fill-column 92))
1761     (goto-char (point-min))
1762     (while (re-search-forward "^\\ +" nil t)
1763       (replace-match "" nil nil))
1764     (fill-individual-paragraphs (point-min) (point-max) t)))
1765
1766 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1767
1768 (defun ff/start-slide ()
1769   (interactive)
1770   (insert "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1771
1772 \\begin{frame}{")
1773
1774   (save-excursion (insert "}{}
1775
1776 \\end{frame}
1777
1778 "))
1779   )
1780
1781 (add-hook
1782  'latex-mode-hook
1783  (lambda ()
1784    (define-key latex-mode-map [(meta S)] 'ff/start-slide)
1785    (define-key latex-mode-map [(control c) (control a)] 'align-current)
1786    (define-key latex-mode-map [(control end)] 'tex-close-latex-block)
1787    (define-key latex-mode-map [(control tab)] 'ispell-complete-word)
1788    (copy-face 'default 'tex-verbatim)
1789    ;; (ff/configure-faces '((tex-verbatim :background "gray95")))
1790    ))
1791
1792 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1793
1794 (defun ff/start-test-code ()
1795   (interactive)
1796   (let ((start (point)))
1797     (insert "
1798 { // ******************************* START ***************************
1799 #warning Test code added on "
1800             (format-time-string "%04Y %b %02d %02H:%02M:%02S" (current-time))
1801             "
1802
1803 } // ******************************** END ****************************
1804
1805 ")
1806     (indent-region start (point) nil))
1807   (previous-line 3)
1808   (c-indent-command))
1809
1810 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1811
1812 (defun ff/code-to-html () (interactive)
1813        (save-restriction
1814          (narrow-to-region (region-beginning) (region-end))
1815          (replace-string "\"" "&quot;" nil (point-min) (point-max))
1816          (replace-string " " "&nbsp;" nil (point-min) (point-max))
1817          (replace-string ">" "&gt;" nil (point-min) (point-max))
1818          (replace-string "<" "&lt;" nil (point-min) (point-max))
1819          (replace-string "\e" "^[" nil (point-min) (point-max))
1820          (replace-string "\7f" "^?" nil (point-min) (point-max))
1821          (replace-string "\1f" "^_" nil (point-min) (point-max))
1822          (replace-regexp "$" "<br />" nil (point-min) (point-max))
1823          )
1824        )
1825
1826 (defun ff/downcase-html-tags () (interactive)
1827        (save-excursion
1828          (beginning-of-buffer)
1829          (while (re-search-forward "<\\([^>]+\\)>" nil t)
1830            (downcase-region (match-beginning 1) (match-end 1)))
1831          )
1832        )
1833
1834 ;; If we enter html mode and there is no makefile around, create a
1835 ;; compilation command with tidy (this is cool stuff)
1836
1837 (add-hook 'html-mode-hook
1838           (lambda ()
1839             (unless (or (not (buffer-file-name))
1840                         (file-exists-p "makefile")
1841                         (file-exists-p "Makefile"))
1842               (set (make-local-variable 'compile-command)
1843                    (let ((fn (file-name-nondirectory buffer-file-name)))
1844                      (format "tidy -utf8 %s > /tmp/%s" fn fn))))))
1845
1846 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1847
1848 (defun ff/count-words-region (beginning end)
1849   "Print number of words in the region.
1850 Words are defined as at least one word-constituent character
1851 followed by at least one character that is not a
1852 word-constituent.  The buffer's syntax table determines which
1853 characters these are."
1854
1855   (interactive "r")
1856   (message "Counting words in region ... ")
1857   (save-excursion
1858     (goto-char beginning)
1859     (let ((count 0))
1860       (while (< (point) end)
1861         (re-search-forward "\\w+\\W+")
1862         (setq count (1+ count)))
1863       (cond ((zerop count) (message "The region does NOT have any word."))
1864             ((= 1 count) (message "The region has 1 word."))
1865             (t (message "The region has %d words." count))))))
1866
1867 ;; (add-hook 'html-mode-hook 'flyspell-mode)
1868
1869 (defun ff/tidy-html ()
1870   "Run tidy in on the content of the current buffer, put the result in
1871 a file in /tmp"
1872   (interactive)
1873   (call-process-region (point-min) (point-max)
1874                        "/usr/bin/tidy"
1875                        nil
1876                        (list nil (make-temp-file "/tmp/tidy-html."))))
1877
1878 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1879
1880 ;; Create the adequate embryo of a file if it does not exist
1881
1882 (defun ff/start-file () (interactive)
1883        (let ((filename (buffer-file-name)))
1884          (when filename
1885
1886            (when (string-match "\\.sh$" filename)
1887              (sh-mode)
1888              (insert "#!/bin/bash\n\nset -e\nset -o pipefail\n\n")
1889              (save-excursion
1890                (ff/add-copyrights))
1891              )
1892
1893            (when (string-match "\\.html$" filename)
1894              (html-mode)
1895              (ff/start-html)
1896              (previous-line 4)
1897              )
1898
1899            (when (string-match "\\.h$" filename)
1900              (c++-mode)
1901              (ff/headerize)
1902              (save-excursion
1903                (ff/add-copyrights)
1904                (newline))
1905              (newline)
1906              (newline)
1907              (previous-line 1)
1908              )
1909
1910            (when (string-match "\\.c$" filename)
1911              (c-mode)
1912              (ff/add-copyrights)
1913              (ff/start-c))
1914
1915            (when (string-match "\.\\(cc\\|cpp\\)$" filename)
1916              (c++-mode)
1917              (ff/add-copyrights)
1918              (let ((headername  (replace-regexp-in-string "\\.\\(cc\\|cpp\\)$" ".h"
1919                                                           filename)))
1920                (if (file-exists-p headername)
1921                    (insert (concat "\n#include \"" (file-name-nondirectory headername) "\"\n"))
1922                  (ff/start-c++))
1923                ))
1924
1925            (when (string-match "\\.tex$" filename)
1926              (latex-mode)
1927              (ff/start-latex)
1928              ))
1929          )
1930        (set-buffer-modified-p nil)
1931        )
1932
1933 (if (>= emacs-major-version 22)
1934     (add-to-list 'find-file-not-found-functions 'ff/start-file)
1935   (add-to-list 'find-file-not-found-hooks 'ff/start-file))
1936
1937 (when (>= emacs-major-version 24)
1938   (define-obsolete-function-alias 'make-local-hook 'ignore "21.1")
1939   (setq send-mail-function 'sendmail-send-it) ;; emacs 24.x stuff
1940
1941   (custom-set-faces
1942    '(diff-added ((default (:background "gray90" :foreground "green4" :weight bold))))
1943    '(diff-removed ((default (:background "gray90" :foreground "red2" :weight bold))))
1944    '(diff-changed ((default (:background "gray90" :foreground "blue" :weight bold))))
1945    )
1946   )
1947
1948 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1949
1950 (define-key global-map [f8] 'ff-find-other-file)
1951 (define-key global-map [(shift f8)] (lambda () (interactive) (ff-find-other-file t)))
1952
1953 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1954 ;; Antiword, htmlize and boxquote
1955 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1956
1957 (autoload 'no-word "no-word")
1958 (add-to-list 'auto-mode-alist '("\\.doc\\'" . no-word))
1959 ;; (add-to-list 'auto-mode-alist '("\\.DOC\\'" . no-word))
1960
1961 (autoload 'htmlize-buffer "htmlize" nil t)
1962
1963 (setq boxquote-top-and-tail "------------------")
1964 (autoload 'boxquote-region "boxquote" nil t)
1965
1966 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1967 ;; The compilation hacks
1968 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1969
1970 ;; If we enter c++ mode and there is no makefile around, we create a
1971 ;; make command on the fly for the specific object file
1972
1973 (add-hook 'c++-mode-hook
1974           (lambda ()
1975             (unless (or (file-exists-p "makefile") (file-exists-p "Makefile"))
1976               (set (make-local-variable 'compile-command)
1977                    (concat
1978                     "make -k "
1979                     (file-name-sans-extension
1980                      (file-name-nondirectory buffer-file-name)))))))
1981
1982 ;; <f1> runs the compilation according to the compile-command (and
1983 ;; thus does not ask any confirmation), shows the compilation buffer
1984 ;; during compilation and delete all windows showing the compilation
1985 ;; buffer if the compilation ends with no error
1986
1987 ;; <shift-f1> asks for a compilation command and runs the compilation
1988 ;; but does not restore the window configuration (i.e. the compilation
1989 ;; buffer's window will still be visible, as usual)
1990
1991 ;; <f2> goes to the next compilation error (as C-x ` does on the
1992 ;; standard configuration)
1993
1994 (defun ff/restore-windows-if-no-error (buffer msg)
1995   "Delete the windows showing the compilation buffer if msg
1996   matches \"^finished\"."
1997
1998   (when (string-match "^finished" msg)
1999     ;;     (delete-windows-on buffer)
2000     (if (boundp 'ff/window-configuration-before-compilation)
2001         (set-window-configuration ff/window-configuration-before-compilation))
2002     )
2003   )
2004
2005 (add-to-list 'compilation-finish-functions 'ff/restore-windows-if-no-error)
2006
2007 (defun ff/fast-compile ()
2008   "Compiles without asking anything."
2009   (interactive)
2010   (let ((compilation-read-command nil))
2011     (setq ff/window-configuration-before-compilation (current-window-configuration))
2012     (compile compile-command)))
2013
2014 (setq compilation-read-command t
2015       compile-command "make -j -k"
2016       compile-history '("make clean" "make DEBUG=yes -j -k" "make -j -k")
2017       )
2018
2019 (defun ff/universal-compile () (interactive)
2020        (funcall (or (cdr (assoc major-mode
2021                                 '(
2022                                   (latex-mode . tex-file)
2023                                   (html-mode . browse-url-of-buffer)
2024                                   ;; Here you can add other mode -> compile command
2025                                   )))
2026                     'ff/fast-compile         ;; And this is the failsafe
2027                     )))
2028
2029 (define-key global-map [f1] 'ff/universal-compile)
2030 (define-key global-map [(shift f1)] 'compile)
2031 (define-key global-map [f2] 'next-error)
2032
2033 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2034 ;; Related to mail
2035 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2036
2037 ;; (when (ff/load-or-alert "flyspell-timer" t)
2038 ;;   (add-hook 'flyspell-mode-hook 'flyspell-timer-ensure-idle-timer))
2039
2040 (defun ff/start-flyspell () (interactive)
2041        (ff/configure-faces
2042         '(
2043           ;; (flyspell-incorrect :background "#ff0000" :foreground "black")
2044           ;; (flyspell-duplicate :background "#ff9000" :foreground "black")
2045           (flyspell-incorrect :foreground "#ff0000" :weight 'bold)
2046           (flyspell-duplicate :foreground "#ff9000" :weight 'bold)
2047           ))
2048        ;; (flyspell-buffer)
2049        )
2050
2051 (add-hook 'flyspell-mode-hook 'ff/start-flyspell)
2052
2053 (defun ff/pick-dictionnary () (interactive)
2054        (when (and (boundp 'flyspell-mode) flyspell-mode)
2055          (if (and current-input-method (string-match "latin" current-input-method))
2056              (ispell-change-dictionary "francais")
2057            (ispell-change-dictionary "american"))
2058          ;;     (flyspell-buffer)
2059          )
2060        )
2061
2062 (defadvice toggle-input-method (after ff/switch-dictionnary nil activate)
2063   (ff/pick-dictionnary))
2064
2065 ;; (add-hook 'message-mode-hook 'auto-fill-mode)
2066 ;; (add-hook 'message-mode-hook 'flyspell-mode)
2067
2068 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2069 ;; Delete all windows which are in the same "column", which means
2070 ;; whose xmin and xmax are bounded by the xmin and xmax of the
2071 ;; currently selected column
2072 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2073
2074 ;; This is from emacs23 ! better than my old ff/delete-other-windows-in-column
2075
2076 (unless (fboundp 'delete-other-windows-vertically)
2077
2078   (defun delete-other-windows-vertically (&optional window)
2079     "Delete the windows in the same column with WINDOW, but not WINDOW itself.
2080 This may be a useful alternative binding for \\[delete-other-windows]
2081  if you often split windows horizontally."
2082     (interactive)
2083     (let* ((window (or window (selected-window)))
2084            (edges (window-edges window))
2085            (w window) delenda)
2086       (while (not (eq (setq w (next-window w 1)) window))
2087         (let ((e (window-edges w)))
2088           (when (and (= (car e) (car edges))
2089                      (= (caddr e) (caddr edges)))
2090             (push w delenda))))
2091       (mapc 'delete-window delenda)))
2092   )
2093
2094 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2095 ;; Misc things
2096 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2097
2098 ;; Entropy is cool
2099
2100 (defun ff/entropy (l)
2101   (apply '+
2102          (mapcar
2103           (lambda (x)
2104             (if (= x 0.0) 0.0
2105               (* (- x) (/ (log x) (log 2)))))
2106           l)
2107          )
2108   )
2109
2110 ;; Usefull to deal with results in latex files
2111
2112 (defun ff/round-floats-in-region () (interactive)
2113        (save-restriction
2114          (condition-case nil
2115              (narrow-to-region (region-beginning) (region-end))
2116            (error (thing-at-point 'word)))
2117          (save-excursion
2118            (goto-char (point-min))
2119            (while (re-search-forward "[0-9\.]+" nil t)
2120              (let ((value (string-to-number (buffer-substring (match-beginning 0) (match-end 0)))))
2121                (delete-region (match-beginning 0) (match-end 0))
2122                (insert (format "%0.2f" value)))))))
2123
2124 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2125 ;; Keymaping
2126 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2127
2128 (load "info" nil t)
2129
2130 (define-key global-map [(shift iso-lefttab)] 'ispell-complete-word)
2131 ;; shift-tab going backward is kind of standard
2132 (define-key Info-mode-map [(shift iso-lefttab)] 'Info-prev-reference)
2133
2134 ;; (define-key global-map [(control x) (control a)] 'auto-fill-mode)
2135
2136 ;; Put back my keys, you thief!
2137 (define-key global-map [(home)] 'beginning-of-buffer)
2138 (define-key global-map [(end)] 'end-of-buffer)
2139 ;; (define-key global-map [(insertchar)] 'overwrite-mode)
2140 (define-key global-map [(delete)] 'delete-char)
2141
2142 ;; Cool shortcuts to move to the end / beginning of block keen
2143 (define-key global-map [(control right)] 'forward-sexp)
2144 (define-key global-map [(control left)] 'backward-sexp)
2145
2146 ;; Wheel mouse moves up and down 2 lines (and DO NOT BEEP when we are
2147 ;; out of the buffer)
2148
2149 (define-key global-map [mouse-4]
2150   (lambda () (interactive) (condition-case nil (scroll-down 2) (error nil))))
2151 (define-key global-map [mouse-5]
2152   (lambda () (interactive) (condition-case nil (scroll-up 2) (error nil))))
2153
2154 ;; with shift it goes faster
2155 (define-key global-map [(shift mouse-4)]
2156   (lambda () (interactive) (condition-case nil (scroll-down 50) (error nil))))
2157 (define-key global-map [(shift mouse-5)]
2158   (lambda () (interactive) (condition-case nil (scroll-up 50) (error nil))))
2159
2160 ;; Meta-? shows the properties of the character at point
2161 (define-key global-map [(meta ??)]
2162   (lambda () (interactive)
2163     (message (prin1-to-string (text-properties-at (point))))))
2164
2165 ;; Compiles the latex file in the current buffer
2166
2167 (setq tex-start-commands "\\input")
2168 (define-key global-map [f3] 'tex-file)
2169 (define-key global-map [(shift f3)] 'tex-bibtex-file)
2170
2171 ;; To run xdvi on the dvi associated to the .tex in the current
2172 ;; buffer, and to edit the .fig or bitmap image used to generate the
2173 ;; .eps at point
2174
2175 (define-key global-map [f4] 'ff/run-viewer)
2176
2177 ;; Closes the current \begin{}
2178
2179 ;; Meta-/ remaped (completion)
2180
2181 (define-key global-map [(shift right)] 'dabbrev-expand)
2182 (define-key global-map [(meta =)] 'dabbrev-expand)
2183
2184 ;; Change the current window.
2185
2186 (defun ff/next-same-frame-window () (interactive)
2187        (select-window (next-window (selected-window)
2188                                    (> (minibuffer-depth) 0)
2189                                    nil)))
2190
2191 (defun ff/previous-same-frame-window () (interactive)
2192        (select-window (previous-window (selected-window)
2193                                        (> (minibuffer-depth) 0)
2194                                        nil)))
2195
2196 (define-key global-map [(shift prior)] 'ff/next-same-frame-window)
2197 (define-key global-map [(shift next)] 'ff/previous-same-frame-window)
2198
2199 (define-key global-map [(control })] 'enlarge-window-horizontally)
2200 (define-key global-map [(control {)] 'shrink-window-horizontally)
2201 (define-key global-map [(control \")] 'enlarge-window)
2202 (define-key global-map [(control :)] 'shrink-window)
2203
2204 ;; (define-key global-map [(control shift prior)] 'next-multiframe-window)
2205 ;; (define-key global-map [(control shift next)] 'previous-multiframe-window)
2206
2207 ;; I have two screens sometime!
2208 ;; (define-key global-map [(meta next)] 'other-frame)
2209 ;; (define-key global-map [(meta prior)] (lambda () (interactive) (other-frame -1)))
2210
2211 ;; (load "winner")
2212 (winner-mode 1)
2213 ;; (define-key global-map [(shift backspace)] 'winner-undo)
2214
2215 ;; (define-key global-map [(shift home)] 'delete-other-windows-vertically)
2216 ;; (define-key global-map [(control +)] 'enlarge-window)
2217 ;; (define-key global-map [(control -)] 'shrink-window)
2218 ;; Goes to next/previous buffer
2219 ;; (define-key global-map [(control prior)] 'ff/next-buffer)
2220 ;; (define-key global-map [(control next)] 'ff/prev-buffer)
2221
2222 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2223 ;; If M-. on a symbol, show where it is defined in another window
2224 ;; without giving focus, cycle if repeated.
2225 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2226
2227 (when (ff/load-or-alert "etags")
2228
2229   (defun ff/find-tag-nofocus () (interactive)
2230          "Show in another window the definition of the current tag"
2231          (let ((tag (find-tag-default)))
2232            (display-buffer (find-tag-noselect tag (string= tag last-tag)))
2233            (message "Tag %s" tag)
2234            )
2235          )
2236
2237   (define-key global-map [(meta .)] 'ff/find-tag-nofocus)
2238   )
2239
2240 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2241 ;; Destroys the current buffer and its window if it's not the only one
2242 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2243
2244 (defcustom ff/kill-this-buffer-and-delete-window-exceptions ""
2245   "*Regexp matching the buffer names which have to be kept when using
2246 `ff/kill-this-buffer-and-delete-window'.")
2247
2248 (defun ff/kill-this-buffer-and-delete-window (universal)
2249   "Unless its name matches
2250 `ff/kill-this-buffer-and-delete-window-exceptions', kills the
2251 current buffer and deletes the current window if it's not the
2252 only one in the frame. If the buffer has to be kept, go to the
2253 next one. With universal argument, kill all killable buffers."
2254   (interactive "P")
2255   (if universal
2256       (let ((nb-killed 0))
2257         (mapc (lambda (x)
2258                 (unless (string-match ff/kill-this-buffer-and-delete-window-exceptions
2259                                       (buffer-name x))
2260                   (kill-buffer x)
2261                   (setq nb-killed (1+ nb-killed))
2262                   ))
2263               (buffer-list))
2264         (message "Killed %d buffer%s" nb-killed (if (> nb-killed 1) "s" "")))
2265     (if (string-match ff/kill-this-buffer-and-delete-window-exceptions (buffer-name))
2266         (ff/next-buffer)
2267       (kill-this-buffer)))
2268   (unless (one-window-p t) (delete-window))
2269   )
2270
2271 (define-key global-map [(control backspace)] 'ff/kill-this-buffer-and-delete-window)
2272 ;; (define-key calc-mode-map [(control backspace)] 'calc-quit)
2273
2274
2275 (setq ff/kill-this-buffer-and-delete-window-exceptions
2276       "^ \\|\\*Messages\\*\\|\\*scratch\\*\\|\\*Group\\*\\|\\*-jabber-\\*\\|\\*-jabber-process-\\*\\|\\*media\\*")
2277
2278 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2279 ;; Misc stuff
2280 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2281
2282 (defun ff/elisp-debug-on ()
2283   "Switches `debug-on-error' and `debug-on-quit'."
2284   (interactive)
2285   (if debug-on-error
2286       (setq debug-on-error nil
2287             debug-on-quit nil)
2288     (setq debug-on-error t
2289           debug-on-quit t))
2290   (if debug-on-error
2291       (message "elisp debug on")
2292     (message "elisp debug off")))
2293
2294 (defun ff/create-dummy-buffer (&optional universal) (interactive "P")
2295        (find-file (concat "/tmp/" (ff/non-existing-filename "/tmp/" "dummy" "")))
2296        (text-mode)
2297        (if universal (ff/insert-url (current-kill 0)))
2298        (message "New dummy text-mode buffer"))
2299
2300 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2301 ;; Recentf to keep a list of recently visited files. I use it
2302 ;; exclusively with my selector.el
2303 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2304
2305 (load "recentf")
2306
2307 ;; If we just check for file-symlink-p, everytime we start emacs it
2308 ;; will check all the remote files listed in recentf-list, so we check
2309 ;; that they are not remote first
2310 (defun ff/file-not-remote-but-symlink (filename)
2311   (and (not (file-remote-p filename)) (file-symlink-p filename)))
2312
2313 (setq recentf-exclude (append recentf-exclude
2314                               '(
2315                                 ff/file-not-remote-but-symlink
2316                                 "enotes$" "secure-notes$" "media-playlists$"
2317                                 "bbdb$"
2318                                 "svn-commit.tmp$" ".git/COMMIT_EDITMSG$"
2319                                 "\.bbl$" "\.aux$" "\.toc$"
2320                                 ))
2321       recentf-max-saved-items 1000
2322       recentf-save-file (concat ff/emacs-dir "/recentf")
2323       )
2324
2325 (when (boundp 'recentf-keep) (add-to-list 'recentf-keep 'file-remote-p))
2326
2327 (recentf-mode 1)
2328
2329 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2330 ;; My front-end to mplayer
2331 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2332
2333 ;; (ff/compile-when-needed "media/mplayer")
2334 ;; (ff/compile-when-needed "media")
2335
2336 (when (ff/load-or-alert "media")
2337
2338   (unless window-system
2339     (ff/configure-faces
2340      '(
2341        (media/mode-string-face
2342         :foreground "blue4" :weight 'bold)
2343
2344        (media/current-tune-face
2345         :foreground "black" :background "yellow" :weight 'normal)
2346
2347        (media/instant-highlight-face
2348         :foreground "black" :background "orange" :weight 'normal)
2349        ))
2350     )
2351
2352   (define-key global-map [(meta \\)] 'media)
2353
2354   (setq media/expert t
2355         media/add-current-song-to-interrupted-when-killing t
2356         media/duration-to-history 30
2357         media/history-size 1000
2358         media/playlist-file (concat ff/emacs-dir "/media-playlists")
2359         media/mplayer/args '(
2360                              "-framedrop"
2361                              "-zoom"
2362                              "-cache" "512"
2363                              "-subfont-osd-scale" "3"
2364                              ;; "-stop-xscreensaver"
2365                              ;; "-osdlevel" "3"
2366                              )
2367         media/mplayer/timing-request-period 1.0
2368         )
2369   )
2370
2371 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2372 ;; A dynamic search
2373 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2374
2375 ;; selector.el is one of my own scripts, check my web page
2376
2377 (when (ff/load-or-alert "selector" t)
2378   ;; (define-key global-map [(shift return)] 'selector/quick-move-in-buffer)
2379   (define-key global-map [(control x) (control b)] 'selector/switch-buffer)
2380
2381   (defun ff/visit-debpkg-file (&optional regexp)
2382     "This function lists all the files found with dpkg -S and
2383 proposes to visit them."
2384     (interactive "sPattern: ")
2385
2386     (selector/select
2387
2388      (mapcar
2389       (lambda (s)
2390         (cons (selector/filename-to-string s) s))
2391       (split-string
2392        (shell-command-to-string (concat "dpkg -S " regexp " | awk '{print $2}'"))))
2393
2394      'selector/find-file
2395      "*selector find-file*"
2396      ))
2397   )
2398
2399 (add-hook 'selector/mode-hook (lambda () (setq truncate-lines t)))
2400
2401 (defun ff/selector-insert-record-callback (r)
2402   (bbdb-display-records (list r))
2403   ;; Weird things will happen if you kill the buffer from which you
2404   ;; invoked ff/selector-mail-from-bbdb
2405   (insert (car (elt r 6)))
2406   )
2407
2408 (defun ff/selector-compose-mail-callback (r)
2409   (vm-compose-mail (car (elt r 6)))
2410   )
2411
2412 (defun ff/selector-mail-from-bbdb () (interactive)
2413        (selector/select
2414         (mapcar
2415          (lambda (r) (cons (concat (elt r 0)
2416                                    " "
2417                                    (elt r 1)
2418                                    " ("
2419                                    (car (elt r 6))
2420                                    ")")
2421                            r))
2422          (bbdb-records))
2423         (if (string= mode-name "Mail")
2424             'ff/selector-insert-record-callback
2425           'ff/selector-compose-mail-callback)
2426         "*bbdb-search*"
2427         )
2428        )
2429
2430 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2431 ;; My script to automatically count the number of words and characters
2432 ;; between two markers
2433
2434 (ff/load-or-alert "text-counters.el")
2435
2436 ;; Display them in the modeline when in text-mode
2437
2438 (add-hook 'text-mode-hook 'tc/add-text-counters-in-modeline)
2439
2440 ;; (add-hook 'text-mode-hook
2441 ;; (lambda ()
2442 ;; (setq comment-start " > ")))
2443
2444 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2445 ;; A function to remove temporary alarm windows
2446 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2447
2448 (defcustom ff/annoying-windows-regexp
2449   "\\*Messages\\*\\|\\*compilation\\*\\|\\*tex-shell\\*\\|\\*Help\\*\\|\\*info\\*\\|\\*Apropos\\*\\|\\*BBDB\\*\\|\\*.*-diff\\*"
2450   "The regexp matching the windows to be deleted by `ff/delete-annoying-windows'"
2451   )
2452
2453 (defun ff/delete-annoying-windows ()
2454   "Close all the windows showing buffers whose names match
2455 `ff/annoying-windows-regexp'."
2456   (interactive)
2457   (when ff/annoying-windows-regexp
2458     (mapc (lambda (w)
2459             (when (and (not (one-window-p w))
2460                        (string-match ff/annoying-windows-regexp
2461                                      (buffer-name (window-buffer w))))
2462               (delete-window w)))
2463           (window-list)
2464           )
2465     (message "Removed annoying windows")
2466     )
2467   )
2468
2469 (setq ff/annoying-windows-regexp
2470       (concat ff/annoying-windows-regexp
2471               "\\|\\*unspooled mails\\*\\|\\*enotes alarms\\*\\|\\*system info\\*"))
2472
2473 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2474 ;; Some handy functions
2475 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2476
2477 (defun ff/twin-horizontal-current-buffer () (interactive)
2478        (delete-other-windows)
2479        (split-window-horizontally)
2480        (balance-windows)
2481        )
2482
2483 (defun ff/twin-vertical-current-buffer () (interactive)
2484        (delete-other-windows)
2485        (split-window-vertically)
2486        (balance-windows)
2487        )
2488
2489 (defun ff/flyspell-mode (arg) (interactive "p")
2490        (if flyspell-mode (flyspell-mode -1)
2491          (flyspell-mode 1)
2492          (flyspell-buffer))
2493        )
2494
2495 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2496 ;; The fridge!
2497 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2498
2499 (defun ff/move-region-to-fridge () (interactive)
2500        "Cut the current region, paste it in a file called ./fridge
2501 with a time tag, and save this file"
2502        (unless (use-region-p) (error "No region selected"))
2503        (let ((bn (file-name-nondirectory (buffer-file-name))))
2504          (kill-region (region-beginning) (region-end))
2505          (with-current-buffer (find-file-noselect "fridge")
2506            (goto-char (point-max))
2507            (insert "\n")
2508            (insert "######################################################################\n")
2509            (insert "\n"
2510                    (format-time-string "%Y %b %d %H:%M:%S" (current-time))
2511                    " (from "
2512                    bn
2513                    ")\n\n")
2514            (yank)
2515            (save-buffer)
2516            (message "Region moved to fridge")
2517            )
2518          )
2519        )
2520
2521 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2522 ;; My own keymap mapped to C-`
2523 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2524
2525 (setq ff/map (make-sparse-keymap))
2526 (define-key global-map [(control \`)] ff/map)
2527
2528 (unless window-system
2529   ;; (define-key global-map [(control @)] ff/map)
2530   (define-key global-map [(meta O) \`] ff/map)
2531   )
2532
2533 (define-key esc-map "`" ff/map)
2534
2535 (defun ff/git-status (&optional dir) (interactive)
2536        (if (buffer-file-name)
2537            (git-status (file-name-directory (buffer-file-name)))
2538          (error "No file attached to this buffer")))
2539
2540 (defun ff/insert-date (&optional universal) (interactive "P")
2541        ;; (insert (format-time-string "\n * %Y %b %d %H:%M:%S\n\n" (current-time)))
2542        ;; (insert (format-time-string "%Y %b %d %H:%M:%S" (current-time)))
2543        ;; (insert (format-time-string "%d.%m.%y" (current-time)))
2544        (if universal
2545            (insert (format-time-string "%d.%m.%Y %H:%M:%S" (current-time)))
2546          (insert (format-time-string "%d.%m.%Y" (current-time))))
2547        )
2548
2549 (define-key ff/map [(control g)] 'ff/git-status)
2550 (define-key ff/map [(control w)] 'server-edit)
2551 (define-key ff/map [(control d)] 'ff/elisp-debug-on)
2552 ;; (define-key ff/map "d" 'diary)
2553 (define-key ff/map "d" 'ff/insert-date)
2554 (define-key ff/map [(control \`)] 'ff/bash-new-buffer)
2555 (define-key ff/map [(control n)] 'enotes/show-all-notes)
2556 (define-key ff/map [(control s)] 'ff/secure-note-add)
2557 (define-key ff/map [(control t)] 'ff/start-test-code)
2558 (define-key ff/map [(control q)] 'ff/create-dummy-buffer)
2559 (define-key ff/map [(control a)] 'auto-fill-mode)
2560 (define-key ff/map [(control i)] 'ff/system-info)
2561 (define-key ff/map "w" 'ff/word-occurences)
2562 (define-key ff/map [(control c)] 'calendar)
2563 ;; (define-key ff/map [(control c)] (lambda () (interactive) (save-excursion (calendar))))
2564 (define-key ff/map [(control l)] 'goto-line)
2565 (define-key ff/map "l" 'longlines-mode)
2566 (define-key ff/map [(control o)] 'selector/quick-pick-recent)
2567 (define-key ff/map "s" 'selector/quick-move-in-buffer)
2568 (define-key ff/map "S" 'selector/search-sentence)
2569 (define-key ff/map "t" (lambda () (interactive) (find-file "~/private/TODO.txt")))
2570 (define-key ff/map "h" 'ff/tidy-html)
2571 (define-key ff/map "c" 'ff/count-char)
2572 (define-key ff/map [(control p)] 'ff/print-to-file)
2573 (define-key ff/map "P" 'ff/print-to-printer)
2574 (define-key ff/map [(control b)] 'bbdb)
2575 (define-key ff/map "m" 'ff/selector-mail-from-bbdb)
2576 (define-key ff/map [(control m)] 'woman)
2577 (define-key ff/map "b" 'bookmark-jump)
2578 (define-key ff/map [(control =)] 'calc)
2579 (define-key ff/map [(control shift b)]
2580   (lambda () (interactive)
2581     (bookmark-set)
2582     (bookmark-save)))
2583 (define-key ff/map "f" 'ff/move-region-to-fridge)
2584 (define-key ff/map [(control f)] 'ff/flyspell-mode)
2585
2586 (define-key ff/map [?\C-0] 'ff/delete-annoying-windows)
2587 (define-key ff/map "1" 'delete-other-windows)
2588 (define-key ff/map [?\C-1] 'delete-other-windows)
2589 (define-key ff/map "2" 'ff/twin-vertical-current-buffer)
2590 (define-key ff/map [?\C-2] 'ff/twin-vertical-current-buffer)
2591 (define-key ff/map "3" 'ff/twin-horizontal-current-buffer)
2592 (define-key ff/map [?\C-3] 'ff/twin-horizontal-current-buffer)
2593
2594 (define-key ff/map " " 'delete-trailing-whitespace)
2595
2596 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2597 ;; Hacks so that all keys are functionnal in xterm and through ssh.
2598 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2599
2600 (unless window-system
2601
2602   ;; One day I will understand these clipboard business. Until then,
2603   ;; so that it works in xterm (yes), let's use xclip. This is a bit
2604   ;; ugly.
2605
2606   ;; (defun ff/yank-with-xclip (&optional arg)
2607   ;; "Paste the content of the X clipboard with the xclip
2608   ;; command. Without ARG converts some of the '\\uxxxx' characters."
2609   ;; (interactive "P")
2610   ;; (with-temp-buffer
2611   ;; (shell-command "xclip -o" t)
2612   ;; (unless arg
2613   ;; (mapc (lambda (x) (replace-string (concat "\\u" (car x)) (cdr x) nil (point-min) (point-max)))
2614   ;; '(("fffd" . "??")
2615   ;; ("2013" . "-")
2616   ;; ("2014" . "--")
2617   ;; ("2018" . "`")
2618   ;; ("2019" . "'")
2619   ;; ("201c" . "``")
2620   ;; ("201d" . "''")
2621   ;; ("2022" . "*")
2622   ;; ("2026" . "...")
2623   ;; ("20ac" . "EUR")
2624   ;; )))
2625   ;; (kill-ring-save (point-min) (point-max)))
2626
2627   ;; (yank))
2628
2629   ;; (define-key global-map [(meta y)] 'ff/yank-with-xclip)
2630
2631   ;;   (set-terminal-coding-system 'iso-latin-1)
2632   ;; (set-terminal-coding-system 'utf-8)
2633
2634   ;; I have in my .Xressource
2635
2636   ;; XTerm.VT100.translations: #override\n\
2637   ;;   <Btn4Down>,<Btn4Up>:scroll-back(2,line)\n\
2638   ;;   <Btn5Down>,<Btn5Up>:scroll-forw(2,line)\n\
2639   ;;   Ctrl<Btn4Down>,Ctrl<Btn4Up>:scroll-back(1,page)\n\
2640   ;;   Ctrl<Btn5Down>,Ctrl<Btn5Up>:scroll-forw(1,page)\n\
2641   ;;   Shift<Btn4Down>,Shift<Btn4Up>:scroll-back(1,halfpage)\n\
2642   ;;   Shift<Btn5Down>,Shift<Btn5Up>:scroll-forw(1,halfpage)\n\
2643   ;;   Alt<KeyPress>:insert-eight-bit()\n\
2644   ;;   !Shift<Key>BackSpace: string("\7f")\n\
2645   ;;   Ctrl<Key>BackSpace: string("\eOZ")\n\
2646   ;;   Shift<Key>Prior: string("\e[5;2~")\n\
2647   ;;   Shift<Key>Next: string("\e[6;2~")\n\
2648   ;;   Shift Ctrl<Key>]: string("\eO}")\n\
2649   ;;   Shift Ctrl<Key>[: string("\eO{")\n\
2650   ;;   Shift Ctrl<Key>/: string("\eO?")\n\
2651   ;;   Ctrl<Key>/: string("\eO/")\n\
2652   ;;   Shift Ctrl<Key>=: string("\eO+")\n\
2653   ;;   Ctrl<Key>=: string("\eO=")\n\
2654   ;;   Shift Ctrl<Key>;: string("\eO:")\n\
2655   ;;   Ctrl<Key>;: string("\eO;")\n\
2656   ;;   Shift Ctrl<Key>`: string("\eO~")\n\
2657   ;;   Ctrl<Key>`: string("\eO`")\n\
2658   ;;   Shift Ctrl<Key>': string("\eO\\\"")\n\
2659   ;;   Ctrl<Key>': string("\eO'")\n\
2660   ;;   Shift Ctrl<Key>.: string("\eO>")\n\
2661   ;;   Ctrl<Key>.: string("\eO.")\n\
2662   ;;   Shift Ctrl<Key>\\,: string("\eO<")\n\
2663   ;;   Ctrl<Key>\\,: string("\eO,")
2664
2665   (define-key function-key-map "\e[2~" [insert])
2666
2667   (define-key function-key-map "\e[Z" [S-iso-lefttab])
2668
2669   (define-key function-key-map "\e[1;2A" [S-up])
2670   (define-key function-key-map "\e[1;2B" [S-down])
2671   (define-key function-key-map "\e[1;2C" [S-right])
2672   (define-key function-key-map "\e[1;2D" [S-left])
2673   (define-key function-key-map "\e[1;2F" [S-end])
2674   (define-key function-key-map "\e[1;2H" [S-home])
2675
2676   (define-key function-key-map "\e[2;2~" [S-insert])
2677   (define-key function-key-map "\e[5;2~" [S-prior])
2678   (define-key function-key-map "\e[6;2~" [S-next])
2679
2680   (define-key function-key-map "\e[1;2P" [S-f1])
2681   (define-key function-key-map "\e[1;2Q" [S-f2])
2682   (define-key function-key-map "\e[1;2R" [S-f3])
2683   (define-key function-key-map "\e[1;2S" [S-f4])
2684   (define-key function-key-map "\e[15;2~" [S-f5])
2685   (define-key function-key-map "\e[17;2~" [S-f6])
2686   (define-key function-key-map "\e[18;2~" [S-f7])
2687   (define-key function-key-map "\e[19;2~" [S-f8])
2688   (define-key function-key-map "\e[20;2~" [S-f9])
2689   (define-key function-key-map "\e[21;2~" [S-f10])
2690
2691   (define-key function-key-map "\e[1;5A" [C-up])
2692   (define-key function-key-map "\e[1;5B" [C-down])
2693   (define-key function-key-map "\e[1;5C" [C-right])
2694   (define-key function-key-map "\e[1;5D" [C-left])
2695   (define-key function-key-map "\e[1;5F" [C-end])
2696   (define-key function-key-map "\e[1;5H" [C-home])
2697
2698   (define-key function-key-map "\e[2;5~" [C-insert])
2699   (define-key function-key-map "\e[5;5~" [C-prior])
2700   (define-key function-key-map "\e[6;5~" [C-next])
2701
2702   (define-key function-key-map "\e[1;9A" [M-up])
2703   (define-key function-key-map "\e[1;9B" [M-down])
2704   (define-key function-key-map "\e[1;9C" [M-right])
2705   (define-key function-key-map "\e[1;9D" [M-left])
2706   (define-key function-key-map "\e[1;9F" [M-end])
2707   (define-key function-key-map "\e[1;9H" [M-home])
2708
2709   (define-key function-key-map "\e[2;9~" [M-insert])
2710   (define-key function-key-map "\e[5;9~" [M-prior])
2711   (define-key function-key-map "\e[6;9~" [M-next])
2712
2713   ;; The following ones are not standard
2714
2715   (define-key function-key-map "\eO}" (kbd "C-}"))
2716   (define-key function-key-map "\eO{" (kbd "C-{"))
2717   (define-key function-key-map "\eO?" (kbd "C-?"))
2718   (define-key function-key-map "\eO/" (kbd "C-/"))
2719   (define-key function-key-map "\eO:" (kbd "C-:"))
2720   (define-key function-key-map "\eO;" (kbd "C-;"))
2721   (define-key function-key-map "\eO~" (kbd "C-~"))
2722   (define-key function-key-map "\eO`" (kbd "C-\`"))
2723   (define-key function-key-map "\eO\"" (kbd "C-\""))
2724   (define-key function-key-map "\eO|" (kbd "C-|"))
2725   (define-key function-key-map "\eO'" (kbd "C-'"))
2726   (define-key function-key-map "\eO>" (kbd "C->"))
2727   (define-key function-key-map "\eO." (kbd "C-."))
2728   (define-key function-key-map "\eO<" (kbd "C-<"))
2729   (define-key function-key-map "\eO," (kbd "C-,"))
2730   (define-key function-key-map "\eO-" (kbd "C--"))
2731   (define-key function-key-map "\eO=" (kbd "C-="))
2732   (define-key function-key-map "\eO+" (kbd "C-+"))
2733
2734   (define-key function-key-map "\eOZ" [C-backspace])
2735
2736   (define-key minibuffer-local-map "\10" 'previous-history-element)
2737   (define-key minibuffer-local-map "\ e" 'next-history-element)
2738
2739   ;; (define-key global-map [(alt prior)] 'ff/prev-buffer)
2740   ;; (define-key global-map [(alt next)] 'ff/next-buffer)
2741
2742   )
2743
2744 ;; I am fed up with Alt-Backspace in the minibuffer erasing the
2745 ;; content of the kill-ring
2746
2747 (defun ff/backward-delete-word (arg)
2748   "Delete characters forward until encountering the end of a word, but do not put them in the kill ring.
2749 With argument ARG, do this that many times."
2750   (interactive "p")
2751   (delete-region (point) (progn (forward-word (- arg)) (point))))
2752
2753 (define-key minibuffer-local-map
2754   [remap backward-kill-word] 'ff/backward-delete-word)
2755
2756 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2757 ;; Privacy
2758 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2759
2760 ;; Where to save the bookmarks and where is bbdb
2761
2762 (setq bookmark-default-file (concat ff/emacs-dir "/bmk")
2763       bbdb-file "~/private/bbdb"
2764       custom-file (concat ff/emacs-dir "/custom"))
2765
2766 ;; enotes.el is one of my own scripts, check my web page
2767
2768 (when (ff/load-or-alert "enotes" t)
2769   (setq enotes/file "~/private/enotes"
2770         enotes/show-help nil
2771         enotes/full-display nil
2772         enotes/default-time-fields "9:30")
2773
2774   (enotes/init)
2775   ;; (add-hook 'enotes/alarm-hook
2776   ;;  (lambda () (ff/play-sound-async "~/local/sounds/three_notes2.wav")))
2777   )
2778
2779 ;; (when (ff/load-or-alert "goto-last-change.el")
2780 ;; (define-key global-map [(control x) (control a)] 'goto-last-change))
2781
2782 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2783 ;; My private stuff (email adresses, mail filters, etc.)
2784 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2785
2786 (ff/load-or-alert "~/private/emacs.perso.el" t)
2787
2788 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2789 ;; emacs server
2790 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2791
2792 ;; Runs in server mode, so that emacsclient works
2793 (server-start)
2794
2795 (defun ff/raise-frame-and-give-focus ()
2796   (when window-system
2797     (raise-frame)
2798     (x-focus-frame (selected-frame))
2799     (set-mouse-pixel-position (selected-frame) 4 4)
2800     ))
2801
2802 ;; Raises the window when the server is invoked
2803
2804 (add-hook 'server-switch-hook 'ff/raise-frame-and-give-focus)