emacs不同情况下的{}补全该怎么做
-
- 帖子: 871
- 注册时间: 2006-01-03 20:44
emacs不同情况下的{}补全该怎么做
在C语言中{}主要出现于两种情况,一种是函数体,一种是数组赋值。在函数体中{}自动补全最好是自动断行,光标在中间。
int main(void){
}
而如果是数组赋值时则不能断行。int a[2] = {1,3};
在EMACS中如何针对两种不同情况智能补全呢?
int main(void){
}
而如果是数组赋值时则不能断行。int a[2] = {1,3};
在EMACS中如何针对两种不同情况智能补全呢?
-
- 帖子: 750
- 注册时间: 2006-03-19 11:39
-
- 帖子: 871
- 注册时间: 2006-01-03 20:44
Re: emacs不同情况下的{}补全该怎么做
谢谢。我也这么想,就是不懂lisp语言,不知该如何做。能不能帮个忙。kardinal 写了:判断 { 前面是 )还是 = 不就行了
-
- 帖子: 750
- 注册时间: 2006-03-19 11:39
Re: emacs不同情况下的{}补全该怎么做
不知道你用什么方式实现的括号补全,不过惯用法是 skeleton-pair-insert-maybe
skeleton 的代码大概看了下,说实话,没看明白
……有点复杂
好在 lisp 抽象机制比较强大,不用了解其实现,也可以用点简单粗暴的方式改变其运行方式
下面的我试了下,初步可以运行……有什么问题再说吧
[lisp]
(defadvice skeleton-pair-insert-maybe (around xxx activate)
(if (eq last-command-event 123)
(let ((skeleton-pair-alist
(save-excursion
(skip-chars-backward " \t")
(if (eq (char-before (point)) 61)
'((?\{ _ "}"))
'((?{ \n > _ \n ?} >))))))
ad-do-it)
ad-do-it))
[/lisp]
缺点就是补全 “{” 的时候,完全无视你自己设置的 skeleton-pair-alist
当然解决这个也不难……不过要处理的列表复杂点而已,是个体力活,而且基本没有必要
因为这个功能俺不大用
skeleton 的代码大概看了下,说实话,没看明白

好在 lisp 抽象机制比较强大,不用了解其实现,也可以用点简单粗暴的方式改变其运行方式
下面的我试了下,初步可以运行……有什么问题再说吧
[lisp]
(defadvice skeleton-pair-insert-maybe (around xxx activate)
(if (eq last-command-event 123)
(let ((skeleton-pair-alist
(save-excursion
(skip-chars-backward " \t")
(if (eq (char-before (point)) 61)
'((?\{ _ "}"))
'((?{ \n > _ \n ?} >))))))
ad-do-it)
ad-do-it))
[/lisp]
缺点就是补全 “{” 的时候,完全无视你自己设置的 skeleton-pair-alist
当然解决这个也不难……不过要处理的列表复杂点而已,是个体力活,而且基本没有必要
因为这个功能俺不大用

-
- 帖子: 871
- 注册时间: 2006-01-03 20:44
Re: emacs不同情况下的{}补全该怎么做
谢谢楼上的付出的热情、智力与体力。谢谢。
-
- 帖子: 750
- 注册时间: 2006-03-19 11:39
Re: emacs不同情况下的{}补全该怎么做

把上面的 '((?{ \n > _ \n ?} >)) 改成 skeleton-pair-alist
可以在一般情况下使用全局 skeleton-pair-alist 的设定
不过感觉没有必要,维持原样就挺好
-
- 帖子: 750
- 注册时间: 2006-03-19 11:39
Re: emacs不同情况下的{}补全该怎么做
[lisp]
(defadvice skeleton-pair-insert-maybe (around xxx activate)
(let ((skeleton-pair-alist skeleton-pair-alist)
(c-before
(lambda(x)(save-excursion
(skip-chars-backward " \t")
(eq (char-before (point)) x)))))
(if (and (eq last-command-event 123)(funcall c-before 61))
(setq skeleton-pair-alist '((?\{ _ "}"))))
ad-do-it))
[/lisp]
这个是整理之后的,虽然比原来的效率差一点(对于人来说是可以忽略的),但是方便自己添加规则
把中间那句 if 改成 cond 就可以匹配许多的规则了
如果想更方便的修改添加,可以用表驱动的方式,弄个查询表
……对于我来说,给一个全局变量取名的难度实在太高了……假设是 aaa 吧(你可以改成自己喜欢的名字)
[lisp]
(defadvice skeleton-pair-insert-maybe (around xxx activate)
(let ((lst aaa)
(skeleton-pair-alist skeleton-pair-alist))
(mapc
(lambda(x)
(if (and (eq last-command-event (cadr x))(eval (car x)))
(setq skeleton-pair-alist (list (cdr x)))))
lst)
ad-do-it))
(defun char-bf (x)
(save-excursion
(skip-chars-backward " \t")
(eq (char-before (point)) x)))
(setq aaa
'(
((char-bf ?=) . (?\{ _ "}"))
((or (char-bf ?/)(char-bf ?=)) . (?\[ n _ n "]"))
))
[/lisp]
(defadvice skeleton-pair-insert-maybe (around xxx activate)
(let ((skeleton-pair-alist skeleton-pair-alist)
(c-before
(lambda(x)(save-excursion
(skip-chars-backward " \t")
(eq (char-before (point)) x)))))
(if (and (eq last-command-event 123)(funcall c-before 61))
(setq skeleton-pair-alist '((?\{ _ "}"))))
ad-do-it))
[/lisp]
这个是整理之后的,虽然比原来的效率差一点(对于人来说是可以忽略的),但是方便自己添加规则
把中间那句 if 改成 cond 就可以匹配许多的规则了
如果想更方便的修改添加,可以用表驱动的方式,弄个查询表
……对于我来说,给一个全局变量取名的难度实在太高了……假设是 aaa 吧(你可以改成自己喜欢的名字)
[lisp]
(defadvice skeleton-pair-insert-maybe (around xxx activate)
(let ((lst aaa)
(skeleton-pair-alist skeleton-pair-alist))
(mapc
(lambda(x)
(if (and (eq last-command-event (cadr x))(eval (car x)))
(setq skeleton-pair-alist (list (cdr x)))))
lst)
ad-do-it))
(defun char-bf (x)
(save-excursion
(skip-chars-backward " \t")
(eq (char-before (point)) x)))
(setq aaa
'(
((char-bf ?=) . (?\{ _ "}"))
((or (char-bf ?/)(char-bf ?=)) . (?\[ n _ n "]"))
))
[/lisp]
-
- 帖子: 750
- 注册时间: 2006-03-19 11:39
Re: emacs不同情况下的{}补全该怎么做
[lisp]
(setq aaa
'(
((char-bf ?=) . (?\{ _ "}"))
((or (char-bf ?/)(char-bf ?=)) . (?\[ n _ n "]"))
((char-bf '(?+ ?-)) . (?\\ "+" _ "+\\"))
((bolp) . (?/ "*" _ "*/"))
((not (bolp)) . (?/ _))
))
(define-key-s 1 '("/" "\\") 'skeleton-pair-insert-maybe)
[/lisp]
玩了会 'skeleton-pair-insert-maybe ,挺有意思
列表的最后两条,可以实现在行首 “/” 自动变为 “/*_*/”
第二个和第三个的条件判断其实差不多,要使第三个正确,需要改下 char-bf 函数
[lisp]
(defun char-bf (x)
(let ((x (if (listp x) x (list x))))
(save-excursion
(skip-chars-backward " \t")
(memq (char-before (point)) x))))
[/lisp]
(setq aaa
'(
((char-bf ?=) . (?\{ _ "}"))
((or (char-bf ?/)(char-bf ?=)) . (?\[ n _ n "]"))
((char-bf '(?+ ?-)) . (?\\ "+" _ "+\\"))
((bolp) . (?/ "*" _ "*/"))
((not (bolp)) . (?/ _))
))
(define-key-s 1 '("/" "\\") 'skeleton-pair-insert-maybe)
[/lisp]
玩了会 'skeleton-pair-insert-maybe ,挺有意思
列表的最后两条,可以实现在行首 “/” 自动变为 “/*_*/”
第二个和第三个的条件判断其实差不多,要使第三个正确,需要改下 char-bf 函数
[lisp]
(defun char-bf (x)
(let ((x (if (listp x) x (list x))))
(save-excursion
(skip-chars-backward " \t")
(memq (char-before (point)) x))))
[/lisp]
-
- 帖子: 871
- 注册时间: 2006-01-03 20:44
Re: emacs不同情况下的{}补全该怎么做
太感谢了,虽然现在还看不太懂,不过能用就是好。
-
- 帖子: 750
- 注册时间: 2006-03-19 11:39
Re: emacs不同情况下的{}补全该怎么做
死了 N 多脑细胞,终于给起了个合适的名字 my-skeleton-pair-alist
以后只要改改这个列表的内容就可以了
现在不需要自己绑定这些按键了,下面第四句会自己在 my-skeleton-pair-alist 里面查找按键,
并绑定到 skeleton-pair-insert-maybe
char-bf 用来判断当前位置前的字符,并忽略空格和制表符
条件判断是一个S表达式,返回一个布尔值即可(除了 nil 的任何值都是 t)
列表是从前向后读取的,也就是说后面的覆盖前面的
比如下面列表中的4 、5项 (bolp) 的值会覆盖 t,也就是说特殊情况要在后面处理
这个列表用 mapc 处理的,所以会遍历里面的每一项,不要弄的太长,我估摸着超过一千条就能感觉到影响了
如果有必要,可以改用其它更快速的方式处理列表,比如用 catch throw 之类
不过这个列表建议 make-local-variable ,这样可以为不同的模式分别设置。因此这个列表不会太长
mapc 应该没有太大的问题
[lisp]
(defvar my-skeleton-pair-alist
'(
((char-bf ?=) . (?\{ _ "}"))
((or (char-bf ?/)(char-bf ?=)) . (?\[ n _ n "]"))
((char-bf '(?+ ?-)) . (?\\ "+" _ "+\\"))
(t . (?/ _))
((bolp) . (?/ "*" n _ n "*/"))
))
(defadvice skeleton-pair-insert-maybe (around xxx activate)
(let ((skeleton-pair-alist skeleton-pair-alist))
(mapc
(lambda(x)
(if (and (eq last-command-event (cadr x))(eval (car x)))
(setq skeleton-pair-alist (list (cdr x)))))
my-skeleton-pair-alist)
ad-do-it))
(defun char-bf (x)
(let ((x (if (listp x) x (list x))))
(save-excursion
(skip-chars-backward " \t")
(memq (char-before (point)) x))))
(mapcar
(lambda(x)
(define-key (current-local-map)
(eval `(kbd ,(char-to-string (cadr x))))
'skeleton-pair-insert-maybe))
my-skeleton-pair-alist)
[/lisp]
以后只要改改这个列表的内容就可以了
现在不需要自己绑定这些按键了,下面第四句会自己在 my-skeleton-pair-alist 里面查找按键,
并绑定到 skeleton-pair-insert-maybe
char-bf 用来判断当前位置前的字符,并忽略空格和制表符
条件判断是一个S表达式,返回一个布尔值即可(除了 nil 的任何值都是 t)
列表是从前向后读取的,也就是说后面的覆盖前面的
比如下面列表中的4 、5项 (bolp) 的值会覆盖 t,也就是说特殊情况要在后面处理
这个列表用 mapc 处理的,所以会遍历里面的每一项,不要弄的太长,我估摸着超过一千条就能感觉到影响了
如果有必要,可以改用其它更快速的方式处理列表,比如用 catch throw 之类
不过这个列表建议 make-local-variable ,这样可以为不同的模式分别设置。因此这个列表不会太长
mapc 应该没有太大的问题
[lisp]
(defvar my-skeleton-pair-alist
'(
((char-bf ?=) . (?\{ _ "}"))
((or (char-bf ?/)(char-bf ?=)) . (?\[ n _ n "]"))
((char-bf '(?+ ?-)) . (?\\ "+" _ "+\\"))
(t . (?/ _))
((bolp) . (?/ "*" n _ n "*/"))
))
(defadvice skeleton-pair-insert-maybe (around xxx activate)
(let ((skeleton-pair-alist skeleton-pair-alist))
(mapc
(lambda(x)
(if (and (eq last-command-event (cadr x))(eval (car x)))
(setq skeleton-pair-alist (list (cdr x)))))
my-skeleton-pair-alist)
ad-do-it))
(defun char-bf (x)
(let ((x (if (listp x) x (list x))))
(save-excursion
(skip-chars-backward " \t")
(memq (char-before (point)) x))))
(mapcar
(lambda(x)
(define-key (current-local-map)
(eval `(kbd ,(char-to-string (cadr x))))
'skeleton-pair-insert-maybe))
my-skeleton-pair-alist)
[/lisp]
-
- 帖子: 750
- 注册时间: 2006-03-19 11:39
Re: emacs不同情况下的{}补全该怎么做
运行时修改这个列表,可能不会立即生效(新增的按键不会被绑定)
可以弄个针对 my-skeleton-pair-alist 的方法,修改的同时更新热键
但是 elisp 对于对象和闭包的支持都比较纠结,自己弄个函数凑合下吧
可以弄个针对 my-skeleton-pair-alist 的方法,修改的同时更新热键
但是 elisp 对于对象和闭包的支持都比较纠结,自己弄个函数凑合下吧
-
- 帖子: 871
- 注册时间: 2006-01-03 20:44
Re: emacs不同情况下的{}补全该怎么做
太厉害了,表示佩服!!!