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