elisp简单实例: auto-save

news/2024/12/2 13:38:47/

elisp 能找一个简单又实用的代码很不容易,以下代码不是我的原创,只是结合自己的理解,添加修正了一些注释,荣誉归原作者,感谢原作者的开源精神!

调用说明:

把后面代码存为auto-save.el

在init.el 中写上

(require 'auto-save)

就可以了.

下面是auto-save.el 内容了.

;; 我们的auto-save,每秒钟都会为你检查,如果发现文件改动了,就悄悄的为你存盘了,不怕掉电,保证不会丢失你工作.

;; 这行代码的作用就是:
;; 避免 Emacs 在保存文件的时候生成一大堆垃圾的 #foo# 文件, 这种文件最讨厌了, 不但什么用都没有, 反而污染代码目录, 删除都删的手酸
;; 有了我们优雅的auto-save, 就让emacs 的auto-save 休息去吧! 因为它太垃圾了.
(setq auto-save-default nil)

;; defgroup 关键字的意思是定义一个工作组,执行 Alt + x customize-group 命令的时候可以进行图形化的模块配置
;; 第一个参数是模块的名字, 比如 auto-save
;; 第二个参数是模块默认开启的状态, 在 elisp 中, t 表示 true, nil 表示 false
;; 第三个参数是对模块的文本解释
;; 第四个参数表示对外提供 auto-save 这个 group
(defgroup my-auto-save nil
  "Auto save file when emacs idle."
  :group 'my-auto-save)

;; defcustom 关键字的意思是定义一个可以被用户自定义的变量, 当用户执行 Alt + x customize-variable 的时候就可以补全 auto-save-idle 这个变量,
;; defcustom 和 defvar 的区别主要是 defcustom 用于提供一些参数让用户可以在 Emacs 中图形化定制变量内容,
;; defvar 只有变量名和 List 内容, 一般用于函数内部变量值存储用, 不对外抛出给用户定制
;; 第一个参数是变量的名字 autos-save-idle
;; 第二个参数是变量的值, 这里我们定义为 1, 表示自动保存的延迟秒数为1
;; 第三个参数是变量的解释, 一般在 Alt + x describe-variable 的时候就会显示具体变量的文档描述
;; 第四个参数用于定义变量的类型, 这里定义为整形, 这样在 customize-group 的时候只有输入整型才是正确保存
;; 第五个参数表示这个变量属于 auto-save 这个组, 主要作用就是 customize-group 的时候能够在一个界面中设置同一组的所有变量
(defcustom auto-save-idle 1
  "The idle seconds to auto save file."
  :type 'integer
  :group 'my-auto-save)

;; autos-save-slient 的作用就是一个boolean值得变量, 设置为 nil 的时候, 表示每次自动保存都会在 minibuffer 提示,
;; 设置成 t 的时候就会 shutup, 让我安安静静写会代码, 别闹...
(defcustom auto-save-slient nil
  "Nothing to dirty minibuffer if this option is non-nil."
  :type 'boolean
  :group 'my-auto-save)


;; 前方高能核心代码, 请集中注意力
(defun auto-save-buffers ()
  ;; 所有你在 Alt + x 以后可以调用的函数都要手动加上 (interactive) , 否则这段代码只能在 Elisp 解释器中执行, 但是不能直接被用户从 Alt + x 调用,
  ;; 就象 interactive 这个单词的意思一样,想交互就调用这个函数
  (interactive)
 ;; 创建 autosave-buffer-list 这个变量, 用于保存所有需要遍历的 buffer 列表
  (let ((autosave-buffer-list))
    ;; save-excursion 这个关键字的意思是, 所有在 save-excursion 里面的代码不管怎么折腾都不会对 save-excursion 之前的Emacs状态进行任何改变,
    ;;你可以理解为这个关键字的意思就是用于保护现场用的 ;)
    (save-excursion
      ;; dolist 的作用就和很多语言的 foreach 一个意思, 把 buffer-list 这个函数返回的所有 buffer 在循环内赋值给 buf 这个变量,
      ;; 并在 dolist 的作用域中执行对 buf 影响的代码
      (dolist (buf (buffer-list))
        ;; 设置当前代码的 buffer 为 buf 变量值, 如果没有前面 save-excursion, 你会发现emacs会一直在快速的切换所有 buffer 的过程
        (set-buffer buf)
        ;; 如果当前 buffer 有一个相关联文件 (buffer-file-name), 同时当前 buffer 已经被用户修改了 (buffer-modified-p) 的情况下就执行自动保存
        (if (and (buffer-file-name) (buffer-modified-p))
            (progn
              ;; 把当前 buffer 的名字压进 autosave-buffer-list 列表, 用于后面的保存提示
              (push (buffer-name) autosave-buffer-list)
              (if auto-save-slient
                  ;; 如果 auto-save-slient 这个变量为 true, 就不显示任何保存信息,
                  ;;因为 Emacs 的保存函数 (basic-save-buffer) 本身就会 blabla 的告诉你文件已经保存了,
                  ;; 所以我们用 with-temp-message 配合空字符串来禁止 basic-save-buffer的代码在 minibuffer 显示任何内容
                  (with-temp-message ""
                    (basic-save-buffer))
                (basic-save-buffer))
              )))
      ;; unless 的意思是当 auto-save-slient 为 false 就执行
      (unless auto-save-slient
        ;; cond 就是 elisp 版的 switch, 用于条件语句对比执行
        (cond
         ;; 如果 autosave-buffer-list 列表里面没有任何一个文件需要保存, 我们就不要去烦用户了, 默默打酱油路过就好了
         ;; 如果有一个文件需要保存, 我们就说 Saved ...
         ((= (length autosave-buffer-list) 1)
          (message "# Saved %s" (car autosave-buffer-list)))
         ;; 如果有多个文件需要保存, 就说 Saved ... files
         ((> (length autosave-buffer-list) 1)
          (message "# Saved %d files: %s"
                   (length autosave-buffer-list)
                   (mapconcat 'identity autosave-buffer-list ", ")))))
      )))

(defun auto-save-enable ()
  (interactive)
  ;; run-with-idle-timer 函数的意思就是在 auto-save-idle 定义的描述以后自动执行 auto-save-buffers 函数
  ;; #' 的意思就是说run-with-idle-timer 第三个参数是函数而不是一般的参数
  ;; idle timer 每1秒钟(auto-save-idle)就会执行一个auto-save-buffer 函数
  ;; 得到的idle timer 要保留其handle, 以便以后能够删除.
  (setq auto-save-handle (run-with-idle-timer auto-save-idle t #'auto-save-buffers))
  (setq auto-save-running 1))

(defun auto-save-disable()
  (interactive)
  (if (/= auto-save-running 0)
    (cancel-timer auto-save-handle)
    (setq auto-save-running 0)))
(auto-save-enable)
(provide 'auto-save)


http://www.ppmy.cn/news/29919.html

相关文章

计算机网络中的原码、反码、补码

写在前面 原码、反码、补码是计算机组成原理中的概念,是计算机网络的基础知识之一。这些概念是为了处理二进制数的符号位而引入的,常用于计算机中的整数运算,也常用于数据存储和传输等领域。因此,了解和掌握这些概念对于理解计算机…

leetcode_贪心算法

贪心算法相关题简单题目455.分发饼干1005.K次取反后最大化的数组和860.柠檬水找零序列问题376.摆动序列法一:贪心法法二:动态规划单调递增的数字简化版本有点难度53.最大子序和贪心算法动态规划134.加油站968.监控二叉树两个维度权衡问题分发糖果406.根据…

佛科院单片机原理2——80C51单片机结构

一、程序存储器的入口地址:程序入口地址:0000H外部中断0入口地址:0003H定时器0溢出中断入口地址:000BH外部中断1入口地址:00013H定时器1溢出中断入口地址:001BH串行口中断入口地址:0023H定时器2…

1 网关介绍

网关介绍 在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调用。这样的话会产生很多问题,例如&a…

[ant-design-vue] tree 组件功能使用

[ant-design-vue] tree 组件功能使用描述环境信息相关代码参数说明描述 是希望展现一个树形的菜单,并且对应的菜单前有复选框功能,但是对比官网的例子,我们在使用的过程中涉及到对半选中情况的处理: 半选中状态: 选中…

华为OD机试Golang解题 - 计算网络信号

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典文章目录 华为Od必看系列使用说明本期题目…

数组--java--动态数组--有序数组--底层

java数组基础--java中的数组创建数组空间占用初始化数组访问元素插入查找删除元素动态数组扩容插入和添加重写toString删除二维数组二维数组注意点有序数组实现测试写在开头: 这篇文章包括数组的基础、一点底层的内容和一些稍微深入的东西。 作为第一个深入学习的数…

【Python】软件测试必备:了解 fixture 在自动化测试中的重要作用

在自动化软件测试中,fixture 是一种确保测试在一致且受控条件下运行的重要方法。简单来说,fixture 就是一组先决条件或固定状态,必须在运行一组测试之前建立。在测试框架中,fixture 提供了一种方便的方法,用于在每个测…