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