介绍一些Emacs功能强大的函数
作者: xilbert
- 1 字符串类
- 2 hook类函数
- 3 用来高亮的函数
- 4 编译类函数
- 5 将这些函数串起来
1 字符串类
string-match 函数: 用指定的正则表达式去匹配字符串,将匹配的结果放到 match-data中。(match-data 用于存储emacs中字符串模式匹配中的匹配结果) 让我们看一个例子吧!
例 1:
1 2 3 |
(setq mystr "The quick fox jumped quickly.") (string-match "\\(qu\\)\\(ick\\)"mystr) =>副作用:将匹配结果存储到match-data中 |
这条语句的意思是:用\(qu\)\(ick\) 模式对mystr进行搜索,将匹配的结果存储,并且也存储分组1\(qu\) 和分组2 \(ick\)的匹配结果。
那么怎么取出匹配的结果呢? 答案是使用 match-string
1 2 3 |
(match-string 0 mystr) =>结果为quick,也就是模式匹配的结果 (match-string 1 mystr) =>结果为qu ,也就是第一个分组的匹配结果 (match-string 2 mystr) =>结果为ick ,也就是第二个分组的匹配结果 |
string-match 是用正则表达式去搜索字符串的,如果你想替换字符串,那怎么办呢? 那就要用到replace-regexp-in-string。
replace-regexp-in-string 函数:
用指定的正则表示式对字符串去搜索,将搜索到的模式用指定的字符串对原字符串进行替换。这个函数是非破坏性的,不会将你的原字符串破坏,函数返回的结果就是替换结果。
例1 :
假如你想将”d:/gnu/” 替换为”d:\\gnu\\” ,你可以这样写:
(replace-regexp-in-string "/" "\\\\" "d:/gnu/") |
那么为什么将替代字符串写成\\\\,而不是\\ ? 实际上在emacs的正则表示式中,\\\\才代表一个\,而emacs的普通字符串中\\代表\ 。
问题1:emacs 的正则表示达式中\太多了,能不能用个函数将\(hello\) 转化为\\(hello\\) ?
答案 :我也想知道!在emacs 中,我还没找到哪个函数能将“\(hello\)”转化为”\\(hello\\)”,这是字符串转义的缘故。我只能用一个比较拙劣的方法来帮助我写emacs style regexp ——用一段perl代码:
1 2 3 4 5 |
#!/usr/bin/perl print "please input a raw regexp ,i will generic a emacs style regexp\n"; $str =<STDIN>; $str =~ s/\\/\\\\/g; print $str; |
问题2:如果你想将^ . * $ 等特殊字符作为普通字符,你不想手动写成^ ,\\. 等形式,有什么办法帮助你吗?
答 :用 regexp-quote 函数。 例:(regexp-quote “^”) 自动生成”^”
问题3:如果你想用正则表达式表达搜索”hello” 或”world” ,你不想手动写成”hello\\|world”,有无简化的办法?
答: regexp-opt 可以办到。 例:(regexp-opt ‘(“hello” “world”)) 输出了”\\(?:hello\\|world\\)”
让我们再次回到replace-regexp-in-string函数来,它的功能真的很强大,替代字符串中还可以引用分组
例2 : (replace-regexp-in-string “\\(hello\\)\\(world\\)” “\\2\\1″ “helloworld”)
这个表达式的意思是:用\(hello\)\(world\)模式对“helloworld”进行搜索,将搜索到的结果用“\\2\\1”进行替换。函数返回了”worldhello”
2 hook类函数
emacs 中存在大量的hook ,有emacs-lisp-mode-hook ,c-mode-hook 等,基本上一个mode就提供了一个hook 。那么hook的本质是什么,我们能不能设计一个自己的hook ? 实际上,hook 是一个elisp 表,这个表中存放着要被调用的函数的符号(或代码)。
让我们用一个例子说明一下吧!
1 2 3 4 5 6 7 8 |
(defvar myhook nil) ;;定义myhook为空表 (add-hook 'myhook '(lambda ()(insert "fun1 was called "))) ;;将这个匿名函数1加入到myhook表中去(add-hook 'myhook '(lambda ()(insert "fun2 was called "))) ;;将匿名函数2加入myhook表中去(run-hooks 'myhook) ;; =>执行这条语句会在光标后插入fun2 was called fun1 was called |
那么为什么会先执行匿名函数2呢,而不是匿名函数1呢?这是因为add-hook 会将函数插入到myhook列表的头部,并且run-hooks 是从myhook头执行到尾的,因此匿名函数2会先执行。
那么这样设计有什么好处呢?好处是比较明显的,比如用户执行了(add-hook ‘c-mode-hook ‘myfun),其中myfun是要修改了c-mode中的某个变量值的,但不巧的是,系统在此之前就执行了(add-hook ‘c-mode-hook ‘firstfun),并且firstfun也要设置这个变量的值。那么通过这样设计,你的修改将不会成功(因为你的修改会被系统的系统覆盖),这样就保证了用户不能随意地改变mode的状态,保证了系统的稳定性。
既然知道了hook就是一个表,那么我们也就可以用操作列表的方式来操作它了。
1 2 3 |
(setq myhook (cdr myhook)) ;; =>丢弃myhook中的第一个函数 (setq myhook (reverse myhook)) ;; =>将myhook反转,改变函数执行的顺序 (setq myhook nil) ;; =>将myhook清空 |
3 用来高亮的函数
1、hi-lock-set-pattern 函数
它的作用为在当前buffer中对匹配的模式应用用户指定的face
我之前在text-mode 中打开outline-minor-mode,结果标题没有被高亮,经千辛万苦终于将问题解决,这得益于hi-lock-set-pattern函数。我是这样设置的:
先定义一些face ,如下:
1 2 3 4 5 6 7 8 9 10 11 |
(defface cyan-face'((t :foreground "cyan"))"我自定义的cyan face")(defface yellow-face'((t :foreground "yellow"))"我自定义的yellow face")(defface magenta-face'((((class color)) :foreground "magenta"))"我自定义的magenta face") |
这些face 都是从ahei-face.el中的,那里面还有许多其他的face。
然后然加入下面的代码,让outline-minor-mode启动时执行hi-lock-set-pattern,将标题高亮。
1 2 3 4 5 |
(add-hook 'outline-minor-mode-hook'(lambda ()(hi-lock-set-pattern "^\\*[^*]*?$" 'cyan-face)(hi-lock-set-pattern "^\\*\\*[^*]*?$" 'yellow-face)(hi-lock-set-pattern "^\\*\\*\\*[^*]*?$" 'magenta-face))) |
2、hi-lock-unface-buffer
既然有高亮的函数,就应该有取消高亮的函数,它就是hi-lock-unface-buffer了
4 编译类函数
complie 函数非常强大,它的参数是个编译命令字符串,它会执行这个编译命令,执行完后会打开一个buffer,其主模式为compilation-mode。如果编译出错,会在它打开的buffer中输出出现错误的行数,这时就可以通过点击鼠标跳转到发生错误的代码处。如果编译成功,则会输出编译结果。
我们可以这样设置编译命令:
1 2 3 4 |
(compile "gcc hello.c") (compile "c++ hello.cpp") (compile "perl hello.pl") (compile "d:/python/python25.exe hello.py") |
5 将这些函数串起来
下面我会用一个例子将上面所讲的大部分函数串起来。
需求 :我想实现按f5就能编译当前buffer,并且要有错误定位功能,支持的语言可以添加(不要修改已经写好的代码)
实际环境:window xp ,cygwin
由于使用的是cygwin,调用gcc 时,gcc 需要cygwin类型的路径
这是emacs 给出的路径类型: d:/gnu/
在cygwin下是 :/cygdirve/d/gnu
实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
;;这个函数就是用来转换路径的 (defun change-to-cygwin-style-path (emacs-style-path-on-w32)(let ((full-path emacs-style-path-on-w32))(replace-regexp-in-string "\\(\\w+?\\):\\(\\w*\\)" "/cygdrive/\\1\\2" full-path))) (change-to-cygwin-style-path (buffer-file-name))(defvar my-compile-hook nil);;这是主函数,按f5执行此函数 (defun my-compile-main-fun ()(interactive)(run-hooks 'my-compile-hook));;这个函数用来编译现在用得到的语言写的代码,以后如果要用到其他语言,可以写个函数,然后加入到my-compile-hook中去。 (defun orginal-compile-fun ()(let ((mode major-mode)(compstr nil))(cond ((eq mode 'c-mode)(setq compstr (concat "gcc -std=\"c99\" " (change-to-cygwin-style-path (buffer-file-name)))))((eq mode 'c++-mode)(setq compstr (concat "c++ " (change-to-cygwin-style-path (buffer-file-name)))))((eq mode 'emacs-lisp-mode)(emacs-lisp-byte-compile))((eq mode 'python-mode)(setq compstr (concat "python " (buffer-file-name))))((or (eq mode 'cperl-mode) (eq mode 'perl-mode))(setq compstr (concat "D:/Perl/bin/perl.exe " (buffer-file-name)))))(save-buffer)(if compstr (compile compstr)))) ;;将orginal-compile-fun加入my-compile-hook中 (add-hook 'my-compile-hook 'orginal-compile-fun);;将my-compile-main-fun 绑定到f5上 (global-set-key [(f5)] 'my-compile-main-fun) |
如果有一天,你要用octave 语言,你可以这样扩展:
1 2 3 4 5 |
(add-hook 'my-compile-hook '(lambda ()(if (eq major-mode 'octave-mode)(progn(save-buffer)(compile (concat "octave --silent " (buffer-file-name))))))) |
使用hook机制是不是很方便呀,这样就不用去修改orginal-compile-fun的代码了。
ps:不知不觉罗嗦了这么多,其实我写这篇文章的目的有两个:1、是给初学emacs lisp的人介绍一下emacs字符串的操作和hook的机理以及强大的compile函数,希望有点用处。2、希望高手们也分享一下自己觉得很强大的emacs lisp 函数。
介绍一些Emacs功能强大的函数相关推荐
- 视频编辑软件有哪些?介绍几种功能强大的编辑软件
视频编辑软件有哪些呢?如果我们录制了一段视频,但是其中包含了一些无用或者不太好的片段,我们就需要进行视频修剪,剪掉这些片段,让视频更加精炼.通过修剪视频素材,我们可以将一些不必要的部分去掉,保留最有价 ...
- 介绍一款功能强大的步进电机控制驱动芯片TMC5240
步进电机由于具有控制简单,良好的速度和位置控制被大量用在工业自动化.医疗设备.仪器仪表.实验室自动化.办公自动化.智能家居......等众多行业,实现让步进电机转起来相对容易很多,但是在应用中简单的转 ...
- 这是一款功能强大的开源 Python 绘图库
今天给大家分享一篇可视化干货,介绍的是功能强大的开源 Python 绘图库 Plotly,教你如何用超简单的(甚至只要一行!)代码,绘制出更棒的图表. 我之前一直守着 matplotlib 用的原因, ...
- 分享一款功能强大的win7免费语音朗读软件
很多时候我们常常要对着电脑看上一整天,眼镜什么的也都会觉得很疲劳,所以在工作的空挡我们还是需要注意休息一下,然而我还还可以使用一种办法,就是让需要查阅的文件用语音朗读出来,我们就可以用耳朵听,让眼镜休 ...
- php强大的函数,PHP中一些功能强大却很少使用的函数
本文主要介绍了PHP中功能强大却很少使用的函数,结合实例形式总结分析了php中非常实用的几个函数,包括函数的调用.注册.调用.判断等操作技巧.需要的朋友可以参考下,希望对大家有所帮助. 具体如下: c ...
- Visual Studio Code,一款功能强大且轻巧的免费代码集成编辑器介绍
Visual Studio Code - 编辑器+代码理解+调试 下载 软件官网下载地址 初步环境设置 基本设置 功能介绍 1. 界面友好 代码阅读 代码编辑 下载 软件官网下载地址 链接: http ...
- java sendmessage函数_功能强大的SendMessage函数
功能强大的SendMessage函数 分类:计算机等级 | 更新时间:2016-07-08| 来源:转载 Windows API(应用程序接口)是Windows系列软件为程序开发人员提供的火力强大的& ...
- python有vlookup的功能么,vlookup函数功能非常强大,那在Python中如何实现?
vlookup函数功能非常强大,那在Python中如何实现? vlookup函数功能非常强大,那在Python中如何实现? 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原 ...
- android联想功能介绍,在Android世界中联想推出了功能强大的手机Z5 Pro GT
在Android世界中,联想推出了功能强大的手机Z5 Pro GT.它已经引入了许多强大的规范.顺便说一句,这部手机中提供的RAM数量不存在于其他任何人中.但是在功能方面,除了Oneplus 6T之外 ...
最新文章
- ASP.NET MVC 学习1
- DELL服务器安装过程中出现的ERROR及解决方案
- 【pmcaff】社交媒体时代,村姑如何找到真爱?
- (十七)java版spring cloud+spring boot 社交电子商务平台-spring+springmvc+kafka分布式消息中间件集成方案...
- IOS学习笔记二十一(NSDictionary、NSMutableDictionary)
- python中自带的模块_python中的模块详解
- python win32ui_Python创建普通菜单示例【基于win32ui模块】
- html button跳转页面_HTML跳转到页面指定位置的几种方法
- eclise去连接mysql,Eclipse如何连接MySQL
- 第三章 Python丰富的数据类型
- python各种库下载地址:
- 推荐系统-利用用户行为数据
- 阳春三月,再送32本书,快来快来!
- 简单解释:STM32参考手册的地址偏移和复位值
- HTML5在vivo手机适配问题
- CSS中的text-overflow属性详解 (控制文字在一行显示,超出部分加省略号)
- PowerDesigner如何导出表到word的方法
- 华硕x450vb黑苹果系统拯救与安装
- digitalLogic_逻辑门和基本公式@同或和异或的关系
- hdfs - balancer学习
热门文章
- Nessus安装使用及自动化说明
- Altium Designer 详细图文教程
- 习题5-6 使用函数输出水仙花数 (20分)
- FIT2CLOUD飞致云发布开源Linux面板项目1Panel
- 人均劳动生产率的计算方法_劳动生产率应该如何计算
- STM32MP157驱动开发——多点电容触摸屏驱动
- 20230318解决编译友善之臂的RK3399的Android7.1.2的ninja_wrapper出错
- 机器视觉实用工具集NO.4——颜色查找可视化工具,在HSV、LAB、RGB三个颜色空间轻松进行颜色查找
- DM数据库数据守护集群搭建
- android 9.0跳过“未知来源”进行安装应用