返回顶部
首页 > 资讯 > 精选 >关于Emacs中的变量需要知道的事情有哪些
  • 911
分享到

关于Emacs中的变量需要知道的事情有哪些

2023-06-16 02:06:46 911人浏览 泡泡鱼
摘要

关于EMacs中的变量需要知道的事情有哪些,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。学习 Elisp 是如何处理变量的,以及如何在你的脚本与配置中使用它们。GNU Em

关于EMacs中的变量需要知道的事情有哪些,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

学习 Elisp 是如何处理变量的,以及如何在你的脚本与配置中使用它们。

GNU Emacs 是由 C 和 Emacs Lisp(Elisp,Lisp 编程语言的一种方言)写成,它是一个编辑器的同时,又碰巧是 Elisp 的沙盒。因此,理解 Elisp 中的一些基本编程概念会对你有一些帮助。

如果你是 Emacs 新手,请先阅读 Sacha Chua 的《给 Emacs 新手的资源》精品帖。本篇文章假定你熟悉常见的 Emacs 术语,并且能够阅读并求值 Elisp 代码的简单片段。最好你也听说过变量作用域的概念,知道它在其它编程语言中的作用。本篇文章中的示例假定你使用的是相对较新的 Emacs 版本(v.25 之后的版本)。

Elisp 手册  包含了 Elisp 的方方面面,但它是写给那些有明确查找目标的人们的(它在这方面也做得相当棒)。但是很多人想要能够在更高的层次上解释  Elisp  概念的材料,同时将信息压缩成最精华的部分。本篇文章也正是我回应这种呼声的一次尝试,为读者描绘基础的大体轮廓。使他们能在配置中用上这些技巧,也让他们在手册中查询细节变得更容易。

全局变量

defcustom 定义的用户设置和用 defvardefconst 定义的变量是全局的。使用 defcustomdefvar 声明变量的一个非常重要的原因是,当一个变量已经被绑定bind,对它们进行重新求值不会覆盖掉已有的值。举个栗子,如果你在初始化文件中对 my-var 进行如下绑定:

(setq my-var nil)

对如下表达式求值不会将变量覆盖为 t

(defvar my-var t)

注意此处有一个例外:如果你用 C-M-x 快捷键对上述声明求值,它将调用 eval-defun 函数,并将变量覆盖为 t。通过此方式,你可以按需将变量强制覆盖。这种行为是刻意而为之的:你可能知道,Emacs 中的许多特性是按需加载的,也可以称为自动加载。如果那些文件中的声明将变量覆盖为它们的默认值,那它也就覆盖了你初始化文件中的设置。

用户选项

用户选项就是使用 defcustom 声明的全局变量。与使用 defvar 声明的变量不同,这些变量可以用 M-x customize 界面来配置。据我所知,大部分人因为觉得它开销较大而不经常使用。一旦你知道如何在你的初始化文件中设置变量,也就没有理由一定要去使用它了。许多用户没有意识到的一个细节是,通过 customize 的方式设置用户选项能够执行代码,有的时间可用来运行一些附加的配置说明:

(defcustom my-option t  "My user option."  :set (lambda (sym val)         (set-default sym val)         (message "Set %s to %s" sym val)))

若你对这段代码求值,并键入 M-x customize-option RET my-option RET 运行 customize 界面,lambda 匿名函数就会被调用,回显区域就会显示出该选项的符号名与值。

如果你在初始化文件中使用 setq 改变该选项的值,那么匿名函数不会运行。要想在 Elisp 中正确设置一个选项,你需要使用函数 customize-set-variable。或者,人们在他们的配置文件中使用了各种版本的 csetq 宏来自动处理(如你所愿,你可以通过 GitHub 的代码搜索发现更复杂的变体)。

(defmacro csetq (sym val)  `(funcall (or (get ',sym 'custom-set) 'set-default) ',sym ,val))

若你正在使用 use-package 宏,:custom 关键字会替你处理好以上这些。

在你将以上代码放入到你的初始化文件中之后,你便可以使用 csetq 宏在设置变量的同时运行任何现存的 setter 函数。要证明这点,你可以使用此宏来改变上面定义的选项,并观察回显区域的消息输出。

(csetq my-option nil)

动态绑定与词法绑定

当你在使用其它编程语言时,你可能不会意识到动态绑定与词法绑定的区别。当今的大部分编程语言使用词法绑定,并且在学习变量作用域与变量查找时也没有必要去了解它们之间的区别。

如此看来,Emacs Lisp 比较特殊因为动态绑定是默认选项,词法绑定需要显式启用。这里有一些历史遗留原因,但在实际使用中,你应该时刻启用词法绑定,因为它更快并且不容易出错。要启用词法绑定,只需将如下的注释行作为你的 Emacs Lisp 文件的第一行:

;;; -*- lexical-binding: t; -*-

另一种方式,你可以调用 add-file-local-variable-prop-line,在你选择将变量 lexical-binding 置为 t 后,会自动插入如上的注释行。

在加载包含如上特殊格式行的文件时,Emacs 会相应地设置变量,这意味着该缓冲区中的代码加载时启用了词法绑定。若要采用交互式的方式,你可以调用 M-x eval-buffer 命令,它会将词法绑定考虑在内。

既然你已经知道了如何启用词法绑定,那么了解这些术语的含义就很明智了。对于动态绑定,在程序执行期间建立的最后一个绑定将用于变量查找。你可以通过将以下代码放入空缓冲区并执行 M-x eval buffer,以对此进行测试

(defun a-exists-only-in-my-body (a)  (other-function)) (defun other-function ()  (message "I see `a', its value is %s" a)) (a-exists-only-in-my-body t)

你可能会很惊讶地发现,在 other-function 中查找变量 a 竟然成功了。

若你在顶部添加了特殊的词法绑定注释后,重新运行前面的示例,这段代码将抛出 variable is void 错误,因为 other-functioin 无法识别变量 a。如果你使用的是其它编程语言,这才是你所期望的行为。

启用词法绑定后,作用域会由周围的代码所定义。这并不单单是性能原因,时间也已经表明了词法绑定才是更受喜爱的。

特殊变量与动态绑定

如你所知,let 用于临时建立局部绑定:

(let ((a "I'm a")      (b "I'm b"))  (message "Hello, %s. Hello %s" a b))

接下来有趣的是——使用 defcustomdefvar 以及 defconst 定义的变量被称为特殊变量,不论词法绑定是否启用,它们都将使用动态绑定:

;;; -*- lexical-binding: t; -*- (defun some-other-function ()  (message "I see `c', its value is: %s" c)) (defvar c t) (let ((a "I'm lexically bound")      (c "I'm special and therefore dynamically bound"))  (some-other-function)  (message "I see `a', its values is: %s" a))

通过 C-h e 切换至 Messages 缓冲区,查看上述示例输出的消息。

使用 let 或者函数参数绑定的局部变量会遵循由 lexical-binding 变量定义的查找规则,但使用 defvardefconstdefcustom 定义的全局变量,能够沿着调用栈在 let 表达式中被修改。

这种技巧允许方便地进行特殊定制,并且经常在 Emacs 中被使用。这并不奇怪,毕竟 Emacs Lisp 最开始只提供动态绑定作为唯一选择。下面是一个常见的示例,说明如何向只读缓冲区临时写入数据:

(let ((inhibit-read-only t))  (insert ...))

这是另一个常见的示例,如何进行大小写敏感的搜索:

(let ((case-fold-search nil))  (some-function-which-uses-search ...))

动态绑定允许你采用作者未曾预料的方式对函数进行修改。对于像 Emacs 这样设计使用的程序来说,这是个强大的工具与特性。

有一点需要注意:你可能会意外地使用局部变量名,该变量在其他地方被声明为特殊变量。防止这种冲突的一个技巧是避免在局部变量名中使用下划线。在我当前的 Emacs 会话中,以下代码只留下少数潜在冲突的候选:

(let ((vars ()))  (mapatoms   (lambda (cand)     (when (and (boundp cand)                (not (keyWordp cand))                (special-variable-p cand)                (not (string-match "-"                                   (symbol-name cand))))       (push cand vars))))  vars) ;; => (t obarray noninteractive debugger nil)

缓冲区局部变量

每个缓冲区都能够拥有变量的一个局部绑定。这就意味着对于任何变量,都会首先在当前缓冲区中查找缓冲区局部变量取代默认值。局部变量是 Emacs 中一个非常重要的特性,比如它们被主模式用来建立缓冲区范围内的行为与设置。

事实上你已经在本文中见过缓冲区局部变量——也就是将 lexical-binding 在缓冲区范围内设置为 t 的特殊注释行。在 Emacs 中,在特殊注释行中定义的缓冲区局部变量也被称为文件局部变量

任何的全局变量都可以用缓冲区局部变量来遮掩,比如上面定义的变量 my-var,你可用如下方式设置局部变量:

(setq-local my-var t);; or (set (make-local-variable 'my-var) t)

此时 my-var 对于你在对上述代码进行求值时对应的缓冲区来说就是局部变量。若你对它调用 describe-variable,文档会同时告诉你局部与全局的值。从编程的角度来讲,你可以分别用 buffer-local-value 获取局部值,用 default-value 获取全局值。若要移除局部值,你可以调用 kill-local-variable

另一个需要注意的重要性质就是,一旦一个变量成为缓冲区局部变量,后续在该缓冲区中使用的 setq 都将只能设置局部的值。要想设置默认值,你需要使用 setq-default

因为局部变量意味着对缓冲区的定制,它们也就经常被用于模式钩子中。一个典型的例子如下所示:

(add-hook 'Go-mode-hook          (defun go-setup+ ()            (setq-local compile-command              (if (string-suffix-p "_test.go" buffer-file-name)                  "go test -v"                (fORMat "go run %s"                        (shell-quote-argument                         (file-name-nondirectory buffer-file-name)))))))

这将设置 go-mode 缓冲区中 M-x compile 使用的编译命令。

另一个重要的方面就是一些变量会自动成为缓冲区局部变量。这也就意味着当你使用 setq 设置这样一个变量时,它会针对当前缓冲区设置局部绑定。这个特性不应该被经常使用,因为这种隐式的行为并不好。不过如果你想的话,你可以使用如下方法创建自动局部变量:

(defvar-local my-automatical-local-var t);; or (make-variable-buffer-local 'my-automatical-local-var)

变量 indent-tabs-mode 就是 Emacs 内建的一个例子。如果你在初始化文件中使用 setq 改变变量的值,根本不会影响默认值。只有在你加载初始化文件时正处在当前的缓冲区的局部值会被改变。因此,你需要使用 setq-default 来改变 indent-tabs-mode 的默认值。

Emacs 是一个强大的编辑器,并且随着你的定制它将变得更加强大。现在,你知道了 Elisp 是如何处理变量的,以及你应如何在你自己的脚本与配置中使用它们。

关于关于Emacs中的变量需要知道的事情有哪些问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网精选频道了解更多相关知识。

--结束END--

本文标题: 关于Emacs中的变量需要知道的事情有哪些

本文链接: https://lsjlt.com/news/282053.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 关于Emacs中的变量需要知道的事情有哪些
    关于Emacs中的变量需要知道的事情有哪些,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。学习 Elisp 是如何处理变量的,以及如何在你的脚本与配置中使用它们。GNU Em...
    99+
    2023-06-16
  • 关于彻底测试你需要知道的所有事情
    什么是穷举测试?当您的团队中的所有测试人员都用尽并且所有计划的测试都已执行时,就会发生详尽的测试(也称为完整测试)。它是一种质量保证测试技术,其中测试所有场景或数据以进行测试。以更容易理解的方式,详尽的测试意味着确保在测试阶段结束时没有未发...
    99+
    2023-06-04
  • ASP shell 容器:你需要知道的一切关于响应的事情!
    ASP shell 是一种常用的 Web 攻击工具,它可以通过 Web 应用程序的漏洞来获得系统的控制权。然而,这种攻击手法也可以被用来进行安全测试和漏洞挖掘。ASP shell 容器就是一个用来模拟 ASP shell 攻击的工具,它可...
    99+
    2023-06-21
    shell 容器 响应
  • Java开发人员需要知道的一些关于日志记录和Numy的事情。
    Java开发人员需要知道的一些关于日志记录和Numy的事情 在Java开发中,日志记录是非常重要的一部分。它可以帮助开发人员快速定位问题,提高开发效率。同时,Numy(即NumberUtils)也是一个非常实用的工具类,它提供了很多常用的数...
    99+
    2023-10-07
    日志 npm numy
  • 关于CSS变量的知识点有哪些
    这篇文章主要介绍关于CSS变量的知识点有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!css的全称是什么css的全称是Cascading Style Sheets(层叠样式表),它是一种用来表现HTML或XML等...
    99+
    2023-06-15
  • Linux Shell 中的 Java 函数:你需要知道的事情!
    在 Linux Shell 中使用 Java 函数是一项非常有用的技能。尤其是在需要对大量数据进行处理时,Java 函数可以帮助我们快速高效地完成任务。在本文中,我们将介绍使用 Java 函数在 Linux Shell 中进行编程的基本知...
    99+
    2023-08-10
    函数 linux shell
  • JavaScript需要知道的小技巧有哪些
    这篇文章主要介绍JavaScript需要知道的小技巧有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、神奇的扩展运算符扩展运算符(spread)是三个点( ... ), 可以说我在 JavaScript 中最喜...
    99+
    2023-06-22
  • Java开发中需要知道的基础知识有哪些
    这篇文章将为大家详细讲解有关Java开发中需要知道的基础知识有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Java 是一个多功能的编程语言,在某种程度上,它用在几乎所有可能涉及计算机的行业了里。Ja...
    99+
    2023-06-02
  • 关于mysql自增id,你需要知道的
    导读:在使用MySQL建表时,我们通常会创建一个自增字段(AUTO_INCREMENT),并以此字段作为主键。本篇文章将以问答的形式讲述关于自增id的一切。 注: 本文所讲的都是基于Innodb存储引擎。 1.M...
    99+
    2022-05-21
    mysql 自增id mysql 自增 mysql id
  • PHP日志文件同步:你需要知道的所有事情。
    PHP日志文件同步:你需要知道的所有事情 在现代的Web应用程序中,日志文件是非常重要的组成部分。它们记录了应用程序的运行情况,包括错误、警告、调试信息和性能数据等。在开发和维护应用程序时,日志文件是一个非常有用的工具,可以帮助我们快速定位...
    99+
    2023-07-09
    日志 文件 同步
  • 关于bash函数你可能不知道的一些事情(译)
    关于bash函数,这里有一些您不知道的东西。通常当你写一个函NXtvFVsJb数时,你会这样做: function name () { ... } 不是吗?我知道你会这么做,因为这是所有人写函数的方式...
    99+
    2022-06-04
    bash 函数 bash 函数调用 bash 函数参数
  • Flex程序员应该知道的事情有哪些
    这篇文章给大家分享的是有关Flex程序员应该知道的事情有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1.重新定义:Flex是web标准MXML是Flex应用的标准语言,它允许开发人员开发应用程序架构,不仅包...
    99+
    2023-06-17
  • Java8中需要知道的函数式接口有哪些
    这篇“Java8中需要知道的函数式接口有哪些”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java8中需要知道的函数式接口有...
    99+
    2023-07-05
  • 学习Numpy:你需要知道的最重要的事情是什么?
    Numpy是Python中最常用的科学计算库之一。它提供了高效的多维数组对象和用于操作数组的各种函数。在本文中,我们将学习Numpy的一些基础知识,并且演示一些代码,以帮助你更好地了解如何使用这个库。 数组的创建 首先,我们需要学会创...
    99+
    2023-07-10
    django numpy leetcode
  • 二维码在ASP路径中的应用:您需要知道的所有事情
    二维码在ASP路径中的应用:您需要知道的所有事情 随着二维码技术的不断发展,越来越多的企业和个人开始使用二维码来传递信息和进行营销。而在ASP路径中应用二维码也成为了一个越来越热门的话题。在本文中,我们将为您介绍二维码在ASP路径中的应用,...
    99+
    2023-10-06
    path 二维码 http
  • ASP 框架与 Apache、Linux 系统之间的关系,你需要知道的事情。
    ASP框架与Apache、Linux系统之间的关系,你需要知道的事情 ASP框架是一种基于Microsoft的Web应用程序开发技术,它提供了许多功能强大的工具和库,帮助开发者快速构建高性能的Web应用程序。但是,随着Linux和Apach...
    99+
    2023-10-13
    框架 apache linux
  • Spring Boot 和 Python API 的结合使用,你需要知道的一些事情。
    Spring Boot 是一款非常流行的 Java 开发框架,它可以帮助开发者快速搭建一个基于 Java 的 Web 应用程序。Python 是一种脚本语言,其最大的特点是简单易学,同时也具有非常强大的科学计算和数据处理能力。在本文中,我们...
    99+
    2023-11-10
    spring linux api
  • Python shell 打包到 Linux:你需要知道的所有事情是什么?
    Python是一种高级编程语言,广泛应用于Web开发、数据分析、人工智能等领域。在Linux系统中,Python的应用非常广泛,从系统管理到网络编程,从数据处理到机器学习,都有Python的身影。如果你想将Python shell程序打包...
    99+
    2023-10-19
    shell 打包 linux
  • 关于Android bitmap你不知道的一些事
    本文为大家分享了Android bitmap使用细节,供大家参考,具体内容如下 1、计算机表示图形的几种方式 1)BMP :几乎不进行压缩 占用空间比较大 2)JPG : 在...
    99+
    2022-06-06
    bitmap Android
  • 一名合格的SEO需要做的事情有哪些
    这篇文章将为大家详细讲解有关一名合格的SEO需要做的事情有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。  实际上现在SEO真的非常忙,而一名合格的SEO需要做的事情也非常多:  做好站内优化,你扪心...
    99+
    2023-06-10
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作