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