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