免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4740 | 回复: 9
打印 上一主题 下一主题

原创:方便的emacs-c扩展 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-10-19 09:06 |只看该作者 |倒序浏览
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 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-10-19 21:07 |只看该作者
我的 emacs  没有 setf,楼主是自己实现的 setf 还是加了某个包?

论坛徽章:
0
3 [报告]
发表于 2009-10-20 11:42 |只看该作者

回复 #2 retuor 的帖子

setf is a Lisp macro in `cl-macs.el'.

(setf place val place val ...)

Set each place to the value of its val.
This is a generalized version of `setq'; the places may be symbolic
references such as (car x) or (aref x i), as well as plain symbols.
For example, (setf (cadar x) y) is equivalent to (setcar (cdar x) y).
The return value is the last val in the list.

cl-macs.el 应该是emacs的一部分

论坛徽章:
0
4 [报告]
发表于 2009-10-21 00:26 |只看该作者
原帖由 DQP 于 2009-10-20 11:42 发表

cl-macs.el 应该是emacs的一部分



是的。用 (require 'cl) 可以加载 cl-macs.el

谢谢。

论坛徽章:
0
5 [报告]
发表于 2009-10-21 00:37 |只看该作者
看了 lz 的 4 和 3,有一些疑问。

setf 可以用 setq 替代吧,如果用 setq,就不需要 cl-macs 了。

toggle-window-max 的功能没看明白,试用了一下,好像是把当前窗口最大化,那个 toggle 如何理解呢?

fly-in-buffers 中 toggle 的作用比较明显,根据一个给定变量的值,决定取全部 buffer 还是部分 buffer。不过 string-match 的正则看不懂,正则是只写的,

lz 能帮忙解释一下这些疑问吗?

论坛徽章:
0
6 [报告]
发表于 2009-10-23 19:18 |只看该作者
原帖由 retuor 于 2009-10-21 00:37 发表
看了 lz 的 4 和 3,有一些疑问。

setf 可以用 setq 替代吧,如果用 setq,就不需要 cl-macs 了。

toggle-window-max 的功能没看明白,试用了一下,好像是把当前窗口最大化,那个 toggle 如何理解呢?

...



setq 在该情况下可以代替setf
那个词语的意思是触发:呵呵。希望自己没有把英文写错。你按下那些键,窗口最大,在按下窗口回复原状。
正则表达式我看了些时间,终于有了感觉,当然在处理文本的时候很方便,但是很多书籍都非常垃圾,他们常常误导你,比方说sed 's/.../../'他们告诉你这是个替换,这纯粹是扯淡,但是只有很长时间之后你才知道他们是在扯淡。建议你看perl的正则语法,几乎现在的语言的正则都是从哪里学习到的,但是基本上都是没有学到位:比方说零宽匹配。

论坛徽章:
0
7 [报告]
发表于 2009-10-23 20:45 |只看该作者
我这里好像最大化后就缩不回来了,我再调一下。

如果你能告诉我那个正则是想滤出或滤掉哪种 buffer 名,那么理解起来就容易了。

论坛徽章:
0
8 [报告]
发表于 2009-10-23 22:32 |只看该作者
我测试了 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。

论坛徽章:
0
9 [报告]
发表于 2009-10-25 16:04 |只看该作者
最大化可以用 switch-to-buffer-other-frame/c-x 5 b 代替。这样会新开一个 frame,用完后 delete-frame/c-x 5 0 就可以了。

论坛徽章:
0
10 [报告]
发表于 2009-10-28 21:40 |只看该作者

回复 #9 retuor 的帖子

i want to do this better with functional programming,
a moment.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP