当前位置: 首页 > article >正文

Emacs 折腾日记(二十)——修改emacs的一些默认行为

上一篇我们完成了emacs输入法的配置以及将emacs配置成了使用vim的操作方式。但是emacs目前有些默认行为我不太喜欢,这节我们一起来修改它

备份设置

我们打开emacs的配置文件所在路径,发现有大量的~结尾的文件,这是emacs的备份文件。这里,我们不使用这个特性,可以通过git等版本管理软件进行版本的控制和备份的管理。而且去掉这些还能让目录干净点。

(setq make-backup-files nil)                                  ; 不自动备份
(setq auto-save-default nil)                                  ; 不使用Emacs自带的自动保存

将用户设置独立开来

在修改这些配置的时候经常会发现在init.el 中出现类似下面的代码被修改

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(package-selected-packages nil))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )

这里保存的是使用编辑器接口产生的配置信息。如果让它们随意堆砌在init.el 中不利于版本的管理,我们将它放入到另一个文件中

(setq custom-file (expand-file-name "~/.emacs.d/custom.el"))
(load custom-file 'no-error 'no-message)

之前我们用 require 来加载一个代码文件,这里我们使用 load 来加载代码文件。它们有什么区别呢?

  • 首先 require 需要加载一个已经被定义为库的代码文件,也就是通过 provide 定义的库文件。而load传入文件路径来加载
  • 其次 require 会根据 provide 定义的库文件自动处理库文件,每个库文件只加载一次,并且会自动处理依赖。而 load 这些操作都需要手动进行
  • load 可以根据if条件来有选择的加载不同的库文件。而 require 则无法做到
  • load 可以进行错误处理,例如上面我们定义在加载时通过 noerror 限制错误,通过 no-message 不输出信息。而 require 是严格报错的。

其他的一些基础设置

这里再添加一些其他的基础配置

(fset 'yes-or-no-p 'y-or-n-p)    ;; 将所有的 yes-or-no-p 都替换为 y-or-n-p
(setq confirm-kill-emacs #'y-or-n-p)   ; 在关闭 Emacs 前询问是否确认关闭,防止误触
(electric-pair-mode t)            ; 自动补全括号
(column-number-mode t)            ; 在 Mode line 上显示列号
(global-auto-revert-mode t)         ; 当另一程序修改了文件时,让 Emacs 及时刷新 Buffer
(delete-selection-mode t)          ; 选中文本后输入文本会替换文本(更符合我们习惯了的其它编辑器的逻辑)

(add-hook 'prog-mode-hook #'hs-minor-mode)  ; 编程模式下,可以折叠代码块
(add-hook 'prog-mode-hook #'show-paren-mode) ; 编程模式下,光标在括号上时高亮另一个括号

(fset 'yes-or-no-p 'y-or-n-p) 将所有的 yes-or-no-p 都替换为 y-or-n-p。这样在每次确定的时候能从 yes 或者 no的输入变成输入 y 或者 n,能少输入几个字符。

这里又看到了一个新的符号# ,它代表的意思是取符号的函数部分。前面我们介绍符号的时候说,符号有两个部分的值,变量值和函数值。我们可以通过 function 来获取符号的函数部分的值。它的作用等同于 (setq confirm-kill-emacs (function y-or-n-p))

这里又有一个新的函数 function。我们在介绍符号的时候介绍过使用 symbol-function 来获取符号的函数,那么他们两个有什么区别呢?

首先 function 返回的是函数对象,而 symbol-function 返回函数本身。这个比较的抽象,我们使用例子来说明

(setq bar "I am a bar variable")
(defun bar()
  "I am a bar function")

(function bar) ;; ==> bar
(symbol-function 'bar) ;; ==> #[nil ("I am a bar function") (t)]

(functionp bar) ;; ==> nil
(functionp (function bar)) ;; ==> t

上面的例子中,我们实际上定义了bar的变量部分和函数部分的值。同一 bar 符号它既可以作为变量使用,也可以作为函数使用。我们在使用 functionbar 求值的时候,得到的返回虽然也是 bar 但是它返回的是它的函数部分,而 symbol-function 则直接返回函数的结构,因为lisp代码本身就是一个列表结构,所以这里它返回的实际上是函数的代码。它返回的比 function 更加的底层。

下面我们使用 functionp 进行了测试,发现 function 返回的是一个函数对象。

虽然在理解上有些差别,但是都可以直接通过 funcall 来调用

(bar) ;; ==> "I am a bar function"
(funcall bar) ;; ==> error
(funcall (function bar)) ;; ==> "I am a bar function"
(funcall (symbol-function 'bar)) ;; ==> "I am a bar function"

我们发现当一个符号既有值部分,又有函数部分,是无法通过 funcall 来直接调用的。所以上述代码使用 # 这个语法糖来保证后续正常调用这个符号对应的函数部分。


http://www.kler.cn/a/613880.html

相关文章:

  • 【C++项目实战】:基于正倒排索引的Boost搜索引擎(1)
  • s1: Simple test-time scaling 【论文阅读笔记】
  • PPTP、L2TP 和 IPSec
  • PyTorch 分布式训练(Distributed Data Parallel, DDP)简介
  • 在IDEA中快速注释所有console.log
  • Taro创建微信小程序项目 第一步搭建项目
  • 掌握!Postman 设置 Bearer Token 的完整指南
  • 3d pose 指标和数据集
  • 【tips】微信小程序wxs 注意
  • WHAT - 程序员英语之美式发音学习系列(五)
  • 【华三】华三模拟器HCL防火墙、AC和交换机的Web登入
  • 06-SpringBoot3入门-常见注解(简介)
  • 基于HTML5和CSS3实现3D旋转相册效果
  • 力扣hot100二刷——动态规划
  • uni-app踩坑记录【图片先压缩再上传】
  • Oracle 数据库同步至 GaussDB问题及解决方案
  • uv:现代 Python 项目管理的高效助手
  • 简单介绍一下Unity中的ScriptableObject
  • Rust从入门到精通之入门篇:4.变量与数据类型
  • JS—异步编程:3分钟掌握异步编程