emacs 查看变量的值_您需要了解的有关Emacs中变量的知识

emacs 查看变量的值

GNU Emacs用C和Emacs Lisp(Elisp)(Lisp编程语言的一种方言)编写。 因为它是一个文本编辑器,恰好是Elisp沙箱,所以了解基本的编程概念在Elisp中的工作方式很有帮助。

Emacs ,请访问Sacha Chua 为Emacs初学者准备的出色资源清单。 本文假定您熟悉常用的Emacs术语,并且知道如何阅读和评估Elisp代码的基本摘要。 理想情况下,您还应该听说过变量作用域及其在另一种编程语言中的工作方式。 这些示例还假设您使用的是最新的Emacs版本( v.25或更高版本 )。

Elisp手册包含了所有需要了解的内容,但是它是为已经知道他们要寻找的人而写的(确实非常有用)。 但是,许多人希望获得能在更高层次上解释Elisp概念并将信息量减少到最有用的位的资源。 本文是我对此的回应,旨在使读者更好地掌握基础知识,以便他们可以将其用于配置,并使人们更容易查看手册中的某些细节。

全局变量

defcustom定义的用户选项和用defvardefconst定义的变量是全局的。 defcustomdefvar声明的变量的一个重要方面是,重新评估它们不会重置已绑定的变量。 例如,如果您在初始化文件中为my-var建立绑定,如下所示:

 ( setq my - var nil ) 

计算以下形式不会将变量重置为t

 ( defvar my - var t ) 

请注意,有一个例外 :如果使用CMx评估上面的调用eval-defun的声明,则该值将重置为t 。 这样,您可以根据需要强制设置该值。 这种行为是故意的:您可能知道,Emacs中的许多功能仅按需加载(即,它们是自动加载的)。 如果这些文件中的声明将变量重置为其默认值,则它将覆盖init中的所有设置。

用户选项

用户选项只是使用defcustom声明的全局变量。 与使用defvar声明的变量不同,此类变量可通过Mx自定义接口进行配置。 据我所知,大多数人不会使用它,因为它感觉笨拙。 一旦知道了如何在init文件中设置变量,就没有理由使用它了。 许多用户不了解的一个细节是,使用customize设置用户选项可能会执行代码,有时这会用于运行其他设置指令:


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

如果您评估此代码并使用带有Mx custom-option RET my-option RETcustomize接口更改值,则将调用lambda,并且echo区域中的消息将告诉您该选项的符号和值。

如果在初始化文件中使用setq来更改此选项的值,则setter函数将不会运行。 要使用Elisp正确设置此类选项,您需要使用函数custom -set-variable 。 或者,人们在其配置中使用各种版本的csetq宏来自动处理此问题(如果愿意,您可以使用GitHub代码搜索来发现更复杂的变体):


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

如果您使用use-package宏,则:custom关键字将为您处理此问题。

将上面的代码放入您的init文件后,您可以使用csetq以尊重任何现有setter函数的方式设置变量。 使用此宏更改上面定义的选项时,可以通过在回显区域中查看消息来证明这一点:

 ( csetq my - option nil ) 

动态绑定和词汇绑定

如果使用其他编程语言,则可能没有意识到动态绑定和词法绑定之间的区别。 如今,大多数编程语言都使用词法绑定,当您了解变量作用域/查找时,无需了解它们之间的区别。

Emacs Lisp在这方面很特殊,因为默认情况下是动态绑定,并且必须显式启用词汇绑定。 这是有历史原因的,在实践中,应始终启用词汇绑定,因为它更快且不易出错。 要启用它,只需将以下注释行作为Emacs Lisp文件的第一行:

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

或者,您可以调用Mx add-file-local-variable-prop-line ,当您选择值为t的变量lexical-binding时,它将在上方插入注释行。

加载具有这种特殊格式的行的文件时,Emacs会相应地设置变量,这意味着将在启用了词法绑定的情况下加载该缓冲区中的代码。 以交互方式,您可以使用Mx eval-buffer ,它将词法绑定设置考虑在内。

既然您知道如何启用词法绑定,那么了解术语的含义就很明智了。 对于动态绑定,将在程序执行过程中建立的最后一个绑定用于变量查找。 您可以通过将以下代码放入空缓冲区并执行Mx 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 )

您可能会惊讶地发现在其他函数中变量a的查找成功。

如果重试前面的示例,并在顶部使用特殊的词法绑定注释,则代码将引发“ variables is void”错误,因为其他函数不知道a变量。 如果您来自另一种编程语言,这就是您所期望的行为。

使用词法绑定时,范围由周围的源代码定义。 这不仅是出于性能方面的原因-经验和时间表明,此行为是首选的。

特殊变量和动态绑定

如您所知, let用于临时建立本地绑定:


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

事情是这样的:用defcustomdefvardefconst声明的变量称为特殊变量 ,并且无论是否启用了词法绑定,它们都会继续使用动态绑定:


   
   
;;; -*- 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 ) )

要在上面的示例中看到两个消息,请使用Ch e切换到* Messages *缓冲区。

Let或函数参数绑定局部变量遵循与defvar定义的词汇绑定变量,但是全局变量定义的查找规则,defconst,defcustom可内心深处调用堆栈改变为身体的时间。

这种行为允许方便的临时自定义,并且经常在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的重要功能。 例如,主要模式使用它们来建立其本地缓冲区行为和设置。

您已经在本文中看到了局部缓冲区变量: 词法绑定的特殊注释行将局部缓冲区绑定到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检查默认值 。 要删除本地版本,可以调用Mx 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)))))))

这将设置Mx编译用于go模式缓冲区的编译命令。

另一个重要的方面是,某些变量是自动局部缓冲区的。 这意味着,一旦setq这样的变量,它将立即为当前缓冲区设置本地绑定。 不应经常使用此功能(因为这种隐式行为不好),但是如果需要,您可以创建这样的自动局部变量,如下所示:


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

变量indent-tabs-mode是其内置示例。 如果您在初始化文件中使用setq来更改此变量的值,则它根本不会影响默认值。 仅会在加载初始化文件时更改当前缓冲区的值。 因此,您需要使用setq-default更改indent-tabs-mode的默认值。

结束语

Emacs是一个功能强大的编辑器,只有根据您的需要对其进行更改,它才能变得更加强大。 现在您知道了Elisp如何处理变量以及如何在自己的脚本和配置中使用它们。


该文件先前已在CC BY-NC-SA 4.0许可下出现在With-Emacs中 ,并经过修改(带有合并请求)并在获得作者许可的情况下重新发布。

翻译自: https://opensource.com/article/20/3/variables-emacs

emacs 查看变量的值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值