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