从零开始的Emacs配置学习

emacs

该怎么说呢,很早就下载了这个操作系统(编辑器)了,一年前(2019)在看SICP的时候就有想法用emacs写scheme,但是由于配置过于复杂,还是选择了用vscode进行编辑。然后中间因为一些其他的事情停止了对SICP的学习,总共四章的内容也只看了两章多,这次放假希望一次性把emacs配置好再把SICP看完吧。接下来将介绍我的emacs配置过程。

快捷键的使用

C 即 Control , M 即 Alt (至少在我的键盘上是这样的)

C - x , C - s 对当前文档进行保存

C - x, C - c 关闭当前程序

C - x, C - f 输入文件名,emacs会搜索文件并打开

M - x 输入具体操作(这个比较类似 sublime 和 vscode 里面的C - p)

C - w剪切

M - w 复制

C - y 粘贴

M - y 在按下C - y后,按此键,切换粘贴的内容

C - / 撤销

C - g中断当前命令输入

C - s 或者C - r 搜索(方向不同)

配置文件

在emacs 27以前的版本通常是在”.emacs”这个文件里进行修改的,具体操作是M - x后,输入.emac回车,就可以进入配置文件了。

关闭滚动条与工具栏

(scroll-bar-mode -1) 关闭滚动条 (tool-bar-mode -1) 关闭工具栏

添加国内源

这个设置和Linux系统下的添加镜像源的操作如出一辙。

1
2
3
4
5
6
;; add tinghua resource
(setq package-archives '(("gnu" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/gnu/")
("org" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/org/")
("melpa" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/melpa/")))

(package-initialize) ;; You might already have this line

包管理器的初始化、刷新、安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    ;; package initialize
(setq package-check-signature nil)

(require 'package)

(unless (bound-and-true-p package--initialized)
(package-initialize))

;; refresh resource
(unless package-archive-contents
(package-refresh-contents))

;; use-package
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))

unless 语句即如果没有进行(…)那么就进行(…)。

使用use-package管理扩展

最基本的格式

1
(use-package restart-emacs)

M-x后输入restart-emacs,emacs就会重启了。

常用格式

1
2
3
4
5
6
7
8
;; 常用格式
(use-package smooth-scrolling
: ensure t; 是否一定要确保已安装
: defer nil ;是否延迟加载
: init (setq smooth-scrolling-margin 2) ;初始化参数
: config (smooth-scrolling-mode t) ;基本配置参数
: bind ;快捷键绑定
: hook ;hook模式的绑定)

推荐添加的配置

1
2
3
4
5
6
7
(eval-and-compile
(setq use-package-always-ensure t) ; 不用每个包都手动添加:ensure t 关键字
(setq use-package-always-defer t) ; 默认都是延时加载,不用每个包都手动添加:defer t 关键字
(setq use-package-always-demand nil) ;
(setq use-package-expand-minimally t) ;
(setq use-package-verbose t) ; 打印安装过程
)

安装主题

使用 use-package 安装

1
2
3
;; install a theme
;;(use-package gruvbox-theme
;; :init(load-theme 'gruvbox-dark-soft t))

通过他人编写的文件安装

在这个开源项目(https://github.com/belak/emacs-monokai-pro-theme )中找到了合适版本的emacs配色,然后根据README.md的教程完成。

将monokai-pro-theme.el文件放入.emacs.d/themes/中 然后执行M-x package-install monokai-pro-theme(load-theme 'monokai-pro t)添加到配置文件,重启后就可以看见主题更改了。

1
2
;; use monokai
(load-theme 'monokai t) ;; or (load-theme 'monokai-pro t)

更换一个更加优雅的状态栏

1
2
3
4
5
6
;; an elegent mode-line
(use-package smart-mode-line
:init
(setq sml/noconfir-load-theme t
sml/theme 'respectful)
(sml/setup))

显示行标

1
(global-linum-mode t)

工程化管理配置

由于将所有的配置都写到.emacs里会使整个文档看起来很凌乱,于是就需要将不同方面(ui界面,use-package管理等)的配置代码区分开来。

于是不妨新建一个文件夹/.emacs.d/lisp/里面专门存放配置文件。并且根据配置的不同方向,命名如下:

  • init-elpa.el 存放镜像源相关配置
  • init-package.el 存放包管理器的相关配置u
  • init-startup.el emacs启动时运行的一些代码(关闭工具栏和滚动条等)
  • init-ui.el 界面的主题和字体等配置

比如目前我的init-ui.el是这样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
;; install a theme
;;(use-package gruvbox-theme
;; :init(load-theme 'gruvbox-dark-soft t))

;; use monokai
(load-theme 'monokai t) ;; or (load-theme 'monokai-pro t)

;; an elegent mode-line
(use-package smart-mode-line
:init
(setq sml/noconfir-load-theme t
sml/theme 'respectful)
(sml/setup))

;; show the line number
(global-linum-mode t)

;; make the background transparent
(set-frame-parameter (selected-frame) 'alpha (list 85 60))
(add-to-list 'default-frame-alist (cons 'alpha (list 85 60)))
(put 'downcase-region 'disabled nil)

(provide 'init-ui)

(provide 'init-ui)在这里是将init-ui暴露的意思,后续的require会根据是否暴露来找到配置文件。

将所有的配置往/.emacs.d/目录下的init.el文件里迁移。

1
2
3
4
5
6
7
(add-to-list 'load-path
(expand-file-name(concat user-emacs-directory "lisp")))

(require 'init-startup)
(require 'init-elpa)
(require 'init-ui)
(require 'init-package)

load-path是一个list,需要将配置添加进去。

expand-file-name将后面的两个字符串拼接成一个目录,concat是拼接的意思,user-emacs-directory系统的全局变量,寻找emacs的目录,即/.emacs.d/这个目录。

诸如(require 'init-startup)require和provide是配对的,调用之前配置好的init-startup

这些都配置好了以后就可以把.emacs文件删了。

关于自定义配置

1
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))

通过这个命令可以将一些自定义配置(诸如鼠标点击的)后系统生成的文字,保存到custom.el里面。 通过这个方法可以使得init.el文件看上去并不是那么凌乱了。

1
2
(when (file-exits-p custom-file)
(load-file custom-file))

系统可能不会自动加载custom里面的配置,这里的代码意思是当发现custom-file文件存在是就自动加载。

启动配置

1
2
3
4
5
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(setq default-buffer-file-coding-system 'utf-8)

用于解决乱码问题。

1
(setq gc-cons-threshold most-positive-fixnum)

控制垃圾回收阈值,满了再回收。

代码补全

使用company插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(use-package company
:diminish (company-mode " Cmp.")
:defines (company-dabbrev-ignore-case company-dabbrev-downcase)
:hook (after-init . global-company-mode)
:config (setq company-dabbrev-code-everywhere t
company-dabbrev-code-modes t
company-dabbrev-code-other-buffers 'all
company-dabbrev-downcase nil
company-dabbrev-ignore-case t
company-dabbrev-other-buffers 'all
company-require-match nil
company-minimum-prefix-length 1
company-show-numbers t
company-tooltip-limit 20
company-idle-delay 0
company-echo-delay 0
company-tooltip-offset-display 'scrollbar
company-begin-commands '(self-insert-command))
(eval-after-load 'company
'(add-to-list 'company-backends
'(company-abbrev company-yasnippet company-capf))))