Команда оболочки Emacs Lisp в регионе

В GNU Emacs я хочу запустить программу figlet для текущего выделенного текста. Затем я хочу прокомментировать созданный регион.

Я понял, как это сделать, используя стандартные команды Emacs:

  • установите отметку с помощью C- ‹space› в начале слова
  • переместите курсор в конец слова
  • C-u M-x shell-command-on-region RET figlet RET
  • M-x comment-region RET

Однако мне не удалось придумать, как написать программу Emacs lisp для выполнения всего этого. Вот моя попытка:

(defun figlet-region () 
  (interactive)
  (push-mark)
  (shell-command-on-region "figlet")
  (comment-region (mark) (point))
  (pop-mark)
)

(global-set-key "\C-c\C-f" 'figlet-region)

Тогда C-<space>; M-x figlet-region производит мусор:

figlet-region: Wrong number of arguments: #[(start end command &optional output-buffer replace error-buffer display-error-buffer) "ÆÇÈ  
\"!É
'jÊ!j;j
0Wb
?Ë`Ì\"Í ÎQÎDRÎÉ!\"&
ffÏ )ãÐqÑ!#Ò#p=¬É$]d|e^|Íed ΠÎD¡ÎÉ!\"&â%&#qÉ$Á&%Ó *Í ÉØ#DÚ#É!\"&*#Ô!#ÕÖ×!8WrÐ!qd`Z'o   ØcÙÉ\"d'Zb)(Úp!)Û!*" [error-buffer small-temporary-file-directory temporary-file-directory exit-status error-file replace make-temp-file expand-file-name "scor" nil ...] 9 1945557 (let (string) (unless (mark) (error "The mark is not set now, so there is no region")) (setq string (read-from-minibuffer "Shell command on region: " nil nil nil (quote shell-command-history))) (list (region-beginning) (region-end) string current-prefix-arg current-prefix-arg shell-command-default-error-buffer t))], 1

Отвечать

(defun figlet-region (&optional b e) 
  (interactive "r")
  (shell-command-on-region b e "figlet" (current-buffer) t)
  (comment-region (mark) (point)))

(Это основано на ответе Трея Джексона.)

Пример (режим взаимодействия с Лиспом)

;;  _   _                 _        
;; | |_| |__   __ _ _ __ | | _____ 
;; | __| '_ \ / _` | '_ \| |/ / __|
;; | |_| | | | (_| | | | |   <\__ \
;;  \__|_| |_|\__,_|_| |_|_|\_\___/

Пример (режим CPerl)

#  _   _                 _        
# | |_| |__   __ _ _ __ | | _____ 
# | __| '_ \ / _` | '_ \| |/ / __|
# | |_| | | | (_| | | | |   <\__ \
#  \__|_| |_|\__,_|_| |_|_|\_\___/

person Community    schedule 10.10.2009    source источник


Ответы (3)


Я не уверен, чего вы пытаетесь добиться, нажимая и выскакивая метки, я считаю, что вы получите ту же функциональность, сделав это:

(defun figlet-region (&optional b e) 
  (interactive "r")
  (shell-command-on-region b e "figlet")
  (comment-region b e))

Аргумент для Interactive указывает Emacs передать область (точку и метку) в качестве первых двух аргументов команды.

person Trey Jackson    schedule 10.10.2009
comment
обратите внимание, что shell-command-on-region может изменить регион, поэтому последняя строка должна читать (comment-region (mark) (point)), как в моем ответе. - person sds; 01.04.2014
comment
В форме, использованной в моем ответе, он не будет изменять регион (если только вы не вызываете его из буфера *Shell Command Output*, что просто странно). Если вы собираетесь использовать (mark) и (point) - нет смысла передавать регион через аргументы, поскольку он не будет работать должным образом, если не вызывается интерактивно. - person Trey Jackson; 02.04.2014
comment
представьте себе, что shell-command-on-region заменяет область _2 _-_ 3_ пустой строкой. будет тогда comment-region DRT? - person sds; 02.04.2014
comment
Да, если shell-command-on-region был вызван с большим количеством аргументов, тогда то, что вы говорите, верно. Но это не (в моем примере), поэтому ваша точка зрения не применима. Мой ответ не решает всей его проблемы, но он все понял. - person Trey Jackson; 02.04.2014

Использование интерактивной команды типа shell-command-on-region в программе lisp - не лучшая идея. Вместо этого вам следует использовать call-process-region:

(defun figlet-region (&optional b e) 
  (interactive "r")
  (call-process-region b e "figlet" t t)
  (comment-region (mark) (point)))

Он должен быть более устойчивым к различным пользовательским опциям.

person sds    schedule 23.05.2013
comment
Имейте в виду, что использование первого t после ‹command› в вызове call-process-region приводит к удалению региона. Сигнатура этой функции: ‹начало конечной программы и необязательное удаление целевого отображения и остальных аргументов› - person Alexandro de Oliveira; 10.05.2017

Ну, я не уверен, откуда идет мусор, но сама ошибка исходит от shell-command-region. При использовании в elisp он ожидает как минимум 3 аргумента: START END и COMMAND.

Кроме того, вообще плохая практика - возиться с пометкой в ​​функциях. Вот что говорит по этому поводу документ push-mark:

Начинающие программисты на Emacs Lisp часто пытаются использовать метку в неправильных целях. См. Документацию по `set-mark 'для получения дополнительной информации.

person Bahbar    schedule 10.10.2009