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