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