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