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