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