ess – Envíe el contenido de la región o la línea actual a un archivo tmp, luego ejecute el script de shell con el nombre de archivo como argumento

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))))

Leave a Comment

Your email address will not be published. Required fields are marked *

web tasarım