;; 下面的几个函数可以实现自动增加数字,和循环改变文本的功能。定义方法是 ;; 1. 一个 (regexp . (lambda () ....) 的方式。 下面的第一个定义就提供了自动增加 ;; 和减少数字的功能。 ;; 2. 一个含有字符串的 list , 那么就会在这些字符串中循环选择。 ;; M-x wcy-rotate-text 可以接受 C-u 的参数,负数表示减少数字或者反向循环。 ;; 参数的大小可以指定增加或者减少多少,或者循环的步长。 (defvar wcy-rotate-text-definations '(("-?[0-9]+" . (lambda () (format "%d" (+ rotate-arg (string-to-number (match-string 0)))))) ("zero" "one" "two" "three" "four" "five" "six" "seven" "eight" "nine") ("Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday") ) " a list of ROT text defination. each element is a defination. element can be a list of string. element can be a cons. (REGEXP . func) if REGEXP matched, func is called with no args, return value is the next value. ") (defun wcy-rotate-text-aux () (catch 'break (mapc #'(lambda (def) (let ((regexp (if (functionp (cdr def)) (car def) (mapconcat 'regexp-quote def "\\|"))) (func (if (functionp (cdr def)) (cdr def) #'(lambda () (let* ((l (length def)) (r (length (member (match-string 0) def))) (i (% (+ rotate-arg (- l r)) l))) (format "%s" (nth i def))))))) (if (re-search-forward regexp (line-end-position) t nil) (throw 'break (funcall func))))) wcy-rotate-text-definations) nil)) (defun wcy-rotate-text(rotate-arg) (interactive "p") (let ((x (wcy-rotate-text-aux))) (when x (replace-match x) (goto-char (match-beginning 0)))))
;;这个功能绑定在 C-3 上。这个功能就是根据光标的所在位置,智能的选择一块区域,也就 ;;是设置成为当前的 point 和 mark。这样就可以方便的拷贝或者剪切,或者交换他们的位 ;;置。 ;;如果当前光标在一个单词上,那么区域就是这个单词的开始和结尾分别。 ;;如果当前光标在一个连字符上,那么就选择包含连字符的一个标识符。 ;;这个两个的是有区别的,而且根据不同的 mode 的语法定义,连字符和单词的定义也不一样。 ;;例如 C mode 下, abc_def_xxx , 如果光标停在 abc 上,那么就会选择 abc 这个单词。 如果 ;;停在下划线上,那么就会选择 abc_def_xxx 。 ;;如果当前光标在一个双引号,单引号,一个花括号,方括号,圆括号,小于号,或者大于号, ;;等等,那么就会选择他们对应的另一个括号之间的区域。 引号中的 escape 字符也是可以 ;;自动识别的。嵌套关系也是可以识别的。这一点可以和 VIM 中的 % 的功能类比。 (defun wcy-mark-some-thing-at-point() (interactive) (let* ((from (point)) (a (mouse-start-end from from 1)) (start (car a)) (end (cadr a)) (goto-point (if (= from start ) end start))) (if (eq last-command 'wcy-mark-some-thing-at-point) (progn ;; exchange mark and point (goto-char (mark-marker)) (set-marker (mark-marker) from)) (push-mark (if (= goto-point start) end start) nil t) (when (and (interactive-p) (null transient-mark-mode)) (goto-char (mark-marker)) (sit-for 0 500 nil)) (goto-char goto-point)))) (define-key global-map (kbd "C-3") 'wcy-mark-some-thing-at-point) (define-key global-map (kbd "M-C-SPC") 'wcy-mark-some-thing-at-point)
M-x align-regexp 可以方便的对齐一些文字。 例如
Fred (123) 456-7890
Alice (123) 456-7890
Mary-Anne (123) 456-7890
Joe (123) 456-7890
选择这段文字之后, M-x align-regexp ,然后根据提示输入, ``('' 这样就可以得到下 面的结果:
Fred (123) 456-7890
Alice (123) 456-7890
Mary-Anne (123) 456-7890
Joe (123) 456-7890
我把 C-w 绑定 backward-kill-word, 这样就和 bash 的 input-line 是一致的了。我试 了试,还挺好用。但是原来的 C-w 是和 kill-region 绑定的。改变习惯还是很难的。以前 我不喜欢 transient-mark-mode ,但是现在发现她可以派上用场了。可以在激活选择区域 的时候,C-w 和 kill-region 绑定,否则和 backward-kill-word 绑定,感觉不错。
(defmacro wcy-define-2bind-transient-mode (funname cmd-mark-active cmd-mark-no-active) `(defun ,funname () (interactive) (if mark-active (call-interactively ,cmd-mark-active) (call-interactively ,cmd-mark-no-active)))) ;; 和 bash 中的类似的快键,不用再按 backspace 了。 (global-set-key "\C-w" 'wcy-backward-kill-word-or-kill-region) (wcy-define-2bind-transient-mode wcy-backward-kill-word-or-kill-region 'kill-region 'backward-kill-word)
我定义了一个 macro , 可以方便的定义这种双重绑定,也就是,在 mark-active 时运行 一个函数,否则运行另一个函数。