原创:方便的emacs-c扩展
version: 0.3
自己完成了点emacs的小功能
1:自动的添加本地变量的定义,不需要在编写函数的时候从函数的一个地方跳到函数的开始部分然后在跳回来。
2:自动的添加头包含
3:窗口漂移,buffer漂移,非常实用
4:触发窗口最大化,非常实用(有点bug,不影响正常使用,修补中)
5:一键插入if for while等block。
注释:非常感谢楼下的支持。这是这个程序的第二版本,让程序更具有函数式的风格,我刚开始学习emacs和lisp,其中的设计风格不怎么好,希望大家多指正。完全不是谦虚:感谢有lisp这门语言。
关于解释器:我用的开发环境比较混乱elisp, slime, clisp, emacs-lisp,可能有的代码在别的emacs中不能执行,但是我敢肯定在emacs23/gentoo 中绝对可以使用。
;; toggle max window.
(setq window-min-heigh 1)
(setq window-min-width 1)
(setf (symbol-function 'toggle-window-max)
(lexical-let ((toggle-done nil)
(increament-width 0)
(increament-height 0))
(lambda ()
(interactive)
(if toggle-done
(progn
(shrink-window increament-height)
(shrink-window-horizontally increament-width)
(setf increament-height 0)
(setf increament-width 0)
(setf toggle-done (not toggle-done)))
(progn
(setf increament-width (- (frame-width) (window-width) (+ window-min-width 2)))
(setf increament-height (- (frame-height) (window-height) (+ window-min-height 2)))
(setf toggle-done (not toggle-done))
(enlarge-window-horizontally increament-width)
(enlarge-window increament-height))))))
(global-set-key (kbd "M-l") 'toggle-window-max)
;; end toggle max window.
;; fly in buffers.
(setq *toggle-fly-all-buffers* nil)
(defun toggle-fly-all-buffers ()
(interactive)
(setq *toggle-fly-all-buffers* (not *toggle-fly-all-buffers*)))
(defconst +common-system-buffers+ '("*shell*" "*Message*" "*slime-repl clisp*" "*scratch*" "terminal"))
(defun user-bufferp (buffer)
(if (not (string-match "^[[:space:]]*?\*.*?\*[[:space:]]*$" (buffer-name buffer)))
t))
(defun all-bufferp (buffer)
(if (or (member (buffer-name buffer) +common-system-buffers+)
(user-bufferp buffer))
t))
(defun %get-all-buffers% (buffers)
(remove-if-not #'all-bufferp buffers))
(defun %get-user-buffers% (buffers)
(remove-if-not #'user-bufferp buffers))
(defun get-all-buffers (all)
(interactive)
(if all (funcall #'%get-all-buffers% (buffer-list))
(funcall #'%get-user-buffers% (buffer-list))))
(defun switch-buffer-to-current-window (&optional buffer)
(if (not buffer) (return))
(bury-buffer (buffer-name (current-buffer)))
(switch-to-buffer (buffer-name buffer)))
(defun fly-in-buffers ()
(interactive)
(switch-buffer-to-current-window
(car (remove (current-buffer) (get-all-buffers *toggle-fly-all-buffers*)))))
(global-set-key (kbd "M-q") 'fly-in-buffers)
;; end fly in buffers.
(defun fly-in-windows ()
(interactive)
(other-window 1))
(global-set-key (kbd "M-j") 'fly-in-windows)
;; newline.
(defun add-newline ()
(interactive)
(move-end-of-line 1)
(newline-and-indent)
)
(global-set-key "M-o" 'add-newline)
;; prev newline.
(global-set-key (kbd "M-i") 'upto-create-newline)
(defun upto-add-newline ()
(interactive)
(previous-line 1)
(add-newline)
)
(defun find-next-blank-line ()
(loop
while (split-string (thing-at-point 'line) split-string-default-separators t)
do (next-line)))
(defun goto-first-blank-line ()
(goto-char (point-min))
(find-next-blank-line))
(defun c-goto-function-first-blank-line ()
(interactive)
(c-beginning-of-defun)
(find-next-blank-line))
(defun c-prompt-function (prompt func)
(let ((variable (read-string prompt)))
(multiple-value-bind (start end)
(values (string-match "\w.*\w[[:space:]]*$" variable) (match-end 0))
(if (> (length (substring variable start end)) 0)
(funcall func (substring variable start end))))))
(defun c-insert-control ()
(insert "(")
(save-excursion
(insert ")")
(add-newline)
(insert "{")
(add-newline)
(insert "}")
(indent-for-tab-command)
(upto-add-newline)))
;; insert variable.
(defun %c-insert-statement-variable% (variable)
(save-excursion
(c-goto-function-first-blank-line)
(c-indent-line-or-region)
(insert (format "%s;n" (substring variable start end)))))
(defun c-insert-statement-variable ()
(c-prompt-function "variable define: " '%c-insert-statement-variable%))
;; end insert variable
;; insert header file.
(defconst +c-common-header+ "stdio stdlib string unistd sys/types errno")
(defun c-insert-statement-header ()
(c-prompt-function "header files: " '%c-insert-statement-header%))
(defun %c-insert-statement-header% (header-files)
(save-excursion
(goto-first-blank-line)
(mapcar (lambda (header-file) (insert (format "#include <%s.h>n" header-file)))
(split-string header-files split-string-default-separators t))))
(defun c-insert-common-header-files ()
(interactive)
(%c-insert-statement-header% +c-common-header+))
;; end insert header file.
;; insert control
(defconst +c-statement-control+ '("if" "for" "while"))
(defconst +c-statement-control-prefix+ "c-insert-statement-")
(defun %c-insert-statement-control% (control)
(let ((x (read-from-string (concat +c-statement-control-prefix+ control))))
(eval `(setf (symbol-function ',(car x))
'(lambda () (progn
(add-newline)
(insert (concat ,control " "))
(c-insert-control)))))))
;; end insert control
(defun c-insert-statement-setup ()
(interactive)
(mapcar #'(lambda (control) (%c-insert-statement-control% control)) +c-statement-control+)
(define-prefix-command 'c-insert-statement-map)
(local-set-key "M-u" 'c-insert-statement-map)
(local-set-key "M-ui" (lambda () (interactive) (c-insert-statement 'if)))
(local-set-key "M-uf" (lambda () (interactive) (c-insert-statement 'for)))
(local-set-key "M-uw" (lambda () (interactive) (c-insert-statement 'while)))
(local-set-key "M-uv" (lambda () (interactive) (c-insert-statement 'variable)))
(local-set-key "M-uh" (lambda () (interactive) (c-insert-statement 'header))))
(defconst c-insert-statement-category
'((if . c-insert-statement-if)
(while . c-insert-statement-while)
(header . c-insert-statement-header)
(variable . c-insert-statement-variable)
(for . c-insert-statement-for)))
(defun c-insert-statement (category)
(let ((pair (assoc category c-insert-statement-category)))
(when pair (funcall (cdr pair)))))
[ 本帖最后由 wojiaohesen 于 2009-11-9 13:26 编辑 ]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
i want to do this better with functional programming,
a moment.
最大化可以用 switch-to-buffer-other-frame/c-x 5 b 代替。这样会新开一个 frame,用完后 delete-frame/c-x 5 0 就可以了。
我测试了 toggle-max 部分,碰到一些问题:
1、在 X 模式下不正常,无法缩回来。原因是一些参数跟字符终端不一致,所以在放大时 kill 掉了其它窗口。
2、在字符终端模式下,如果以 c-2 方式打开两个窗口,按 M-l 也不正常。此时 enlarge-window-horizontally 会报错,因为横向没有其它窗口。
3、第一行代码 (setq window-min-heigh 1) 变量少写了个 t
4、如果横向超过 2 个窗口,估计要出问题。纵向有多个窗口时估计也会出问题。楼主调试时使用的窗口布局是怎么样的?
ps: 通过研究 lz 的代码,了解了不少 emacs/elisp 的知识,谢谢 lz。
我这里好像最大化后就缩不回来了,我再调一下。
如果你能告诉我那个正则是想滤出或滤掉哪种 buffer 名,那么理解起来就容易了。
setq 在该情况下可以代替setf
那个词语的意思是触发:呵呵。希望自己没有把英文写错。你按下那些键,窗口最大,在按下窗口回复原状。
正则表达式我看了些时间,终于有了感觉,当然在处理文本的时候很方便,但是很多书籍都非常垃圾,他们常常误导你,比方说sed 's/.../../'他们告诉你这是个替换,这纯粹是扯淡,但是只有很长时间之后你才知道他们是在扯淡。建议你看perl的正则语法,几乎现在的语言的正则都是从哪里学习到的,但是基本上都是没有学到位:比方说零宽匹配。
看了 lz 的 4 和 3,有一些疑问。
setf 可以用 setq 替代吧,如果用 setq,就不需要 cl-macs 了。
toggle-window-max 的功能没看明白,试用了一下,好像是把当前窗口最大化,那个 toggle 如何理解呢?
fly-in-buffers 中 toggle 的作用比较明显,根据一个给定变量的值,决定取全部 buffer 还是部分 buffer。不过 string-match 的正则看不懂,正则是只写的,
lz 能帮忙解释一下这些疑问吗?
是的。用 (require 'cl) 可以加载 cl-macs.el
谢谢。
cl-macs.el 应该是emacs的一部分
我的 emacs 没有 setf,楼主是自己实现的 setf 还是加了某个包?