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