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