;;; .emacs --- Emacs init file
;; Copyright (C) 1989-2010 Juri Linkov
;; Author: Juri Linkov
;; Keywords: dotemacs, init
;; URL:
;; Version: 2010-01-17 for GNU Emacs 23.1.90 (x86_64-pc-linux-gnu)
;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;; "Show me your .emacs
;; and I'll tell you who you are."
;; -- modified proverb
;;; settings
;; Enable all disabled commands (eval-expression, narrow-to-..., etc.)
(setq disabled-command-function nil)
;; Get rid of all space-wasting garbage and minimize clutter
(and (fboundp 'menu-bar-mode) (menu-bar-mode -1))
(and (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
(and (fboundp 'tool-bar-mode) (tool-bar-mode -1))
(and (fboundp 'tooltip-mode) (fboundp 'x-show-tip) (tooltip-mode -1))
;; Blinking cursors are distracting - turn blink OFF
(and (fboundp 'blink-cursor-mode) (blink-cursor-mode (- (*) (*) (*))))
;; Use "y or n" for answers instead of complete words "yes or no"
(fset 'yes-or-no-p 'y-or-n-p)
;; If not on AC power line, then display battery status on the mode line
(and (require 'battery nil t)
(functionp battery-status-function)
(or (equal (cdr (assoc ?L (funcall battery-status-function))) "on-line")
(display-battery-mode)))
;; Create display table to modify some display elements
(or standard-display-table (setq standard-display-table (make-display-table)))
;; Display page delimiter ^L as a horizontal line
(aset standard-display-table ?\^L (vconcat (make-vector 64 ?-) "^L"))
;; Display triangle for outline of invisible lines.
;; For information, see (info "(elisp) Display Table Format")
;; (from old code in faces.el in Emacs repo modified for Emacs 23)
(if (facep 'escape-glyph)
(let* ((face (lsh (face-id 'escape-glyph) 22)) ;; 22 was 19 in Emacs 22
(backslash (+ face ?\\))
;; TRIANGULAR BULLET keeps the default font height
(dot (+ face #x2023)))
;; (aset standard-display-table 2208 (vector backslash ?\s)) ; no-break space
;; (aset standard-display-table 2221 (vector backslash ?-)) ; soft hyphen
;; (set-char-table-extra-slot standard-display-table 2 backslash) ; \364
;; (set-char-table-extra-slot standard-display-table 3 (+ face ?^)) ; ^@
;; (set-char-table-extra-slot standard-display-table 4 (vector dot dot dot))
(set-char-table-extra-slot standard-display-table 4 (vector dot))))
;; Non-customizable variables
(setq gc-cons-percentage 0.3)
(setq print-gensym t)
(setq print-circle t)
(setq redisplay-dont-pause t)
;; Tabify only initial whitespace
(setq tabify-regexp "^[ \t]+")
;; For a new non-file buffer set its major mode based on the buffer name.
;; http://thread.gmane.org/gmane.emacs.devel/115520/focus=115794
(setq-default major-mode (lambda ()
(if buffer-file-name
(fundamental-mode)
(let ((buffer-file-name (buffer-name)))
(set-auto-mode)))))
;;; frame
;; To use maximum screen space, my Emacs frame covers the entire screen
;; and has no menus, no toolbars, no scrollbars, no title and no borders.
;; Such customization on 1024x768 display mode and 6x10 font produces
;; Emacs text screen resolution 168 columns x 75 lines.
;; `split-window-horizontally' gives two windows with 83 columns x 75 lines.
;; And `follow-mode' displays one buffer with 83 columns x 150 lines.
(cond
((eq window-system 'x)
;;(create-fontset-from-ascii-font "-rfx-fixed-medium-r-normal--10-*-*-*-c-60-koi8-*")
(create-fontset-from-ascii-font "-misc-fixed-medium-r-*--10-*-*-*-*-*-*-*")
(setq default-frame-alist
(append
'(
;;TRY: maximize instead of (width . 168)
;;TRY: maximize instead of (height . 77)
;; This is useful with the next code in the ~/.sawfish/rc,
;; because I can't find a way to unframe and maximize Emacs window from Emacs:
;; (require 'sawfish.wm.state.maximize)
;; (define (my-customize-emacs-window w)
;; (when (string-match "emacs" (nth 2 (get-x-property w 'WM_CLASS)))
;; (window-put w 'type 'unframed)
;; (maximize-window w)))
;; (add-hook 'before-add-window-hook my-customize-emacs-window t)
(font . "-misc-fixed-medium-r-normal--10-*-*-*-c-60-iso8859-1")
;;(font . "-*-*-medium-r-normal--10-*-*-*-c-60-fontset-koi8_r_10")
;;? (font . "-rfx-fixed-medium-r-normal--10-*-*-*-c-60-koi8-*")
;;? (font . "-rfx-fixed-medium-r-normal--10-*-*-*-c-60-*-*")
;; (font . "-misc-fixed-medium-r-normal--10-100-75-75-c-60-iso10646-1")
;; (font . "-*-*-medium-r-*--10-*-*-*-*-*-fontset-iso8859_1_10")
(cursor-type . bar)
;; To win a lot of screen pixels:
(vertical-scroll-bars . nil)
(horizontal-scroll-bars . nil)
(scroll-bar-width . 0)
(internal-border-width . 0)
(menu-bar-lines . 0)
(tool-bar-lines . 0)
(line-spacing . 0))
default-frame-alist))))
;;; mouse
;; Move the mouse to the screen corner on any keypress.
(when (and (display-mouse-p) (require 'avoid nil t))
;; Move the mouse to the lower-right corner instead of default upper-right
(defun mouse-avoidance-banish-destination ()
(cons (+ 3 (frame-width)) (frame-height)))
(mouse-avoidance-mode 'banish))
;; Show the text pointer in void text areas (no need any more)
;; (setq void-text-area-pointer nil)
;;; colors
(defun my-colors-light (&optional frame)
"Set colors suitable for working in light environments,
i.e. in daylight or under bright electric lamps."
(interactive)
(setq frame-background-mode 'light)
(if frame
(select-frame frame)
(setq frame (selected-frame)))
;; The color with minimal eye fatigue in light environments
;; is "AntiqueWhite3" (RGB: 205 192 176),
;; (set-background-color "AntiqueWhite3")
(set-background-color "white")
(set-foreground-color "black")
(when (facep 'region)
(set-face-background 'region "DarkGrey" frame))
(when (facep 'fringe)
(set-face-background 'fringe (face-background 'default) frame)
(set-face-foreground 'fringe (face-foreground 'default) frame))
;; When started Emacs under root, warn by red color in the modeline
(when (and (facep 'mode-line)
(file-exists-p "/root")
(file-writable-p "/root"))
(set-face-background 'mode-line "firebrick")))
(define-key global-map [f6 ?c ?s] 'my-colors-light)
(defun my-colors-dark (&optional frame)
"Set colors suitable for working in the darkness without electricity."
(interactive)
(setq frame-background-mode 'dark)
(if frame
(select-frame frame)
(setq frame (selected-frame)))
(set-background-color "black")
(set-foreground-color "DarkGrey")
(when (facep 'region)
(set-face-background 'region "DimGray" frame))
(when (facep 'fringe)
(set-face-background 'fringe (face-background 'default) frame)
(set-face-foreground 'fringe (face-foreground 'default) frame)))
(define-key global-map [f6 ?c ?d] 'my-colors-dark)
;; Automatically switch to dark background after sunset
;; and to light background after sunrise.
;; (Note that `calendar-latitude' and `calendar-longitude'
;; should be set before calling the `solar-sunrise-sunset')
(defun my-colors-set (&optional frame)
(interactive)
(require 'solar)
(if (and calendar-latitude calendar-longitude calendar-time-zone)
(let* ((l (solar-sunrise-sunset (calendar-current-date)))
(sunrise-string (apply 'solar-time-string (car l)))
(sunset-string (apply 'solar-time-string (car (cdr l))))
(current-time-string (format-time-string "%H:%M")))
(if (or (string-lessp current-time-string sunrise-string)
(string-lessp sunset-string current-time-string))
(my-colors-dark frame)
(my-colors-light frame))
(if (and (boundp 'my-sunset-timer) (timerp my-sunset-timer))
(cancel-timer my-sunset-timer))
(if (and (boundp 'my-sunrise-timer) (timerp my-sunrise-timer))
(cancel-timer my-sunrise-timer))
(setq my-sunset-timer (run-at-time sunset-string (* 60 60 24)
'my-colors-dark))
(setq my-sunrise-timer (run-at-time sunrise-string (* 60 60 24)
'my-colors-light)))))
;; (my-colors-set)
(add-to-list 'after-make-frame-functions 'my-colors-set)
;;; faces
(defun my-faces-fix (&optional frame)
"Fix defined faces."
(interactive)
;; Check if this function is called by `custom-define-hook' from
;; `custom-declare-face' where the variable `face' is bound locally.
(when (boundp 'face)
(dolist (face (face-list))
;; Make italic gray instead of black
(when (face-italic-p face frame)
(if (equal (face-foreground face frame) "black")
(set-face-foreground face "gray50" frame)))
;; My font makes bold text unreadable,
;; so replace bold property with underline property
(when (face-bold-p face frame)
(set-face-bold-p face nil frame)
;; (set-face-inverse-video-p face t frame)
(set-face-underline-p face t frame))
;; Fonts with different height decrease the amount of lines
;; visible on screen, so remove the height property
(when (numberp (face-attribute face :height frame))
(set-face-attribute face frame :height 'unspecified))
;; Fonts with different width decrease the amount of characters
;; on the line, so remove the width property
(when (numberp (face-attribute face :width frame))
(set-face-attribute face frame :width 'unspecified))
;; Fonts with different weight decrease the height and width,
;; of the line, so remove the weight property
;; (when (numberp (face-attribute face :weight frame))
;; (set-face-attribute face frame :weight 'unspecified))
;; (unless (string-match "^mode-line" (symbol-name face))
;; ;; Reset all face attributes
;; (modify-face face))
)))
;; 1. Fix existing faces
;; (let ((face t)) (my-faces-fix))
;; (add-hook 'after-init-hook '(lambda () (let (face) (my-faces-fix))) t)
;; 2. Call `my-faces-fix' every time some new face gets defined
(add-to-list 'custom-define-hook 'my-faces-fix)
;;; keybindings
(define-key global-map [(control left)] 'backward-sexp)
(define-key global-map [(control right)] 'forward-sexp)
(define-key global-map [(control meta left)] 'backward-word)
(define-key global-map [(control meta right)] 'forward-word)
(define-key global-map [(meta left)] 'dired-jump)
(define-key global-map [(meta right)] 'my-find-thing-at-point)
(define-key global-map [(control meta up)] 'backward-paragraph)
(define-key global-map [(control meta down)] 'forward-paragraph)
;; fix new controversial keybindings in Emacs 23
(define-key global-map [home] 'beginning-of-visual-line)
(define-key global-map [end] 'end-of-visual-line)
(define-key global-map [up] 'previous-line)
(define-key global-map [down] 'next-line)
(define-key global-map "\C-p" 'previous-logical-line) ; previous-real-line
(define-key global-map "\C-n" 'next-logical-line) ; next-real-line
;; TODO: currently keybindings (meta up) (meta down) are free, use them
;; Actually I don't use next two keybindings, use them for something useful
;; (define-key global-map [(control meta prior)] 'scroll-right)
;; (define-key global-map [(control meta next)] 'scroll-left)
;; (define-key global-map [(control return)]
;; (lambda () (interactive) (let ((use-hard-newlines t)) (newline))))
;; (define-key global-map [(meta return)]
;; (lambda () (interactive) (scroll-other-window 1))) ;; [(meta down)]
;; (define-key global-map [(meta backspace)]
;; (lambda () (interactive) (scroll-other-window -1))) ;; [(meta up)]
(define-key global-map [(control backspace)] 'backward-kill-word)
;; (define-key global-map [(meta backspace)] 'undo)
;; (define-key global-map [(meta backspace)] 'backward-kill-word)
;; (define-key global-map [(control backspace)] 'join-lines)
(define-key global-map [(control ?=)] 'compare-windows)
;; alternative: (lambda () (interactive) (compare-windows t))
;; I often mistype `compare-windows' as `comapre-windows', allow both:
(defalias 'comapre-windows 'compare-windows)
(define-key global-map [(control kp-home)] 'beginning-of-buffer)
(define-key global-map [(control kp-end)] 'end-of-buffer)
(define-key global-map [(control shift kp-5)] 'goto-line)
(define-key global-map [(control kp-begin)] 'goto-line)
;; These following two keybindings are standard default:
;; (define-key global-map [(meta /)] 'dabbrev-expand)
;; (define-key global-map [(control meta /)] 'dabbrev-completion)
(define-key global-map [(meta kp-divide)] 'hippie-expand)
;; The following key is not available:
;; (define-key global-map [(control meta kp-divide)] 'hippie-expand)
;; BAD key: (define-key global-map "\M-n" 'clone-buffer)
(define-key global-map [(control x) (c) (b)] 'clone-buffer)
(define-key ctl-x-map "\C-\M-u" 'raise-sexp) ;; like `C-M-u'
(define-key ctl-x-map "\M-(" 'delete-pair) ;; the reverse of `M-('
(define-key global-map [f1] 'info)
(define-key global-map [(control f1)] 'info-lookup-symbol)
(define-key global-map [f2] 'save-buffer)
(define-key global-map [f9] 'call-last-kbd-macro)
(define-key global-map [(control f9)] 'compile)
(define-key global-map [(meta f7)] 'grep) ; Commander-like
(define-key global-map [(meta shift f7)] 'grep-find)
(define-key goto-map "re" 'grep)
(define-key goto-map "rr" 'rgrep)
(define-key goto-map "rl" 'lgrep)
(define-key goto-map "\M-r\M-e" 'grep)
(define-key goto-map "\M-r\M-r" 'rgrep)
(define-key goto-map "\M-r\M-l" 'lgrep)
;; (define-key global-map [(control escape)]
;; (lambda () (interactive) (buffer-menu 1))) ; not needed
;; (define-key global-map [(control escape)] 'ibuffer)
;; (define-key global-map [(shift f10)] 'buffer-menu) ; not needed
;; Like standard Emacs 22 commands (bound to C-x left/right)
(define-key global-map [f11] 'previous-buffer) ;; my-buffer-prev
(define-key global-map [f12] 'next-buffer) ;; my-buffer-next
;; Like standard Emacs 22 commands (bound to M-g n/p)
(define-key global-map [(control f11)] 'previous-error)
(define-key global-map [(control f12)] 'next-error)
(define-key global-map [(control shift f11)] 'compilation-previous-file)
(define-key global-map [(control shift f12)] 'compilation-next-file)
(defvar my-next-error-prev-buffer nil)
(defun my-next-error ()
;; Get rid of file buffers visited during going through results.
(when (and my-next-error-prev-buffer
(not (eq my-next-error-prev-buffer (current-buffer)))
;; buffer not edited
(memq buffer-undo-list '(nil t))
;; only on consequent keystrokes
(memq this-command '(next-error previous-error))
(eq (with-current-buffer next-error-last-buffer major-mode)
'grep-mode))
;; TODO: preserve existing file buffers, and positions in all file buffers
;; (goto-char (point-min)) ...
(kill-buffer my-next-error-prev-buffer))
(setq my-next-error-prev-buffer (current-buffer)))
(add-hook 'next-error-hook 'my-next-error)
;; TODO: currently key (control escape) is free, bind it to something useful,
;; unless it is used by the window manager
;; The following two corrections are for Scandinavian keyboard layouts.
;; Bind AltGr-space to the same command as is bound to Alt-space (M-SPC)
;; instead of inserting space-looking nobreak-space (nbsp, 0xa0, 0x8a0).
;; This is not necessary in Emacs 22 where nbsp has a special face.
;; (define-key global-map [?\xa0] 'just-one-space)
;; (define-key global-map [?\x8a0] 'just-one-space)
;; Swap currency sign with dollar sign, so dollar sign which is used more
;; often in programming languages could be typed more easily by pressing
;; shift-4 instead of AltGr-4.
;; (keyboard-translate ?\244 ?\$)
;; (keyboard-translate ?\$ ?\244)
;; Better to change this in .xmodmaprc for other applications too as:
;; keycode 13 = 4 dollar 4 dollar dollar cent
;; Map some diacritic characters (Ao, A", O") to arrow keys
;; which have the same layout as arrow pad keys on AltGr keyboards
;; This is experimental to make C-f/C-b/C-n/C-p like as easy as hjkl.
;; (define-key global-map [?\x8e5] 'previous-line) ; [up]
;; (define-key global-map [?\x8e4] 'next-line)
;; (define-key global-map [?\x8f6] 'backward-char)
;; (define-key global-map [?'] 'forward-char)
;;; quail
;; The default key `C-\' is difficult to type on AltGr keyboards.
;; (global-set-key [(control ?+)] 'toggle-input-method)
;; (global-set-key [(control ?')] 'toggle-input-method)
;; (global-set-key [(meta return)] 'toggle-input-method)
;; (define-key isearch-mode-map [(meta return)] 'isearch-toggle-input-method)
;; added for capslock to ~/.xsession: echo "keycode 66 = Print" | xmodmap -
;; (global-set-key [print] 'toggle-input-method)
;; (define-key isearch-mode-map [print] 'isearch-toggle-input-method)
;; (define-key mule-keymap "\\" 'set-input-method)
;; TODO for Emacs23: if toggle-input-method is called on the active region
;; then convert region to other coding, this is very useful when the region
;; was typed with a wrong input method, when the user forgot to toggle it
;;; mule
;; Delete codings like `utf-*-with-signature' (they hide BOMs)
;; to allow to always display the BOM (Byte-order mark signature)
;; to be able to remove it without the need to visit files literally
;; or with `C-x RET c utf-8 RET C-x C-f'.
;; SEE ALSO http://thread.gmane.org/gmane.emacs.devel/116668/focus=116738
(setq auto-coding-regexp-alist
(delete (rassoc 'utf-16be-with-signature auto-coding-regexp-alist)
(delete (rassoc 'utf-16le-with-signature auto-coding-regexp-alist)
(delete (rassoc 'utf-8-with-signature auto-coding-regexp-alist)
auto-coding-regexp-alist))))
;;; C-z my-map
;; Make the prefix key `C-z' for my personal keymap.
;; On qwerty-keyboards `C-z' is one of the most accessible keys
;; like `C-x' and `C-c', but the prefix key `C-c' is reserved
;; for mode-specific commands (both user-defined and standard Emacs extensions).
;; The standard binding of `C-z' (`suspend-emacs' or `iconify-or-deiconify-frame')
;; is reassigned here to double key sequence `C-z C-z'.
(defvar my-map
(let ((map (make-sparse-keymap))
(c-z (global-key-binding "\C-z")))
(global-unset-key "\C-z")
(define-key global-map "\C-z" map)
(define-key map "\C-z" c-z)
map))
;; my map can be used from isearch
;; (define-key isearch-mode-map "\C-z" my-map)
;; (define-key isearch-mode-map "\C-z" 'isearch-other-control-char)
(when window-system
;; Use single escape keypress instead of knocking it 3 times.
;; On a window system there is no need to use ESC as a prefix key.
(define-key global-map [escape] 'keyboard-escape-quit)
;; Set ESC-modifier to C-z escape
;; This is useful to invoke `M-TAB' or `M-|' on keyboards with AltGr key,
;; as `C-z ESC TAB' or `C-z ESC |'
(define-key my-map [escape] esc-map)
(define-key my-map [(control ?u)] 'rotate-window-buffers)
(define-key my-map "t" 'toggle-truncate-lines)
(define-key my-map "v" 'set-variable)
(define-key my-map "V" 'customize-variable)
(define-key my-map "r" 'revert-buffer)
(define-key my-map "p" (lambda () (interactive) (my-shell-command "perl test.pl")))
;; TEST: try `C-z C-x C-x C-x C-x ...', try `C-x z C-z C-z C-z' (repeat.el)
)
(when window-system
;; Insert paired characters
(define-key esc-map "\"" 'insert-pair)
;; (define-key esc-map "`" 'insert-pair)
;; (define-key global-map "\M-`" 'insert-pair)
;; (define-key esc-map "'" 'insert-pair)
(define-key esc-map "[" 'insert-pair)
(define-key esc-map "{" 'insert-pair)
(define-key esc-map ")" 'up-list)
(add-to-list 'insert-pair-alist '(?\' ?\` ?\')))
(define-key my-map "`" 'insert-pair)
(define-key my-map "<" 'insert-pair)
;; (defun insert-pair-without-space ()
;; (interactive)
;; (let ((parens-require-spaces nil))
;; (call-interactively 'insert-pair)))
;; (defun insert-pair-with-space ()
;; (interactive)
;; (let ((parens-require-spaces t))
;; (call-interactively 'insert-pair)))
;; (define-key esc-map "[" 'insert-pair-without-space)
;; (define-key esc-map "(" 'insert-pair-with-space)
;;; cursor
;; USE (setq default-cursor-type ...) INSTEAD OF THE NEXT FUNCTION
;; (defun set-cursor-type (cursor-type)
;; "Set the text cursor type of the selected frame to CURSOR-TYPE.
;; When called interactively, prompt for the name of the type to use.
;; To get the frame's current cursor type, use `frame-parameters'."
;; ;; see `fringe-query-style'
;; (interactive (list (intern (completing-read
;; "Cursor type: "
;; '("box" "hollow" "bar" "hbar" nil)))))
;; (modify-frame-parameters (selected-frame)
;; (list (cons 'cursor-type cursor-type))))
;; Currently cursor color is frame-local, but should be buffer-local like
;; cursor-type (or maybe even window-local).
;; Also background color should be buffer-local
;; (maybe this is already fixed in the tiled-background branch?).
;; (defadvice toggle-input-method (after my-toggle-input-method activate)
;; (if current-input-method
;; (set-cursor-color "red") ; "AntiqueWhite4"
;; (set-cursor-color "black")))
;; Use box cursor for overwrite-mode, and red cursor for quail active input.
(defun my-change-cursor ()
"Change cursor color and type depending on insertion mode and input method."
(set-cursor-color
(cond (current-input-method "red3") ; "AntiqueWhite4"
((eq (frame-parameter (selected-frame) 'background-mode) 'dark)
"DarkGrey")
(t "black")))
(setq default-cursor-type ;; set-cursor-type
(cond (overwrite-mode 'box)
(t 'bar))))
(add-hook 'post-command-hook 'my-change-cursor)
;;; functions
(defun my-find-thing-at-point ()
"Find variable, function or file at point."
(interactive)
(cond ((not (eq (variable-at-point) 0))
(call-interactively 'describe-variable))
((function-called-at-point)
(call-interactively 'describe-function))
(t (find-file-at-point))))
(defun my-next-link-or-scroll-page-forward (next-point)
"Scroll one screen forward when no more next links are visible on the screen.
The argument `next-point' is the point's position of the next link."
(if (and (> (window-end) next-point) (> next-point (point)))
(goto-char next-point)
(if (>= (window-end) (point-max))
(goto-char (point-max))
(progn (View-scroll-page-forward-set-page-size) (move-to-window-line 0)))))
(defun my-prev-link-or-scroll-page-backward (prev-point)
"Scroll one screen backward when no more previous links are visible on the screen.
The argument `prev-point' is the point's position of the previous link."
(if (and (< (window-start) prev-point) (< prev-point (point)))
(goto-char prev-point)
(if (<= (window-start) (point-min))
(goto-char (point-min))
(progn (View-scroll-page-backward-set-page-size)))))
(defvar my-scroll-auto-timer nil)
(defun my-scroll-auto (arg)
"Scroll text of current window automatically with a given frequency.
With a numeric prefix ARG, use its value as frequency in seconds.
With C-u, C-0 or M-0, cancel the timer."
(interactive
(list (progn
(if (and (boundp 'my-scroll-auto-timer)
(timerp my-scroll-auto-timer))
(cancel-timer my-scroll-auto-timer))
(or current-prefix-arg
(read-from-minibuffer
"Enter scroll frequency measured in seconds (0 or RET for cancel): "
nil nil t nil "0")))))
(if (not (or (eq arg 0) (equal arg '(4))))
(setq my-scroll-auto-timer (run-at-time t arg 'scroll-up 1))))
(define-key my-map "s" 'my-scroll-auto)
;;; window
;; Define buffers that should appear in the same window.
(add-to-list 'same-window-buffer-names "*Apropos*")
(add-to-list 'same-window-buffer-names "*Buffer List*")
(add-to-list 'same-window-buffer-names "*Colors*")
(add-to-list 'same-window-buffer-names "*Command History*")
(add-to-list 'same-window-buffer-names "*Diff*")
(add-to-list 'same-window-buffer-names "*Proced*")
(add-to-list 'same-window-buffer-names "*vc-dir*")
(add-to-list 'same-window-regexps "\\*compilation\\*\\(\\|<[0-9]+>\\)")
(add-to-list 'same-window-regexps "\\*grep\\*\\(\\|<[0-9]+>\\)")
(add-to-list 'same-window-regexps "\\*Help\\*\\(\\|<[0-9]+>\\)")
(defun my-move-to-window-top (&optional arg)
"Position point to the top line of the window."
(interactive)
(move-to-window-line 0))
(define-key global-map [(control prior)] 'my-move-to-window-top)
(defun my-move-to-window-bottom (&optional arg)
"Position point to the bottom line of the window."
(interactive)
(move-to-window-line -1))
(define-key global-map [(control next)] 'my-move-to-window-bottom)
(defun my-windows-balance ()
(interactive)
(other-window 1)
(balance-windows)
(shrink-window-if-larger-than-buffer)
(other-window -1))
(define-key my-map "wb" 'my-windows-balance)
;; [2009-11-29] TRY TO USE `recenter-top-bottom' instead of this:
;; (defvar my-recenter-line 15)
;; (defun my-recenter (&optional arg)
;; "Places point in window on eyes level."
;; (interactive "P")
;; (if (equal arg '(16))
;; (setq my-recenter-line (count-screen-lines
;; (window-start)
;; (save-excursion (beginning-of-line) (point)))
;; arg nil
;; recenter-position (/ (float my-recenter-line)
;; (count-screen-lines
;; (window-start) (window-end)))))
;; (if arg (recenter arg) (recenter my-recenter-line)))
;; (put 'my-recenter 'isearch-scroll t)
;;
;; (define-key my-map "\C-l" 'my-recenter)
;; (define-key global-map "\C-l" 'my-recenter)
;; [2009-11-29] TRY TO USE `move-to-window-line-top-bottom' instead of this:
;; (defun my-move-to-window-line (&optional arg)
;; "Places point in window on eyes level."
;; (interactive "P")
;; (if (equal arg '(16))
;; (setq my-recenter-line (count-screen-lines
;; (window-start)
;; (save-excursion (beginning-of-line) (point)))
;; arg nil))
;; (if arg (move-to-window-line arg) (move-to-window-line my-recenter-line)))
;;
;; (define-key my-map "\M-r" 'my-move-to-window-line)
;; (define-key global-map "\M-r" 'my-move-to-window-line)
(setq recenter-position (car recenter-positions))
;; OLD: (setq split-window-preferred-function 'split-window-preferred-horizontally)
;; (defadvice split-window-preferred-horizontally
;; (around my-split-window-preferred-horizontally act)
;; (let ((window ad-do-it))
;; (if (string-match "\\*Help\\*\\(\\|<[0-9]+>\\)" (buffer-name (car (buffer-list))))
;; (selected-window)
;; window)))
;;; isearch
;; Wrap without failing, posted to
;; http://stackoverflow.com/questions/285660/automatically-wrapping-i-search#287067
;; (defadvice isearch-repeat (after isearch-no-fail activate)
;; (unless isearch-success
;; (ad-disable-advice 'isearch-repeat 'after 'isearch-no-fail)
;; (ad-activate 'isearch-repeat)
;; (isearch-repeat (if isearch-forward 'forward))
;; (ad-enable-advice 'isearch-repeat 'after 'isearch-no-fail)
;; (ad-activate 'isearch-repeat)))
;; Automatically recenter every found isearch match
;; (defadvice isearch-update (before my-isearch-update activate)
;; (sit-for 0)
;; (if (and
;; ;; not the scrolling command
;; (not (eq this-command 'isearch-other-control-char))
;; ;; not the empty string
;; (> (length isearch-string) 0)
;; ;; not the first key (to lazy highlight all matches w/o recenter)
;; (> (length isearch-cmds) 2)
;; ;; the point in within the given window boundaries
;; (let ((line (count-screen-lines (point) (window-start))))
;; (or (> line (* (/ (window-height) 4) 3))
;; (< line (* (/ (window-height) 9) 1)))))
;; (let ((recenter-position 0.3))
;; (recenter '(4)))))
;; Automatically reposition every found isearch match
;; (defadvice isearch-update (before my-isearch-reposite activate)
;; (sit-for 0)
;; (reposition-window))
(defun isearch-beginning-of-buffer ()
"Move isearch point to the beginning of the buffer."
(interactive)
(goto-char (point-min))
(isearch-repeat-forward))
(define-key isearch-mode-map "\M-<" 'isearch-beginning-of-buffer)
(defun isearch-end-of-buffer ()
"Move isearch point to the end of the buffer."
(interactive)
(goto-char (point-max))
(isearch-repeat-backward))
(define-key isearch-mode-map "\M->" 'isearch-end-of-buffer)
(define-key isearch-mode-map "\t" 'isearch-complete)
(define-key minibuffer-local-isearch-map "\t" 'isearch-complete-edit)
(define-key isearch-mode-map [(control return)] 'isearch-exit)
;; S-RET leaves lazy-highlighted matches.
(defun my-isearch-exit-leave-lazy-highlight ()
"Exit search and leave extra match highlighting."
(interactive)
(let ((lazy-highlight-cleanup nil))
(when isearch-lazy-highlight
(isearch-lazy-highlight-new-loop (point-min) (point-max)))
(isearch-exit)))
(define-key isearch-mode-map [(shift return)]
'my-isearch-exit-leave-lazy-highlight)
;; C-RET doesn't add the current search string to the history.
(add-hook 'isearch-mode-end-hook
(lambda ()
;; On typing C-RET
(when (eq last-input-char 'C-return)
;; Set the point at the beginning of the search string
(if (and isearch-forward isearch-other-end)
(goto-char isearch-other-end))
;; Don't push the search string into the search ring
(if isearch-regexp
(setq regexp-search-ring (cdr regexp-search-ring))
(setq search-ring (cdr search-ring))))))
;; Make Isearch mode-line string shorter, just " /" instead of " Isearch"
;; (add-hook 'isearch-mode-hook
;; (lambda () (setq isearch-mode " /") (force-mode-line-update)))
;; BAD:
;; (define-key isearch-mode-map [(left)] 'isearch-del-char)
;; (define-key isearch-mode-map [(right)] 'isearch-yank-char)
;; (define-key isearch-mode-map [(control right)] 'isearch-yank-word)
;; `C-w' is better than `M-f':
;; (define-key isearch-mode-map "\M-f" 'isearch-yank-word)
;; Do not use customization to not corrupt .emacs with literal
;; control characters.
;; The next line is bad, because \n is bad for `C-M-s SPC $'
;; (setq search-whitespace-regexp "[ \t\r\n]+")
;; TRY to ignore punctuation:
(setq search-whitespace-regexp "\\W+")
;;; occur
;; Make *Occur* buffer names unique.
(add-hook 'occur-hook (lambda () (occur-rename-buffer t)))
;;; replace
(defun substitute-regexp (substitution)
"Use s/old/new/g regexp syntax for `query-replace'."
(interactive
(list
(read-from-minibuffer "Substitute regexp: " '("s///g" . 3) nil nil
'query-replace-history nil t)))
(if (string-match "^s/\\(.*\\)/\\(.*\\)/\\([gi]*\\)" substitution)
(let* ((sregex (match-string 1 substitution))
(ssubst (match-string 2 substitution))
(sflags (match-string 3 substitution))
(case-fold-search (string-match "i" sflags)))
(perform-replace
sregex ssubst (string-match "g" sflags)
t nil nil nil
(if (and transient-mark-mode mark-active) (region-beginning))
(if (and transient-mark-mode mark-active) (region-end))))
(error "Invalid syntax")))
;;; minibuffer
;; Remove potentially dangerous commands from the history immediately
(add-hook 'minibuffer-exit-hook
(lambda ()
(when (string-match
"^rm"
(car (symbol-value minibuffer-history-variable)))
(set minibuffer-history-variable
(cdr (symbol-value minibuffer-history-variable))))))
;; This is not needed when isearch C-s/C-r in the minibuffer is available
;; (but `C-M-r ^command' doesn't match at the beginning of the input area)
(define-key minibuffer-local-map "\eN" 'next-complete-history-element)
(define-key minibuffer-local-map "\eP" 'previous-complete-history-element)
;; M-k in the minibuffer deletes the minibuffer history element.
(defun delete-history-element ()
"Delete the current minibuffer history element from the history.
After deleting the element, the history position is changed either
to the the previous history element, or to the next history element
if the deleted element was the last in the history list."
(interactive)
(cond
((= minibuffer-history-position 1)
(set minibuffer-history-variable
(cdr (symbol-value minibuffer-history-variable))))
((> minibuffer-history-position 1)
(setcdr (nthcdr (- minibuffer-history-position 2)
(symbol-value minibuffer-history-variable))
(nthcdr minibuffer-history-position
(symbol-value minibuffer-history-variable)))))
(condition-case nil (next-history-element 1) (error nil))
(condition-case nil (previous-history-element 1) (error nil)))
(define-key minibuffer-local-map "\ek" 'delete-history-element)
(define-key minibuffer-local-isearch-map "\ek" 'delete-history-element)
;; THE NEXT 3 FUNCTIONS WORK WITH BIG DELAY (try to use like icomplete.el)
;; see also PC-temp-minibuffer-message, file-cache-temp-minibuffer-message,
;; calc-temp-minibuffer-message and bug report in emacs-pretest-bug
;; Subject: bad doc string for PC-temp-minibuffer-message
(defun minibuffer-history-position-message ()
(if (memq this-command '(next-history-element previous-history-element))
(minibuffer-message
(propertize
(format "%s[%s]"
(make-string
1
;; (- (frame-width)
;; (minibuffer-prompt-width)
;; (length (minibuffer-contents-no-properties))
;; 5)
?\ )
minibuffer-history-position) 'face 'shadow))))
;; (defadvice next-history-element (after history-position-message activate)
;; (minibuffer-history-position-message))
;; (defadvice previous-history-element (after history-position-message activate)
;; (minibuffer-history-position-message))
;; (defadvice goto-history-element (after history-position-message activate)
;; (minibuffer-history-position-message))
;; (defadvice goto-history-element (before minibuffer-set-default activate)
;; (if (functionp minibuffer-default-function)
;; (funcall minibuffer-default-function)))
;; Another implementation of the same idea:
(defvar minibuffer-history-position-overlay)
(make-variable-buffer-local 'minibuffer-history-position-overlay)
(defun minibuffer-history-position-setup ()
"Set up a minibuffer for `minibuffer-history-position-mode'.
The prompt should already have been inserted."
(setq minibuffer-history-position-overlay (make-overlay (point-min) (1+ (point-min))))
(overlay-put minibuffer-history-position-overlay 'evaporate t))
;; (add-hook 'minibuffer-setup-hook 'minibuffer-history-position-setup)
(defun minibuffer-history-position-update ()
"Update a minibuffer for `minibuffer-history-position-mode'."
(overlay-put minibuffer-history-position-overlay 'before-string
(propertize (format "(%d) " minibuffer-history-position)
'face 'minibuffer-prompt)))
;; (defadvice next-history-element (after my-next-history-element activate)
;; (minibuffer-history-position-update))
;; (defadvice previous-history-element (after my-previous-history-element activate)
;; (minibuffer-history-position-update))
;;; other features
;; http://thread.gmane.org/gmane.emacs.devel/116457/focus=116468 is like this:
(defun my-info-refresh (&optional arg)
"Display some useful information in the echo area instead of the mode line.
With prefix arg, insert the current timestamp to the current buffer."
(interactive "P")
(cond
((equal arg '(4)) ; C-u f5
(insert (format-time-string "%Y%m%d" (current-time))))
((equal arg '(16)) ; C-u C-u f5
(insert (format-time-string "%Y-%m-%d" (current-time))))
(t (message "%s"
(concat
(format-time-string "%Y-%m-%d %H:%M:%S %z" (current-time)) ;; ISO
" "
(aref calendar-day-abbrev-array (nth 6 (decode-time (current-time))))
" : "
(or (buffer-file-name) default-directory))))))
(define-key my-map [f5] 'my-info-refresh)
(define-key global-map [f5] 'my-info-refresh)
(defun my-work-log-add (&optional arg)
(interactive "P")
(find-file my-work-log-file)
(goto-char (point-max))
(cond ((re-search-backward "^[0-9-]+ [0-9:]+\\( +\\)[^0-9]" nil t)
(goto-char (match-beginning 1))
(replace-match "" t t nil 1)
(insert (format-time-string " %H:%M " (current-time))))
((re-search-backward "^[0-9-]+ [0-9:]+" nil t)
(forward-line 1)
(insert (format-time-string "%Y-%m-%d %H:%M \n" (current-time)))
(backward-char))))
(define-key my-map "wl" 'my-work-log-add)
(defun my-buffer-xray ()
"Display text properties and overlays of current buffer by adding markups."
(interactive)
(let* ((newbuf (get-buffer-create (format "*xray-buffer*/%s" (buffer-name))))
(s (buffer-substring (point-min) (point-max))) ;; (buffer-string) -no-properties
(overlays (sort (overlays-in (point-min) (point-max))
(lambda (a b) (< (overlay-start a)
(overlay-start b)))))
(oi 0)
;; ois is indexes of overlays sorted by start positions
(ois (mapcar (lambda (o) (setq oi (1+ oi)) (cons o oi))
overlays))
;; poss is list of positions of boundaries of text properties
;; and start and end positions of overlays
(poss (sort
(append
(let ((p (point-min)) (pp))
(while p
(setq pp (cons (cons p (text-properties-at p)) pp))
(setq p (next-property-change p)))
pp)
(mapcar (lambda (o)
(list (overlay-start o) 'os (cdr (assq o ois))))
overlays)
(mapcar (lambda (o)
(list (overlay-end o) 'oe (cdr (assq o ois))))
overlays))
;; sort positions in the descending order
(lambda (a b) (if (= (car a) (car b))
;; for equal positions first no prop
(or (null (cadr b))
(and (eq (cadr a) 'os) (eq (cadr b) 'os)
(> (caddr a) (caddr b)))
(and (eq (cadr a) 'oe) (eq (cadr b) 'oe)
(< (caddr a) (caddr b))))
(> (car a) (car b))))))
(p (point)))
(switch-to-buffer newbuf)
(insert s)
(goto-char p)
(save-excursion
(mapcar (lambda (pos)
(goto-char (car pos))
;; insert markup from buffer end to the beginning
(cond
((eq (cadr pos) 'os)
(insert (format "" (caddr pos))))
((eq (cadr pos) 'oe)
(insert (format "" (caddr pos))))
((null (cdr pos))
(insert "
"))
(t (let ((props (cdr pos)))
(insert "
")))))
poss))
(run-hooks 'my-buffer-xray)))
(add-hook 'my-buffer-xray 'html-mode)
;;; qv (evaluable bookmarks)
;; TODO: use bookmark.el?
;; TODO: add Info node and line number
(defun qv (&optional url anchor)
"Add or activate live bookmarks.
When called interactively, put the address of the current location
inside a function call to `qv' into the clipboard that can be
pasted in another buffer that stores bookmarks.
Otherwise, after typing `C-x C-e' on the bookmark funcall
goes to the saved location."
(interactive)
(if (called-interactively-p)
(kill-new
(message "%s"
(concat "(qv "
(cond
(buffer-file-name
(format "\"%s\"\n \"^%s$\"" ;; "\"%s\" %s"
buffer-file-name
;;(line-number-at-pos)
(replace-regexp-in-string
"^[ \t]*" "[ \t]*"
(replace-regexp-in-string
"\"" "\\\\\""
(replace-regexp-in-string
"\\\\" "\\\\\\\\"
(regexp-quote
(buffer-substring-no-properties
(line-beginning-position)
(line-end-position)))))))))
")")))
(cond
((file-exists-p url)
(find-file url)
(cond
((integerp anchor)
(goto-line anchor))
((stringp anchor)
(goto-char (point-min))
(if (re-search-forward anchor)
(goto-char (match-beginning 0)))))))))
;;; packages
;; Load some useful packages
(require 'misc)
(require 'tempo)
(require 'wid-edit)
(require 'generic)
(require 'generic-x)
;; Use standard js-mode instead of javascript-generic-mode from generic-x.
(setq auto-mode-alist (delete (rassoc 'javascript-generic-mode auto-mode-alist)
auto-mode-alist))
;; (and (require 'ffap) (ffap-bindings))
;; Don't bind ffap keybindings anymore, because now `C-x C-f M-n'
;; gets the filename at point when ffap.el is loaded
(require 'ffap)
;;; ee
(when (require 'ee-autoloads nil t)
(define-key global-map [f1] 'ee-info)
(define-key global-map [(control tab)] 'ee-buffers)
(define-key my-map "eb" 'ee-buffers)
(define-key my-map "ehc" 'ee-history-command)
(define-key my-map "ehe" 'ee-history-extended-command)
(define-key my-map "ehs" 'ee-history-shell-command)
(define-key my-map "ei" 'ee-imenu)
(define-key my-map "em" 'ee-marks)
(define-key my-map "eo" 'ee-outline)
(define-key my-map "epr" 'ee-programs)
(define-key my-map "eps" 'ee-ps)
(define-key my-map "et" 'ee-tags)
(define-key my-map "ewa" 'ee-windows-add)
(define-key my-map "eww" 'ee-windows)
(define-key global-map [(meta ?\xa7)] 'ee-windows-and-add-current)
(define-key global-map [(meta ?\x8a7)] 'ee-windows-and-add-current)
(define-key global-map [(meta ?`)] 'ee-windows-and-add-current)
(define-key global-map [(super ?`)] 'ee-windows-and-add-current)
(eval-after-load "ee-windows"
'(progn
(define-key ee-windows-keymap [(meta ?\xa7)] 'ee-windows-select-and-delete-current)
(define-key ee-windows-keymap [(meta ?\x8a7)] 'ee-windows-select-and-delete-current)
(define-key ee-windows-keymap [(meta ?`)] 'ee-windows-select-and-delete-current)
(define-key ee-windows-keymap [(super ?`)] 'ee-windows-select-and-delete-current)
(define-key ee-windows-keymap [( ?\xa7)] 'ee-view-record-next)
(define-key ee-windows-keymap [(?\x8a7)] 'ee-view-record-next)
(define-key ee-windows-keymap [( ?`)] 'ee-view-record-next)
(define-key ee-windows-keymap [( ?\xbd)] 'ee-view-record-prev)
(define-key ee-windows-keymap [(?\x8bd)] 'ee-view-record-prev)
(define-key ee-windows-keymap [( ?~)] 'ee-view-record-prev))))
;; Use standalone wincows.el instead
(when (require 'wincows nil t)
(define-key global-map [(meta ?\xa7)] 'wincows)
(define-key global-map [(meta ?\x8a7)] 'wincows)
(define-key global-map [(meta ?`)] 'wincows)
(define-key global-map [(super ?`)] 'wincows)
(eval-after-load "wincows"
'(progn
(define-key wincows-mode-map [(meta ?\xa7)] 'wincows-select)
(define-key wincows-mode-map [(meta ?\x8a7)] 'wincows-select)
(define-key wincows-mode-map [(meta ?`)] 'wincows-select)
(define-key wincows-mode-map [(super ?`)] 'wincows-select)
(define-key wincows-mode-map [( ?\xa7)] 'wincows-next-line)
(define-key wincows-mode-map [(?\x8a7)] 'wincows-next-line)
(define-key wincows-mode-map [( ?`)] 'wincows-next-line)
(define-key wincows-mode-map [( ?\xbd)] 'wincows-prev-line)
(define-key wincows-mode-map [(?\x8bd)] 'wincows-prev-line)
(define-key wincows-mode-map [( ?~)] 'wincows-prev-line))))
;;; lisp
;; This is my most frequently used command bound to C-RET in Lisp modes.
(defun my-reindent-then-newline-and-indent-and-indent-sexp ()
"Reindent current line, insert newline, then indent the new line.
Move backward out of one level of parentheses.
Indent each line of the list starting just after point."
(interactive "*")
(reindent-then-newline-and-indent)
(save-excursion
(backward-up-list)
(indent-sexp)))
(defun my-join-line-and-indent-sexp ()
"Join this line to previous and fix up whitespace at join.
Move backward out of one level of parentheses.
Indent each line of the list starting just after point."
(interactive "*")
(join-line)
(save-excursion
(backward-up-list)
(let ((indent-sexp-function (key-binding "\e\C-q")))
(if indent-sexp-function (call-interactively indent-sexp-function)))))
;; This is another frequently used command bound to C-backspace.
;; It's almost the reverse of C-RET defined above.
(defun my-join-line-and-indent-sexp-or-backward-kill-word ()
"If point is on the whitespaces at the beginning of a line,
then join this line to previous and indent each line of the upper list.
Otherwise, kill characters backward until encountering the end of a word."
(interactive "*")
(if (save-excursion (and (skip-chars-backward " \t") (bolp)))
(my-join-line-and-indent-sexp)
(backward-kill-word 1)))
(global-set-key [C-backspace] 'my-join-line-and-indent-sexp-or-backward-kill-word)
;; This is bound to TAB in Lisp modes.
(defun my-lisp-indent-or-complete (&optional arg)
"Complete Lisp symbol, or indent line or region.
If the character preceding point is symbol-constituent, then perform
completion on Lisp symbol preceding point using `lisp-complete-symbol'.
Otherwise, call `indent-for-tab-command' that indents line or region."
(interactive "P")
(if (and (not (and transient-mark-mode mark-active
(not (eq (region-beginning) (region-end)))))
(memq (char-syntax (preceding-char)) (list ?w ?_))
(not (bobp)))
(lisp-complete-symbol)
(indent-for-tab-command arg)))
(defun my-beginning-of-line-or-indentation (arg)
"Jump to the beginning of the line or to the indentation (like `M-m')."
(interactive "p")
(if (bolp)
(beginning-of-line-text arg) ; (back-to-indentation) ?
(if (fboundp 'move-beginning-of-line)
(move-beginning-of-line arg)
(beginning-of-line arg))))
(define-key global-map [(control ?a)] 'my-beginning-of-line-or-indentation)
(defun my-reindent-then-newline-and-indent ()
"Create the next number item in the numbered list, or reindent."
(interactive)
(let ((num 1))
(if (save-excursion
(backward-paragraph)
(forward-line)
(not (and (looking-at "^\\s-*\\([0-9]\\)\\.")
(setq num (match-string 1)))))
(reindent-then-newline-and-indent)
(insert (format "\n\n%s. " (1+ (string-to-number num)))))))
(define-key global-map [(control return)] 'reindent-then-newline-and-indent)
(define-key global-map [(control shift return)] 'my-reindent-then-newline-and-indent)
;; Lisp mode
(define-key lisp-mode-map [(control return)]
'my-reindent-then-newline-and-indent-and-indent-sexp)
;; (define-key lisp-mode-map [(control backspace)]
;; 'my-join-line-and-indent-sexp-or-backward-kill-word)
(tempo-define-template "lisp-print-map" '("(map (lambda (x) ) " p ")"))
(define-key lisp-mode-map "\C-zim" 'tempo-template-lisp-print-map)
;; Emacs Lisp mode
(define-key emacs-lisp-mode-map [(control return)]
'my-reindent-then-newline-and-indent-and-indent-sexp)
;; (define-key emacs-lisp-mode-map [(control backspace)]
;; 'my-join-line-and-indent-sexp-or-backward-kill-word)
(define-key emacs-lisp-mode-map [tab] 'my-lisp-indent-or-complete)
;; use C-M-i instead of
;; (define-key emacs-lisp-mode-map [(control meta tab)] 'lisp-complete-symbol)
;; use C-M-i instead of
;; (define-key emacs-lisp-mode-map "\C-ze\t" 'lisp-complete-symbol)
(define-key emacs-lisp-mode-map "\C-xF" 'find-function)
(define-key emacs-lisp-mode-map "\C-x4F" 'find-function-other-window)
(define-key emacs-lisp-mode-map "\C-x5F" 'find-function-other-frame)
(define-key emacs-lisp-mode-map "\C-xK" 'find-function-on-key)
(define-key emacs-lisp-mode-map "\C-xV" 'find-variable)
(define-key emacs-lisp-mode-map "\C-x4V" 'find-variable-other-window)
(define-key emacs-lisp-mode-map "\C-x5V" 'find-variable-other-frame)
(tempo-define-template "emacs-lisp-print-message" '("(message \"%s\" " p ")"))
(define-key emacs-lisp-mode-map "\C-zim" 'tempo-template-emacs-lisp-print-message)
(tempo-define-template "emacs-lisp-print-defun"
'("(defun " p " ()\n (interactive)\n\n)\n"))
(define-key emacs-lisp-mode-map "\C-zid" 'tempo-template-emacs-lisp-print-defun)
;; Lisp Interaction mode
(define-key lisp-interaction-mode-map [(control return)]
'my-reindent-then-newline-and-indent-and-indent-sexp)
;; (define-key lisp-interaction-mode-map [(control backspace)]
;; 'my-join-line-and-indent-sexp-or-backward-kill-word)
;; use C-M-i instead of
;; (define-key lisp-interaction-mode-map [(control meta tab)] 'lisp-complete-symbol)
(tempo-define-template "lisp-print-map" '("(map (lambda (x) ) " p ")"))
(define-key lisp-interaction-mode-map "\C-zim" 'tempo-template-emacs-lisp-print-message)
(font-lock-add-keywords
nil ;; 'emacs-lisp-mode
`(("\\"
(0 (progn (compose-region (match-beginning 0) (match-end 0)
,(make-char 'greek-iso8859-7 107))
nil)))))
(eval-after-load "scheme"
'(progn
(define-key scheme-mode-map [(control return)]
'my-reindent-then-newline-and-indent-and-indent-sexp)
;; (define-key scheme-mode-map [(control backspace)]
;; 'my-join-line-and-indent-sexp-or-backward-kill-word)
))
;;; clojure
(eval-after-load "clojure-mode"
'(progn (add-hook 'clojure-mode-hook
(lambda ()
(set (make-local-variable 'inferior-lisp-program)
"java -cp clojure.jar clojure.lang.Repl")))))
;;; snd
(autoload 'sndtr-mode "sndtr" "Major mode for editing Snd transcripts." t)
;; transcripts sndtr files
(add-to-list 'auto-mode-alist '("\\.trs\\'" . sndtr-mode))
;; marks snd files
(add-to-list 'auto-mode-alist '("\\.marks\\'" . scheme-mode))
(defun run-snd ()
(interactive)
(run-scheme "snd -notebook" "snd"))
(add-to-list 'same-window-buffer-names "*snd*")
;; Added "<" for Scheme "#"
(setq inferior-lisp-prompt "^[^<> \n]*>+:? *")
;(define-key inferior-scheme-mode-map [(meta down)] 'comint-next-prompt)
;(define-key inferior-scheme-mode-map [(meta up)] 'comint-previous-prompt)
(add-hook
'inferior-scheme-mode-hook
(lambda ()
;; no special variable for prompt in cmuscheme.el
(setq comint-prompt-regexp "^[^<>\n]*>+ *") ; added "<"
(define-key global-map "\C-zii"
(lambda ()
(interactive)
(let* ((proc (scheme-proc))
(m (marker-position (process-mark proc)))
(str
(save-excursion
(comint-send-string
proc
"(list (selection-position) (selection-length))\n")
(accept-process-output proc)
(set-buffer "*scheme*")
(buffer-substring
m
(marker-position (process-mark proc))))))
(insert str))))))
;;; dsssl
;; Make font-lock recognise more DSSSL keywords.
;; (setq scheme-font-lock-keywords
;; (cons '("(\\(make\\|element\\|style\\|mode\\|root\\|with-mode\\)[ \t\n]\
;; \\([0-9a-z.-]+\\|([^)]+)\\)"
;; (1 font-lock-keyword-face)
;; (2 font-lock-function-name-face))
;; scheme-font-lock-keywords))
;; Use Scheme mode for DSSSL files.
;; (add-to-list 'auto-mode-alist '("\\.dss?s?l$" . scheme-mode))
(add-to-list 'auto-mode-alist '("\\.ss$" . scheme-mode))
;;; perl
;; Use cperl mode instead of perl mode
;; PS: Don't use over-bloated cperl mode; use default perl mode instead
;; (defalias 'perl-mode 'cperl-mode)
;; (fset 'perl-mode 'cperl-mode)
(add-to-list
'auto-insert-alist
'(perl-mode
nil
"#!/usr/bin/perl -w" \n
"# -*- Perl -*-" \n
;; "# \$Id\$" \n
;; "# \$RCSfile\$\$Revision\$\$Date\$" \n
"# \$Revision\$" \n
\n
"while (<>) {" \n
> "chomp;" \n
> _ \n
> "print \"$_\\n\";\n"
"}\n"))
(tempo-define-template "perl-skeleton"
'("#!/usr/bin/perl -w\n# -*- Perl -*-\n# \$Revision\$\n\nwhile (<>) {\n chomp;\n "
p "\n}\n"))
(tempo-define-template "perl-s-skeleton" '("s/" p "//;"))
(tempo-define-template "perl-print-skeleton" '("print \"$_" p "\\n\";"))
(tempo-define-template "perl-while-skeleton" '("while (<>) {\n chomp;\n " p "\n}\n"))
(eval-after-load "perl-mode"
'(progn
;; (define-auto-insert 'perl-mode (lambda () (tempo-template-perl-skeleton)))
(define-key perl-mode-map "\C-ziw" 'tempo-template-perl-while-skeleton)
(define-key perl-mode-map "\C-zip" 'tempo-template-perl-print-skeleton)
(define-key perl-mode-map "\C-zis" 'tempo-template-perl-s-skeleton)))
;; Try to distinguish between Perl and Prolog file types
;; TODO: make/use external programs (a-la 'file')
;; but best solution is to use "-*- mode: -*-" in the first line
;; qv http://thread.gmane.org/gmane.emacs.devel/114377/focus=114713
(setq auto-mode-alist
(append '(("\\.perl\\'" . perl-mode)
("\\.pm\\'" . perl-mode)
;; pl files in *perl* dir are Perl files
;; ("perl.*\\.pl\\'" . perl-mode)
("\\.pl\\'" . perl-mode))
auto-mode-alist))
(defun my-pl-find-file-hook ()
;; To distinguish Prolog and Perl files with the same file extension
;; '.pl', it assumes that Perl programs begin with a comment '#',
;; but this doesn't work yet for Prolog shell scripts, so it's more
;; reliable to use file local variables with the needed mode specified.
(if (and (looking-at "#")
(or
;; This works when '.pl' is associated with Prolog mode
(string-match "Prolog" mode-name)
;; BTW, Perl mode fits perfectly for different conf-files
(equal mode-name "Fundamental")))
(perl-mode)))
;; (add-hook 'find-file-hooks 'my-pl-find-file-hook)
;; Create Perl links in the *Man* buffer
(eval-after-load "man"
'(progn
(add-hook
'Man-cooked-hook
(lambda ()
;; TODO: add to perl-mode.el? and cperl-mode.el?
(if (string-match "^\\([0-9]+ *\\)?perl" Man-arguments)
(Man-highlight-references0
"DESCRIPTION"
"\\(perl\\(?:[a-z0-9]+[a-z]\\|[a-z][a-z0-9]+\\)\\)[^a-z0-9]"
1 0 'Man-xref-man-page))))))
;;; prolog
(setq prolog-system 'swi)
(setq prolog-indent-width 8)
(setq prolog-electric-dot-flag t)
(setq prolog-program-switches
'((sicstus ("-i"))
(swi ("-G8M"))
(t nil)))
(setq prolog-info-predicate-index "(prolog)Predicates188")
;; Use better prolog-mode from http://www.emacswiki.org/emacs/PrologMode
;; renamed here to prolog2.el
;; (load "progmodes/prolog2.el")
;; (autoload 'run-prolog "prolog2" "Start a Prolog sub-process." t)
;; (autoload 'prolog-mode "prolog2" "Major mode for editing Prolog programs." t)
;; (autoload 'mercury-mode "prolog2" "Major mode for editing Mercury programs." t)
;; (setq outline-regexp "[0-9]+ \\?-") ; for *prolog*
(setq auto-mode-alist
(append '(
;; ("\\.pl?\\'" . 'prolog-mode) ; SWI Prolog
;; pl files in *prolog* dir are Prolog files
("prolog.*\\.pl?\\'" . prolog-mode) ; SWI Prolog
("\\.[Pp][Rr][Oo]\\'" . prolog-mode)
("\\.ari\\'" . prolog-mode) ; Arity Prolog
) auto-mode-alist))
;; Resolve file extension conflict between Octave and Mercury Prolog
;; in favor of Mercury Prolog
;; (add-to-list 'auto-mode-alist '("\\.m\\'" . octave-mode))
(add-to-list 'auto-mode-alist '("\\.m\\'" . mercury-mode))
(add-hook
'prolog-mode-hook
(lambda ()
(require 'prolog)
(setq prolog-system 'swi)
(define-key prolog-mode-map [(control f1)]
(lambda () (interactive) (my-search-prolog-doc-at-point)))
;;(fset 'prolog-add-predicate-comment
;; [C-f5 up up ?\M-3 ?% ? ?\M-2 C-right ?\C-k ?\C-m ?\M-2 ?% ? ? ])
(fset 'prolog-add-predicate-comment
[?\C-n ?\C-o C-f5 ?\C-a up ?\M-3 ?% ? ?\M-2 C-right ?\C-k ?\C-m ?\M-2 ?% ? ? ])
(define-key prolog-mode-map "\C-zic" 'prolog-add-predicate-comment)
;; (define-key prolog-mode-map "\C-zic"
;; (lambda () (interactive) (end-of-line) (insert-string " :- ")))
;; (define-key prolog-mode-map "\C-zi,"
;; (lambda () (interactive) (end-of-line) (insert-string ", ")))
;; (define-key prolog-mode-map "\C-zi."
;; (lambda () (interactive) (end-of-line) (insert-string ".") (newline)))
;; (defun prolog-outline-level () (- 4 (outline-level)))
(set (make-local-variable 'outline-regexp) "%%%+")
(set (make-local-variable 'outline-level) (lambda () (- 5 (outline-level))))
;; (setq outline-level 'prolog-outline-level)
;; global-font-lock-mode doesn't work with prolog.el, but works with prolog2.el
;; (font-lock-mode 1)
))
(add-hook
'prolog-inferior-mode-hook
(lambda ()
;; (setq comint-input-ring-file-name "~/.pl_history")
;; (comint-read-input-ring t)
;; THIS CAUSED TRANSIENT-MODE NOT-WORKING !!!
;; -> (add-hook 'pre-command-hook 'comint-write-input-ring)
(define-key prolog-inferior-mode-map [(control f1)]
(lambda () (interactive) (my-search-prolog-doc-at-point)))
(define-key prolog-inferior-mode-map "\C-zo" 'comint-kill-output-since-last-prompt)
(set (make-local-variable 'outline-regexp) "^[1-9][0-9]* \\?- ")
(set (make-local-variable 'outline-level) (lambda () 1))))
(defun my-search-prolog-doc-at-point ()
(let* ((wordchars "a-zA-Z_0-9")
(str
(concat "\^L\n\n"
(current-word)
;; (buffer-substring-no-properties
;; (save-excursion (skip-chars-backward wordchars) (point))
;; (save-excursion (skip-chars-forward wordchars) (point)))
"(")))
(view-file "~/doc/prog/prolog/PROLOG")
;; (set (make-local-variable 'outline-regexp) "^\\(Chapter [0-9]\\|\\)")
;; (make-local-variable 'outline-level)
(if (not (re-search-forward str nil t))
(progn
(goto-char (point-min))
(re-search-forward str nil t)))
(show-entry) ;?
(message str)))
;; for PROLOG manual:
;; outline-regexp: "Chapter\\|[0-9]\\.[0-9]+ .....\\|[0-9]+\\.[0-9]+\\.[0-9]+ ....."
;; outline-level: outline-level-for-prolog-manual
;; mode: outline-minor
;; (setq outline-regexp "Chapter\\|[0-9]+\\.[0-9]+ .....\\|[0-9]+\\.[0-9]+\\.[0-9]+ .....")
;; (setq outline-level (lambda ()
;; (save-excursion
;; (cond
;; ((looking-at "Chapter") 1)
;; ((looking-at "[0-9]+\\.[0-9]+ ") 2)
;; ((looking-at "[0-9]+\\.[0-9]+\\.[0-9]+ ") 3)))))
;; (defun outline-level-for-prolog-manual ()
;; (save-excursion
;; (cond
;; ((looking-at "Chapter") 1)
;; ((looking-at "[0-9]+\\.[0-9]+ ") 2)
;; ((looking-at "[0-9]+\\.[0-9]+\\.[0-9]+ ") 3))))
;;; erlang
;; TODO: for Yaws templates use mumamo with erlang-mode and html-mode
(add-to-list 'auto-mode-alist '("\\.yaws\\'" . erlang-mode))
;;; haskell
;; also qv comment in (qv "files.el" "^(defvar interpreter-mode-alist")
(add-to-list 'interpreter-mode-alist '("runhugs" . literate-haskell-mode))
;;; html
;; These are needed to set before loading sgml-mode.el:
;; (setq sgml-quick-keys t)
(setq html-quick-keys t)
(eval-after-load "sgml-mode"
'(progn
(modify-syntax-entry ?. "." sgml-mode-syntax-table)
(modify-syntax-entry ?: "." sgml-mode-syntax-table)
(setq html-tag-face-alist (append '(("a" . underline))
html-tag-face-alist))))
(eval-after-load "sgml-mode"
'(progn
(define-skeleton html-headline-1
"HTML level 1 headline tags."
nil
"