Emacs 如何在elisp中使用filter执行sudo命令

Emacs 如何在elisp中使用filter执行sudo命令,emacs,lisp,elisp,Emacs,Lisp,Elisp,我想使用elisp执行一个特权命令,然后在看到某些输出时使用过滤器进行进一步处理 我的理解是,经过详尽的RTFM后,我可以: 将默认目录设置为以“/sudo::/”开头的路径 调用start file process启动将在sudo下运行的进程 下面是我编写的一个函数,它试图做到这一点: (取消启动vpn(配置文件密码文件回调) “启动VPN连接,等待DHCP地址, 然后用它得到的地址调用回调。“ (let*((默认目录)/sudo::/tmp) (buff(获取缓冲区创建“*openvpn*”

我想使用elisp执行一个特权命令,然后在看到某些输出时使用过滤器进行进一步处理

我的理解是,经过详尽的RTFM后,我可以:

  • 默认目录设置为以“/sudo::/”开头的路径
  • 调用
    start file process
    启动将在sudo下运行的进程
  • 下面是我编写的一个函数,它试图做到这一点:

    (取消启动vpn(配置文件密码文件回调)
    “启动VPN连接,等待DHCP地址,
    然后用它得到的地址调用回调。“
    (let*((默认目录)/sudo::/tmp)
    (buff(获取缓冲区创建“*openvpn*”)
    (proc(启动文件进程“openvpn”*openvpn*
    “/usr/local/sbin/openvpn”
    (concat--config“配置文件)
    (concat--auth user pass“密码文件”))
    (设置过程过滤器程序
    (λ(过程输出)
    (消息“Got output:”output)
    (let((ip(获取vpn ip地址输出)))
    (当ip
    (回拨ip((()()())))
    
    当我运行此命令时,我在
    *Messages*
    缓冲区中看到以下输出:

    start-vpn
    Tramp: Opening connection for root@localhost using sudo...
    Tramp: Sending command `exec sudo -u root -s -H -p Password:'
    
    Tramp: Waiting for prompts from remote shell
    Tramp: Sending command `exec sudo -u root -s -H -p Password:'
    Tramp: Found remote shell prompt on `localhost'
    Tramp: Opening connection for root@localhost using sudo...done
    (lambda (proc output) (message "Got output: " output) (let ((ip ...)) (if ip (progn ...))))
    Got output: 
    
    …并且在函数创建的
    *openvpn*
    缓冲区中没有输出

    我不是elisp的专家,所以我怀疑我犯了一些愚蠢的错误。我对
    *消息*
    缓冲区中的
    ”(lambda(proc…
    )也很好奇


    感谢您的任何建议、批评或提示。

    首先,在消息缓冲区中看到
    (lambda…
    的原因是
    set process filter
    返回过滤函数,因此
    start vpn
    也返回过滤函数

    您的
    消息
    调用需要包含格式说明符才能实际显示输出:

    (message "Got output: %s" output)
    
    (回调ip)
    将无法工作,原因有二:

    • Emacs Lisp有单独的函数和变量名称空间,因此
      (回调ip)
      将调用函数
      回调
      (该函数不存在),而您需要
      (funcall回调ip)
      调用存储在变量
      回调
      中的函数
    • 一旦过了这个阶段,由于Emacs Lisp默认使用动态范围,当调用lambda函数时,
      回调的绑定已经消失了

      在Emacs 24中,您可以将
      词法绑定设置为
      t
      ,并且上面的代码应该可以工作。在任何情况下,您都可以显式使用
      词法let
      宏:

      (lexical-let ((callback callback))
        (lambda (proc output)
          (message "Got output: " output)
          (let ((ip (get-vpn-ip-address output)))
            (when ip
              (funcall callback ip))))
      
      此宏使用黑魔法在lambda函数中保留
      回调
      的值