Emacs:如何存储用户提供的最后一个参数作为默认值?

时间:2020-03-06 14:50:48  来源:igfitidea点击:

我正在编写一个交互式函数,我想记住用户提供的最后一个参数并将其用作默认值。

(defun run-rake (param)
  (interactive "sTask: ")
  (shell-command (format "rake %s" task)))

第一次调用该函数时,我希望它记住用户提供的参数,以便下次调用该函数时,可以按Enter键,它将使用上次提供的值。

我似乎在文档中找不到这个,如何在elisp中做到这一点?

解决方案

我想出了如何使用defvar(全局)手动进行此操作,但是感觉就像应该由核心库提供的那种东西(有点像方案的make-parameter)。这似乎比应有的代码更多,也更具手动性:

(defvar *editconf-ruby-run-rake-last-rake-task* nil)

(defun editconf-ruby-run-rake-last-rake-task (&optional new-val)
  (when new-val
    (setf *editconf-ruby-run-rake-last-rake-task* new-val))
  *editconf-ruby-run-rake-last-rake-task*)

(defun editconf-ruby-run-rake (task-name)
  "Execute rake `task-name'.  See                                                                                            
`krb-ruby-get-rakefile-path-for-current-buffer' for how the                                                                  
Rakefile is located.."
  (interactive
   (let* ((rakefile (krb-ruby-get-rakefile-path-for-current-buffer))
          (rake-tasks (krb-ruby-get-rake-tasks rakefile))
          (default-task (or (editconf-ruby-run-rake-last-rake-task)
                            (editconf-ruby-run-rake-last-rake-task (car rake-tasks)))))
     (list
      (read-string (format "Task [%s|%s]: "
                           rake-tasks
                           default-task)
                   nil nil default-task))))
  (editconf-ruby-run-rake-last-rake-task task-name)
  (let ((cmd (format "cd %s; rake %s"
                     (krb-lisp-strip-path-suffix rakefile 1)
                     task-name)))
    (message "editconf-ruby-run-rake: cmd='%s'" cmd)
    (shell-command cmd)))

我们可以看到compile命令如何做到这一点。使用C-h f compile调出compile命令的帮助文本,将光标移到包含该函数的文件的名称上,然后单击RETURN。这将调出compile的源文件。

基本上,有一个动态/全局变量" compile-command",它包含最后一个编译命令。 Emacs是一个单用户单线程系统,因此确实不需要更多。还请记住,Elisp是一个非常老派的Lisp,并且变量具有动态范围(调用堆栈),而不是词法范围。在这种系统中,自然是:

(let ((compile-command "gcc -o foo foo.c frobnicate.c"))
     ...
     (compile)
     ...)

说到compile命令,我们是否尝试过使用它来代替自己的run-rake函数?

read-from-minibuffer

是我们要使用的。它具有用于历史变量的位置。

这是一些示例代码:

(defvar run-rake-history nil "History for run-rake")
(defun run-rake (cmd)
(interactive (list (read-from-minibuffer "Task: " (car run-rake-history) nil nil 'run-rake-history)))
  (shell-command (format "rake %s " cmd)))

显然可以根据需求进行定制。 " run-rake-history"只是一个变量,用于存储此" mini-read读取"调用的历史记录。另一种选择是使用"完成读取",但前提是我们已获得要限制用户使用的选择列表(通常,类似shell的命令不是这种情况)。