Emacs: come memorizzi l'ultimo parametro fornito dall'utente come predefinito?
Domanda
Sto scrivendo una funzione interattiva che mi piacerebbe ricordare l'ultimo argomento fornito dall'utente e usarlo come predefinito.
(defun run-rake (param)
(interactive "sTask: ")
(shell-command (format "rake %s" task)))
La prima volta che viene invocata la funzione, voglio che ricordi l'argomento fornito dall'utente in modo che la volta successiva che invochino la funzione possano semplicemente premere invio e utilizzerà il valore fornito la volta precedente.
Non riesco a trovarlo nella documentazione - come si fa in elisp?
Soluzione
Puoi vedere come il comando compila
fa questo. Apri il testo di aiuto per il comando di compilazione con C-h f compila
, sposta il cursore sul nome del file che contiene la funzione, quindi premi RETURN
. Questo farà apparire il file sorgente per compila
.
Fondamentalmente, c'è una variabile dinamica / globale comando di compilazione
che contiene l'ultimo comando di compilazione. Emacs è un sistema a thread singolo per utente singolo, quindi non c'è davvero bisogno di molto altro. Inoltre, tieni presente che Elisp è un Lisp di vecchia scuola e le variabili hanno un ambito dinamico (call stack), non lessicale. In questo tipo di sistema è naturale:
(let ((compile-command "gcc -o foo foo.c frobnicate.c"))
...
(compile)
...)
Parlando del comando compila
, hai provato a usarlo al posto della tua funzione run-rake
?
Altri suggerimenti
read-from-minibuffer
è quello che vuoi usare. Ha un posto per una variabile storica.
Ecco un codice di esempio:
(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)))
Ovviamente personalizza le tue esigenze. 'Run-rake-history è semplicemente una variabile che viene utilizzata per memorizzare la cronologia per questa invocazione di' read-from-minibuffer. Un'altra opzione sarebbe quella di usare "completing-read - ma ciò presuppone che tu abbia un elenco di scelte che vuoi limitare all'utente (che di solito non è il caso di comandi simili a shell).
Ho capito come farlo manualmente usando un defvar (globale), ma questo sembra il tipo di cosa che dovrebbe già essere fornito dalla libreria principale (tipo di make-parametro simile allo schema). Questo sembra solo più codice e più manuale di quanto dovrebbe essere:
(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)))