Pregunta:
Estoy haciendo la transición a Emacs con el modo malvado después de años de Vim. Por razones laborales, tengo que usar un programa de estadísticas GUI (Stata) con frecuencia. Este programa no se integra bien con editores externos. ess-mode
no es compatible con la versión GUI de Stata, sino solo con una versión de terminal muy limitada. Prefiero una solución simple que pueda mantener yo mismo.
Para que funcione con Vim, escribí un script de shell usando xdotool
que toma como argumento un nombre de archivo, abre la ventana GUI, pega "do filename" en la ventana de comandos, envía return y luego vuelve a la ventana del editor original. No es una solución sofisticada, pero funciona bien en la práctica.
En mi .vimrc
tenía un código que escribiría la región actualmente seleccionada o la línea actual en un archivo temporal en /tmp/randomfoldername/consecutivenumber.do
, luego llamar al script de shell con ese archivo como argumento. Al salir de vim, la carpeta se eliminaría.
Estoy buscando replicar esta funcionalidad en Emacs, pero no sé cómo ni por dónde empezar. Básicamente, quiero imitar lo que están haciendo las funciones del ess-mode
ess-eval-region-or-line-and-step
y ess-eval-buffer
, simplemente llamando al script de shell con el nombre de un archivo temporal o el nombre de el búfer actual.
Si ayuda, este es el código de vimscript:
" Run current buffer
fun! RunIt()
w
!sh "~/dotfiles/rundo.sh" "%:p"
endfun
" Run selection
fun! RunDoLines()
let selectedLines = getbufline('%', line("'<"), line("'>"))
if col("'>") < strlen(getline(line("'>")))
let selectedLines[-1] = strpart(selectedLines[-1], 0, col("'>"))
endif
if col("'<") != 1
let selectedLines[0] = strpart(selectedLines[0], col("'<")-1)
endif
let temp = tempname() . ".do"
call writefile(selectedLines, temp)
exec "!sh ~/dotfiles/rundo.sh " . temp
au VimLeave * silent exe '!del /Q "'.$TEMP.'\*.tmp.do"'
endfun
" Mappings
au FileType stata noremap <F8> :<C-U>call RunIt()<CR><CR>
au FileType stata noremap <F9> :<C-U>call RunDoLines()<CR><CR>
au FileType stata noremap <C-Return> <S-v>:<C-U>call RunDoLines()<CR><CR>
Respuesta:
Si su ~/dotfiles/rundo.sh
acepta stdin como entrada, como muchos otros comandos como grep / wc / bash / python, para ejecutar un comando con la región como stdin, simplemente ejecute M-| ~/dotfiles/rundo.sh
( M-|
ejecuta shell-command-on-region
).
Si el comando no es compatible con stdin, lo siguiente debería hacer lo que describió
(defun rundo (beg end)
"Wrapper of ~/dotfiles/rundo.sh."
(interactive
;; 1. If the region is highlighted
(if (use-region-p)
;; the region
(list (region-beginning) (region-end))
;; the line
(list (line-beginning-position) (line-end-position))))
;; 2. create a temp file
(let ((tempfile (make-temp-file nil nil ".do")))
;; 3. save text to the file
(write-region beg end tempfile)
;; 4. run the command asynchronously
;; (remove '&' to run it synchronously, i.e., blocking Emacs)
(shell-command (format "~/dotfiles/rundo.sh %s &" tempfile))))