Update.
[elisp.git] / emacs.el
1 ;; -*- mode: Emacs-Lisp; mode: rainbow; -*-
2
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4 ;; This program is free software; you can redistribute it and/or         ;;
5 ;; modify it under the terms of the GNU General Public License as        ;;
6 ;; published by the Free Software Foundation; either version 3, or (at   ;;
7 ;; your option) any later version.                                       ;;
8 ;;                                                                       ;;
9 ;; This program is distributed in the hope that it will be useful, but   ;;
10 ;; WITHOUT ANY WARRANTY; without even the implied warranty of            ;;
11 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      ;;
12 ;; General Public License for more details.                              ;;
13 ;;                                                                       ;;
14 ;; You should have received a copy of the GNU General Public License     ;;
15 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.  ;;
16 ;;                                                                       ;;
17 ;; Written by and Copyright (C) Francois Fleuret                         ;;
18 ;; Contact <francois@fleuret.org> for comments & bug reports             ;;
19 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20
21 ;; It's better to set the preferences in the .Xresources so that the
22 ;; window is not first displayed with the wrong options
23
24 ;; Emacs.menuBar:            off
25 ;; Emacs.verticalScrollBars: off
26 ;; Emacs.toolBar:            off
27 ;; Emacs.internalBorder:     1
28 ;; Emacs.FontBackend: xft
29 ;; Xft.dpi: 96
30 ;; Xft.hinting: true
31 ;; Xft.antialias: true
32 ;; Xft.rgba: rgb
33
34 (set-default-font "Inconsolata 15")
35
36 ;; (set-default-font "Bitstream vera sans mono-12")
37 ;; (set-default-font "Liberation Mono-13")
38 ;; (set-default-font "DejaVu sans mono 15")
39 ;; (set-default-font "Droid sans mono 13")
40 ;; (set-default-font "Opensans 10")
41
42 (when (fboundp 'horizontal-scroll-bar-mode)
43   (horizontal-scroll-bar-mode -1))
44
45 ;; This is where I put most of my emacs-related files
46 (setq ff/emacs-dir "~/private/emacs")
47 (unless (file-exists-p ff/emacs-dir)
48   (mkdir ff/emacs-dir t))
49
50 ;; Give the focus to the emacs window if we are under a windowing
51 ;; system
52
53 (when window-system
54   ;; (x-focus-frame nil)
55   (set-mouse-pixel-position (selected-frame) 4 4))
56
57 ;; Where I keep my own scripts
58
59 (add-to-list 'load-path "~/sources/gpl/elisp")
60 (add-to-list 'load-path "~/sources/elisp")
61 (add-to-list 'load-path "~/local/elisp")
62
63 ;; No, I do not like menus
64 (menu-bar-mode -1)
65
66 ;; Nor fringes
67 ;; (when (functionp 'fringe-mode) (fringe-mode '(0 . 0)))
68 ;; (when (functionp 'fringe-mode) (fringe-mode '(0 . 1)))
69 (when (functionp 'fringe-mode) (fringe-mode 10))
70
71 ;; And I do not like scrollbar neither
72 (when (functionp 'scroll-bar-mode) (scroll-bar-mode -1))
73
74 ;; Make all "yes or no" prompts be "y or n" instead
75 (fset 'yes-or-no-p 'y-or-n-p)
76
77 ;; The space bar acting as "yes" has been several times really
78 ;; problematic.
79 (define-key query-replace-map (kbd "SPC") nil)
80
81 ;; Show the matching parenthesis and do it immediately, we are in a
82 ;; hurry
83 (setq show-paren-delay 0)
84 (show-paren-mode t)
85
86 ;; use colorization for all modes
87 (global-font-lock-mode t)
88
89 (setq font-lock-maximum-decoration 3
90       ;;'((latex-mode . 2) (t . 2))
91       )
92
93 ;; Activate the dynamic completion of buffer names
94 ;; (iswitchb-mode 1)
95 ;; (load "lcomplete")
96
97 ;; Save the minibuffer history
98 (setq savehist-file (concat ff/emacs-dir "/savehist"))
99 (when (functionp 'savehist-mode) (savehist-mode 1))
100
101 ;; And allow minibuffer recursion
102 (setq enable-recursive-minibuffers t)
103 (minibuffer-depth-indicate-mode 1)
104
105 ;; I do not like tooltips
106 (when (functionp 'tooltip-mode) (tooltip-mode nil))
107
108 ;; Activate the dynamic completion in the mini-buffer
109 (icomplete-mode 1)
110
111 ;; (setq highlight-current-line-globally t
112 ;; highlight-current-line-ignore-regexp "Faces\\|Colors\\| \\*Mini\\|\\*media\\|INBOX")
113
114 ;; (highlight-current-line-minor-mode 1)
115 ;; (highlight-current-line-set-bg-color "gray75")
116
117 (defun ff/compile-when-needed (name)
118   "Compiles the given file only if needed. Adds .el if required, and
119 uses `load-path' to find it."
120   (if (not (string-match "\.el$" name))
121       (ff/compile-when-needed (concat name ".el"))
122     (mapc (lambda (dir)
123             (let* ((src (concat dir "/" name)))
124               (when (file-newer-than-file-p src (concat src "c"))
125                 (if (let ((byte-compile-verbose nil))
126                       (condition-case nil
127                           (byte-compile-file src)
128                         (error nil)))
129                     (message (format "Compiled %s" src ))
130                   (message (format "Failed compilation of %s" src))))))
131           load-path)))
132
133 ;; This is useful when using the same .emacs in many places
134
135 (defun ff/load-or-alert (name &optional compile-when-needed)
136   "Tries to load the specified file and insert a warning message in a
137 load-warning buffer in case of failure."
138
139   (when compile-when-needed (ff/compile-when-needed name))
140
141   (if (load name t nil) t
142     (let ((buf (get-buffer-create "*loading warnings*")))
143       (display-buffer buf)
144       (set-buffer buf)
145       (insert (propertize "Warning:" 'face 'font-lock-warning-face) " could not load '" name "'\n")
146       (fit-window-to-buffer (get-buffer-window buf))
147       (set-buffer-modified-p nil))
148     nil))
149
150 ;; This is the default in emacs 22.1 and later
151 ;; (auto-compression-mode 1)
152
153 ;; make emacs use the clipboard so that copy/paste works for other
154 ;; x-programs. I have no clue how all that clipboard thing works.
155
156 ;; (setq x-select-enable-clipboard t)
157 ;; (setq interprogram-paste-function 'x-cut-buffer-or-selection-value)
158 ;; (setq x-select-enable-primary t)
159 ;; (setq x-select-enable-clipboard t)
160 ;; (global-set-key "\C-y" 'clipboard-yank)
161
162 (setq
163
164  message-log-max 1000
165
166  ;; avoid GC as much as possible
167  gc-cons-threshold 2500000
168
169  ;; no startup message
170  inhibit-startup-screen t
171
172  ;; no message in the scratch buffer
173  initial-scratch-message nil
174
175  ;; do not fill my buffers, you fool
176  next-line-add-newlines nil
177
178  ;; keep the window focused on the messages during compilation
179  compilation-scroll-output t
180
181  ;; Keep the highlight on the compilation error
182  next-error-highlight t
183
184  ;; blink the screen instead of beeping
185  ;; visible-bell t
186
187  ;; take the CR when killing a line
188  kill-whole-line t
189
190  ;; I prefer to move between lines as defined in the buffer, not
191  ;; visually
192  line-move-visual nil
193
194  ;; I comment empty lines, too (does not seem to work, though)
195  comment-empty-lines t
196
197  ;; We want long lines to be truncated instead of displayed on several lines
198  ;; truncate-lines t
199  ;; Show all lines, even if the window is not as large as the frame
200  ;; truncate-partial-width-windows nil
201  ;; truncate-partial-width-windows t
202
203  ;; Do not keep tracks of the autosaved files
204  auto-save-list-file-prefix nil
205
206  ;; Show me empty lines at the end of the buffer
207  default-indicate-empty-lines t
208
209  ;; Show me the region until I do something on it
210  transient-mark-mode t
211
212  ;; Do not color stuff which are clickable when hovering over it
213  mouse-highlight nil
214
215  ;; Don't bother me with questions even if "unsafe" local variables
216  ;; are set
217  enable-local-variables :all
218
219  ;; I have no problem with small windows
220  window-min-height 1
221
222  ;; I am not a fan of develock
223  develock-auto-enable nil
224
225  ;; I do not like women to open windows
226  woman-use-own-frame nil
227
228  ;; I am not that paranoid, contrary to what you think
229  epa-file-cache-passphrase-for-symmetric-encryption t
230  ;; And I like ascii files
231  epa-armor t
232
233  ;; tramp-default-method "ssh"
234  tramp-default-method "scp"
235
236  ;; I have no problem with files having their own local variables
237  enable-local-eval t
238
239  mail-from-style 'angles
240  browse-url-mozilla-program "firefox"
241  mc-encrypt-for-me t
242  mc-use-default-recipients t
243
244  ;; browse-url-new-window-flag t
245
246  ;; I do not like compilation to automatically split the active window
247  ;; vertically, even when the said window is very wide
248  split-height-threshold 0
249  split-width-threshold nil
250
251  )
252
253 ;; The backups
254
255 (setq
256  temporary-file-directory "/tmp/"
257  vc-make-backup-files t
258  backup-directory-alist '((".*" . "~/misc/emacs.backups/"))
259  version-control t ;; Use backup files with numbers
260  kept-new-versions 10
261  kept-old-versions 2
262  delete-old-versions t
263  backup-by-copying-when-linked t
264  )
265
266 (setq tramp-backup-directory-alist backup-directory-alist)
267
268 (setq user-emacs-directory "~/misc/emacs.d/")
269
270 (setq
271  abbrev-file-name (concat user-emacs-directory "abbrev_defs")
272  server-auth-dir (concat user-emacs-directory "server/")
273  custom-theme-directory user-emacs-directory
274  )
275
276 ;; Stop this crazy blinking cursor
277 (blink-cursor-mode 0)
278
279 ;; (setq blink-cursor-delay 0.05
280 ;; blink-cursor-blinks 0
281 ;; blink-cursor-interval 0.25)
282
283 ;; (set-terminal-coding-system 'utf-8)
284
285 ;; (unless window-system
286 ;; (xterm-mouse-mode 1)
287 ;;   (if (string= (getenv "TERM") "xterm-256color")
288 ;;       (ff/load-or-alert "xterm-256color" t))
289 ;; )
290
291 (setq-default
292
293  ;; Show white spaces at the end of lines
294  show-trailing-whitespace t
295
296  ;; Do not show the cursor in non-active window
297  cursor-in-non-selected-windows nil
298
299  use-dialog-box nil
300  use-file-dialog nil
301
302  ;; when on a TAB, the cursor has the TAB length
303  x-stretch-cursor t
304
305  ;; This is the default coding system when toggle-input-method is
306  ;; invoked (C-\)
307  default-input-method "latin-1-prefix"
308
309  ;; do not put tabs when indenting
310  indent-tabs-mode nil
311  ;; Stop indenting automatically, that's annoying
312  electric-indent-chars nil
313
314  ;; And yes, we have a fast display / connection / whatever
315  baud-rate 524288
316  ;; baud-rate 10
317
318  ;; To keep the cursor always visible when it moves (thanks
319  ;; snogglethrop!)
320  redisplay-dont-pause t
321
322  ;; I want to see the keys I type instantaneously
323  echo-keystrokes 0.1
324  )
325
326 ;; Show the column number
327 (column-number-mode 1)
328
329 ;; What modes for what file extentions
330 (add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode))
331
332 (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
333
334 (require 'org-table)
335
336 (add-to-list 'auto-mode-alist '("\\.txt\\'" . (lambda()
337                                                 (text-mode)
338                                                 (orgtbl-mode)
339                                                 ;; (auto-fill-mode)
340                                                 (flyspell-mode))))
341
342 (add-hook 'c++-mode-hook 'flyspell-prog-mode)
343 (add-hook 'log-edit-mode-hook 'flyspell-mode)
344
345 ;; I am a power-user
346
347 (put 'narrow-to-region 'disabled nil)
348 (put 'upcase-region 'disabled nil)
349 (put 'downcase-region 'disabled nil)
350 ;; (put 'scroll-left 'disabled nil)
351 ;; (put 'scroll-right 'disabled nil)
352
353 ;; My selector is clearer than that
354 ;; (when (load "ido" t) (ido-mode t))
355
356 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
357
358 ;; Makes buffer names more explicit then <2>, <3> etc. when there are
359 ;; several identical filenames
360
361 (when (load "uniquify" t)
362   (setq uniquify-buffer-name-style 'post-forward-angle-brackets))
363
364 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
365 ;; Appearance
366 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
367
368 (when (boundp 'x-display-name)
369
370   (setq-default
371
372    ;; If the display is :0.0, we make the assumption that we are
373    ;; running the emacs locally, and we do not show the
374    ;; hostname. Otherwise, show @host.
375
376    frame-title-format (concat "emacs" ;;invocation-name
377                               (unless (string= x-display-name ":0.0")
378                                 (concat "@" system-name))
379                               " (%b)")
380
381    ;; Use the same for the icone
382
383    icon-title-format frame-title-format
384    ))
385
386 ;; "tool" bar? Are you kidding?
387 (when (fboundp 'tool-bar-mode) (tool-bar-mode -1))
388
389 ;; ;; If my own letter icon is here, use it and change its color
390 ;; (when (file-exists-p "~/local/share/emacs/letter.xbm")
391 ;; (setq-default display-time-mail-icon
392 ;; (find-image
393 ;; '((:type xbm
394 ;; :file "~/local/share/emacs/letter.xbm"
395 ;; :ascent center)))))
396
397 ;; My funky setting of face colors. Basically, we switch to a sober
398 ;; look and darken a bit the colors which need to (because of the
399 ;; darker background)
400
401 (defun ff/configure-faces (fl)
402   "Set face attributes and create faces when necessary"
403   (mapc (lambda (f)
404           (unless (boundp (car f)) (make-empty-face (car f)))
405           (eval `(set-face-attribute (car f) nil ,@(cdr f))))
406         fl))
407
408 ;; Not the same in xterm (which is gray in my case) and in
409 ;; X-window
410
411 (when window-system
412   ;; (setq
413   ;; display-time-use-mail-icon t)
414
415   (ff/configure-faces
416    '(
417      ;; (escape-glyph :foreground "#c0c0c0" :weight 'bold)
418      (escape-glyph :foreground "green3" :weight 'bold)
419      (default :background "gray90" :foreground "black")
420      (cperl-array-face :background "gray90" :foreground "blue" :weight 'bold)
421      (cperl-hash-face :background "gray90" :foreground "purple" :weight 'bold)
422      (message-cited-text :foreground "red4")
423      (diff-mode :background "gray90" :weight 'bold)
424      (diff-added :background "gray90" :foreground "green4" :weight 'bold)
425      (diff-removed :background "gray90" :foreground "red2" :weight 'bold)
426      (diff-changed :background "gray90" :foreground "blue" :weight 'bold)
427      (diff-file-header :background "white" :foreground "black"
428                        :weight 'bold)
429      (diff-header :background "white" :foreground "black")
430      (diff-hunk-header :background "white" :foreground "black")
431      (font-lock-builtin-face :foreground "deeppink3")
432      (font-lock-string-face :foreground "dark olive green")
433      (font-lock-variable-name-face :foreground "sienna")
434      ;; (font-lock-function-name-face :foreground "blue" :weight 'bold)
435      (font-lock-function-name-face :foreground "blue")
436      ;; (font-lock-comment-delimiter-face :foreground "dark violet")
437      ;; (font-lock-comment-face :foreground "dark violet")
438      (flyspell-incorrect :background "#ff0000" :foreground "black")
439      (flyspell-duplicate :background "#ff9000" :foreground "black")
440      (hl-line :background "white")
441      (sh-heredoc :foreground "black" :background "#fff0f0")
442      (sh-heredoc-face :foreground "black" :background "#fff0f0")
443      (header-line :background "gray65")
444      (highlight :background "turquoise")
445      (message-cited-text-face :foreground "firebrick")
446      (isearch :background "yellow" :foreground "black")
447      (isearch-lazy-highlight-face' :background "yellow3" :foreground "black")
448      (region :background "#b8b8e0" :foreground "black")
449      ;; (region :background "plum" :foreground "black")
450      (show-paren-match-face :background "gold" :foreground "black")
451      (show-paren-mismatch-face :background "red" :foreground "black")
452      (trailing-whitespace :background "gray65")
453      (cursor :inverse-video t)
454      (enotes/list-title-face :foreground "blue" :weight 'bold)
455      (mode-line :background "#b0b0ff" :foreground "black" :box nil
456                 :inverse-video nil)
457      (header-line :background "cornflowerblue" :foreground "black" :box nil
458                   :inverse-video nil)
459      (mode-line-inactive :background "gray80" :foreground "black" :box nil
460                          :inverse-video nil)
461      ;; (fringe :background "black" :foreground "gray90")
462      (fringe :background "gray80")
463      (ff/date-info-face :foreground "white")
464      (ff/battery-info-face :foreground "white")
465      (ff/mail-alarm-face :foreground "white" :background "red2")
466      ;; (alarm-vc-face :foreground "black" :background "yellow" :weight 'normal)
467      (gui-button-face :background "green" :foreground "black")
468      ))
469   )
470
471 (unless window-system
472   ;; (xterm-mouse-mode 1)
473   (ff/configure-faces
474    '((italic :underline nil)
475      (info-title-2 :foreground "green")
476      (font-lock-comment-delimiter-face :foreground "green")
477      (font-lock-comment-face :foreground "green")
478      (cperl-array-face :background "gray90" :foreground "blue" :weight 'bold)
479      (cperl-hash-face :background "gray90" :foreground "purple" :weight 'bold)
480      (diff-added :background "gray90" :foreground "green4" :weight 'bold)
481      (diff-removed :background "gray90" :foreground "red2" :weight 'bold)
482      (diff-changed :background "gray90" :foreground "blue" :weight 'bold)
483      (diff-file-header-face :background "white" :foreground "black"
484                             :weight 'bold)
485      (diff-header-face :background "white" :foreground "black")
486      (diff-hunk-header-face :background "white" :foreground "black")
487      (diff-indicator-removed :foreground "red" :weight 'bold)
488      (diff-removed :foreground "red" :weight 'bold)
489      (diff-indicator-added :foreground "blue" :weight 'bold)
490      (diff-added :foreground "blue" :weight 'bold)
491      (font-lock-string-face :foreground "green")
492      (font-lock-variable-name-face :foreground "blue")
493      (font-lock-constant-face :foreground "blue")
494      (font-lock-preprocessor-face :foreground "green")
495      (font-lock-function-name-face :foreground "cyan")
496      (flyspell-incorrect :foreground "red2")
497      (flyspell-duplicate :foreground "OrangeRed2")
498      (hl-line :background "white")
499      (sh-heredoc :foreground "black" :background "#fff0f0")
500      (sh-heredoc-face :foreground "black" :background "#fff0f0")
501      (font-lock-keyword-face :foreground "blue")
502      (highlight :background "darkseagreen3")
503      (isearch :background "orange" :foreground "black")
504      (isearch-lazy-highlight-face' :background "yellow" :foreground "black")
505      ;; (display-time-mail-face :background "white")
506      (show-paren-match-face :background "gold" :foreground "black")
507      (show-paren-mismatch-face :background "red" :foreground "black")
508      (trailing-whitespace :background "white")
509      (mode-line :background "cornflowerblue" :foreground "black" :box nil
510                 :inverse-video nil)
511      (header-line :background "cornflowerblue" :foreground "black" :box nil
512                   :inverse-video nil)
513      (mode-line-inactive :background "gray60" :foreground "black" :box nil
514                          :inverse-video nil)
515      (region :background "white" :foreground "black")
516      (ff/date-info-face :foreground "white" :weight 'bold)
517      (ff/battery-info-face :foreground "white")
518      (ff/mail-alarm-face :foreground "red" :weight 'bold)
519      (selector/selection :background "yellow")
520      (gui-button-face :background "green" :foreground "white")
521      (enotes/information-face :foreground "cyan")
522
523      (file-name-shadow :foreground "black")
524      (shadow :foreground "black")
525      (warning :foreground "black" :background "red")
526      ))
527   )
528
529 ;; When we are root, put the modeline in red
530
531 (when (string= (user-real-login-name) "root")
532   (ff/configure-faces
533    '((mode-line :background "red3" :foreground "black" :box nil
534                 :inverse-video nil))
535    ))
536
537 ;; Why should I have to do this?
538 (add-hook 'sh-mode-hook
539           (lambda ()
540             (set-face-attribute 'sh-heredoc nil
541                                 :foreground "#604000"
542                                 :background "white"
543                                 :italic t)
544             (set-face-attribute 'sh-heredoc-face nil
545                                 :foreground "#604000"
546                                 :background "white"
547                                 :italic t)
548             ))
549
550 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
551 ;; Move the window on the buffer without moving the cursor
552 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
553
554 (defun ff/scroll-down ()
555   "Scroll the buffer down one line and keep the cursor at the same location."
556   (interactive)
557   (condition-case nil
558       (scroll-down 1)
559     (error nil)))
560
561 (defun ff/scroll-up ()
562   "Scroll the buffer up one line and keep the cursor at the same location."
563   (interactive)
564   (condition-case nil
565       (scroll-up 1)
566     (error nil)))
567
568 (defun ff/scroll-left ()
569   "Scroll the buffer left one column and keep the cursor at the same location."
570   (interactive)
571   (condition-case nil
572       (scroll-left 2)
573     (error nil)))
574
575 (defun ff/scroll-right ()
576   "Scroll the buffer right one column and keep the cursor at the same location."
577   (interactive)
578   (condition-case nil
579       (scroll-right 2)
580     (error nil)))
581
582 (define-key global-map [(meta up)] 'ff/scroll-down)
583 (define-key global-map [(meta down)] 'ff/scroll-up)
584
585 (define-key global-map [(meta shift up)]
586   (lambda () (interactive) (condition-case nil (scroll-down 10) (error nil))))
587
588 (define-key global-map [(meta shift down)]
589   (lambda () (interactive) (condition-case nil (scroll-up 10) (error nil))))
590
591 ;; (define-key global-map [(meta shift up)] (lambda () (interactive) (ff/scroll-down 10)))
592 ;; (define-key global-map [(meta shift down)] 'ff/scroll-up)
593
594 (define-key global-map [(meta p)] 'ff/scroll-down)
595 (define-key global-map [(meta n)] 'ff/scroll-up)
596 (define-key global-map [(meta right)] 'ff/scroll-left)
597 (define-key global-map [(meta left)] 'ff/scroll-right)
598
599 (defun ff/delete-trailing-whitespaces-and-indent ()
600   (interactive)
601   (delete-trailing-whitespace)
602   (indent-region (point-min) (point-max) nil))
603
604 (define-key global-map [(control c) (control q)] 'ff/delete-trailing-whitespaces-and-indent)
605
606 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
607 ;; Playing sounds
608 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
609
610 ;; (defun ff/esd-sound (file)
611 ;;   "Plays a sound with the Enlighted sound daemon."
612 ;;   (interactive)
613 ;;   (process-kill-without-query (start-process-shell-command "esdplay"
614 ;;                                                            nil
615 ;;                                                            "esdplay" file)))
616
617 (defun ff/alsa-sound (file)
618   "Plays a sound with ALSA."
619   (interactive)
620   (process-kill-without-query (start-process-shell-command "aplay"
621                                                            nil
622                                                            "aplay" "-q" file)))
623
624 (if (and (boundp 'x-display-name) (string= x-display-name ":0.0"))
625     (defalias 'ff/play-sound-async 'ff/alsa-sound)
626   (defalias 'ff/play-sound-async 'ding))
627
628 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
629 ;; I comment stuff often, let's be efficient. shift + down comments
630 ;; the current line and goes down, and shift + up uncomments the line
631 ;; and goes up (they are not the dual of each other, but moving and
632 ;; then uncommenting would be very counter-intuitive).
633 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
634
635 (defun ff/comment-and-go-down (arg)
636   "Comments and goes down ARG lines."
637   (interactive "p")
638   (condition-case nil
639       (comment-region (point-at-bol) (point-at-eol)) (error nil))
640   (next-line 1)
641   (if (> arg 1) (ff/comment-and-go-down (1- arg))))
642
643 (defun ff/uncomment-and-go-up (arg)
644   "Uncomments and goes up ARG lines."
645   (interactive "p")
646   (condition-case nil
647       (uncomment-region (point-at-bol) (point-at-eol)) (error nil))
648   (next-line -1)
649   (if (> arg 1) (ff/uncomment-and-go-up (1- arg))))
650
651 (define-key global-map [(shift down)] 'ff/comment-and-go-down)
652 (define-key global-map [(shift up)] 'ff/uncomment-and-go-up)
653
654 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
655 ;; Counting various entities in text
656 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
657
658 (defun ff/word-occurences ()
659   "Display in a new buffer the list of words sorted by number of
660 occurrences "
661   (interactive)
662
663   (let ((buf (get-buffer-create "*word counting*"))
664         (map (make-sparse-keymap))
665         (nb (make-hash-table))
666         (st (make-hash-table))
667         (result nil))
668
669     ;; Collects all words in a hash table
670
671     (save-excursion
672       (goto-char (point-min))
673       (while (re-search-forward "\\([\\-a-zA-Z\\\\]+\\)" nil t)
674         (let* ((s (downcase (match-string-no-properties 1)))
675                (k (sxhash s)))
676           (puthash k s st)
677           (puthash k (1+ (gethash k nb 0)) nb))))
678
679     ;; Creates the result buffer
680
681     (define-key map "q" 'kill-this-buffer)
682     (display-buffer buf)
683     (set-buffer buf)
684     (setq show-trailing-whitespace nil)
685     (erase-buffer)
686
687     ;; Builds a list from the hash table
688
689     (maphash
690      (lambda (key value)
691        (setq result (cons (cons value (gethash key st)) result)))
692      nb)
693
694     ;; Sort and display it
695
696     (mapc (lambda (x)
697             (if (and (> (car x) 3)
698                      ;; No leading backslash and at least four characters
699                      (string-match "^[^\\]\\{4,\\}" (cdr x))
700                      )
701                 (insert (number-to-string (car x)) " " (cdr x) "\n")))
702           (sort result (lambda (a b) (> (car a) (car b)))))
703
704     ;; Adjust the window size and stuff
705
706     (fit-window-to-buffer (get-buffer-window buf))
707     (use-local-map map)
708     (set-buffer-modified-p nil))
709   )
710
711 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
712 ;; Printing
713 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
714
715 (load "ps-print")
716
717 (setq ps-print-color-p nil
718       ps-paper-type 'letter
719       ;; ps-paper-type 'a4
720       ;; ps-top-margin (* 1.75 56.692)
721       ;; ps-left-margin 56.692
722       ;; ps-bottom-margin 56.692
723       ;; ps-right-margin 56.692
724
725       ;; Simple header. Remove that silly frame shadow.
726       ps-print-header nil
727       ps-print-header-frame nil
728       ps-header-line-pad 0.3
729       ps-header-font-family 'Courier
730       ps-header-title-font-size '(8.5 . 10)
731       ;; ps-header-font-size '(6 . 7)
732       ps-header-font-size '(10 . 12)
733       ps-font-size '(7 . 8)
734       )
735
736 (ps-put 'ps-header-frame-alist 'back-color 1.0)
737 (ps-put 'ps-header-frame-alist 'shadow-color 1.0)
738 (ps-put 'ps-header-frame-alist 'border-color 0.0)
739 (ps-put 'ps-header-frame-alist 'border-width 0.0)
740
741 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
742
743 ;; http://blog.tuxicity.se/elisp/emacs/2010/03/26/rename-file-and-buffer-in-emacs.htm
744
745 (defun rename-file-and-buffer ()
746   "Renames current buffer and file it is visiting."
747   (interactive)
748   (let ((name (buffer-name))
749         (filename (buffer-file-name)))
750     (if (not (and filename (file-exists-p filename)))
751         (message "Buffer '%s' is not visiting a file!" name)
752       (let ((new-name (read-file-name "New name: " filename)))
753         (cond ((get-buffer new-name)
754                (message "A buffer named '%s' already exists!" new-name))
755               (t
756                (rename-file name new-name 1)
757                (rename-buffer new-name)
758                (set-visited-file-name new-name)
759                (set-buffer-modified-p nil)))))))
760
761 (global-set-key (kbd "C-c r") 'rename-file-and-buffer)
762
763 (defun ff/non-existing-filename (dir prefix suffix)
764   "Returns a filename of the form DIR/PREFIX[.n].SUFFIX whose file does
765 not exist"
766   (let ((n 0)
767         (f (concat prefix suffix)))
768     (while (file-exists-p (concat dir "/" f))
769       (setq n (1+ n)
770             f (concat prefix "." (prin1-to-string n) suffix)))
771     f))
772
773 (defun ff/print-buffer-or-region-with-faces (&optional file)
774
775   ;; I am fed up with spell checking highlights
776   (when (and flyspell-mode
777              ;; (or ispell-minor-mode flyspell-mode)
778              (not (y-or-n-p "The spell checking is on, still print ? ")))
779     (error "Printing cancelled, the spell-checking is on"))
780
781   (unless
782       (condition-case nil
783           (ps-print-region-with-faces (region-beginning) (region-end) file)
784         (error nil))
785     (ps-print-buffer-with-faces file)))
786
787 (defun ff/print-to-file (file)
788   "Prints the region if selected or the whole buffer in postscript
789 into FILE."
790   (interactive
791    (list
792     (read-file-name
793      "PS file: " "/tmp/" nil nil
794      (ff/non-existing-filename
795       "/tmp"
796       (replace-regexp-in-string "[^a-zA-Z0-9_.-]" "_" (file-name-nondirectory
797                                                        (buffer-name)))
798       ".ps"))
799     ))
800   (ff/print-buffer-or-region-with-faces file))
801
802 (defun ff/print-to-printer ()
803   "Prints the region if selected or the whole buffer to a postscript
804 printer."
805   (interactive)
806   (message "Printing to '%s'" (getenv "PRINTER"))
807   (ff/print-buffer-or-region-with-faces))
808
809 ;; Can you believe it? There is a "print" key on PC keyboards ...
810
811 (define-key global-map [(print)] 'ff/print-to-file)
812 (define-key global-map [(shift print)] 'ff/print-to-printer)
813
814 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
815 ;; Dealing with the laptop battery
816 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
817
818 (defcustom ff/battery-dirs '("/sys/class/power_supply/BAT0"
819                              "/sys/class/power_supply/BAT1")
820   "*Where to gather the battery information")
821
822 (defcustom ff/temperature-files '("/sys/class/thermal/thermal_zone0/temp"
823                                   "/sys/class/thermal/thermal_zone1/temp")
824   "*Where to gather the thermal information")
825
826 (defun ff/file-first-line (file)
827   (with-temp-buffer
828     (insert-file-contents-literally file)
829     (buffer-substring (point-at-bol) (point-at-eol))))
830
831 (defun ff/battery-discharging (l)
832   (and l (or (string= (ff/file-first-line (concat (car l) "/status")) "Discharging")
833              (ff/battery-discharging (cdr l)))))
834
835 ;; If there is one "Discharging" among the states of all the
836 ;; batteries, the global state is 'discharging. Otherwise, if there is
837 ;; a "Charging", the state is 'charging. If none is true, it is
838 ;; 'unknown
839 (defun ff/battery-state (l)
840   (if l
841       (let ((u (ff/file-first-line (concat (car l) "/status"))))
842         (if (string= u "Discharging") 'discharging
843           (let ((s (ff/battery-state (cdr l))))
844             (if (eq s 'discharging) 'discharging
845               (if (or (eq s 'charging) (string= u "Charging"))
846                   'charging
847                 'unknown))
848             )
849           )
850         )
851     'unknown))
852
853 (defun ff/sum-values-from-files (list-files prefix)
854   (apply '+
855          (mapcar
856           (lambda (f)
857             (condition-case nil
858                 (string-to-number (ff/file-first-line (format "%s/%s" f prefix)))
859               (error 0))
860             )
861           list-files)))
862
863 (defun ff/battery-percent ()
864   (condition-case nil
865       (/ (* 100 (ff/sum-values-from-files ff/battery-dirs "energy_now"))
866          (ff/sum-values-from-files ff/battery-dirs "energy_full"))
867     (error -1))
868   )
869
870 (defun ff/temp-info-string () (interactive)
871        (condition-case nil
872            ;; The temperature
873
874            (let ((temp (/
875                         (apply 'max (mapcar
876                                      (lambda (f) (string-to-number (ff/file-first-line f)))
877                                      ff/temperature-files))
878                         1000)))
879
880              (if (> temp 50)
881                  (let ((s (format "%dC " temp)))
882                    (if (> temp 70)
883                        (propertize s 'face 'font-lock-warning-face)
884                      s)
885                    )
886                )
887              )
888
889          (error nil))
890        )
891
892 (defun ff/battery-info-string () (interactive)
893        (condition-case nil
894            (pcase (ff/battery-state ff/battery-dirs)
895              ;; (`charging (format "c%d%%" (ff/battery-percent)))
896              ;; (`discharging (format "d%d%%" (ff/battery-percent)))
897              ;; (`unknown "f")
898              (`charging (format "↑%d%%" (ff/battery-percent)))
899              (`discharging (format "↓%d%%" (ff/battery-percent)))
900              (`unknown "✱")
901              (_ "?"))
902          (error nil))
903        )
904
905 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
906
907 (defun ff/system-info () (interactive)
908
909        (let ((buf (get-buffer-create "*system info*"))
910              (map (make-sparse-keymap)))
911
912          (define-key map "q" 'kill-this-buffer)
913          (display-buffer buf)
914          (set-buffer buf)
915          (setq show-trailing-whitespace nil)
916          (erase-buffer)
917
918          (let ((highlight nil))
919
920            (mapc (lambda (x)
921                    (insert
922                     (if (setq highlight (not highlight))
923                         (propertize
924                          (with-temp-buffer (apply 'call-process x)
925                                            (buffer-string))
926                          'face '(:background "#d0d0ff"))
927                       (with-temp-buffer (apply 'call-process x)
928                                         (buffer-string))
929                       ))
930                    )
931
932                  '(
933                    ("hostname" nil t nil "-f")
934                    ("acpi" nil t)
935                    ("df" nil t nil "-h")
936                    ;; ("mount" nil t)
937                    ("ifconfig" nil t)
938                    ("ssh-add" nil t nil "-l")
939                    )))
940
941          (goto-char (point-min))
942          (while (re-search-forward "^$" nil t) (backward-delete-char 1))
943
944          (fit-window-to-buffer (get-buffer-window buf))
945          (use-local-map map)
946          (set-buffer-modified-p nil)
947          ))
948
949 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
950 ;; Make a sound when there is new mail
951 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
952
953 ;; I do not like sounds anymore
954
955 ;; (setq ff/already-boinged-for-mail nil)
956
957 ;; (defun ff/boing-if-new-mail ()
958 ;; (if mail (when (not ff/already-boinged-for-mail)
959 ;; ;; (ff/play-sound-async "~/local/sounds/boing1.wav")
960 ;; ;; (ff/show-unspooled-mails)
961 ;; (setq ff/already-boinged-for-mail t))
962 ;; (setq ff/already-boinged-for-mail nil))
963 ;; )
964
965 ;; (add-hook 'display-time-hook 'ff/boing-if-new-mail)
966
967 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
968 ;; Display time
969 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
970
971 (setq
972
973  display-time-interval 10 ;; Check every 10s
974
975  display-time-string-forms `(
976
977                              load " "
978
979                                   (ff/temp-info-string)
980
981                                   ,@(when (ff/battery-info-string)
982                                       '((propertize
983                                         (ff/battery-info-string)
984                                         'face 'ff/battery-info-face)))
985
986                                   " "
987
988                                   (propertize
989                                    (concat ;;" ˌ"
990                                     24-hours ":" minutes
991                                     " "
992                                     ;; dayname " "
993                                     monthname " " day
994                                     ;;"ˌ"
995                                     )
996                                    'face 'ff/date-info-face)
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)