2012-11-22 12 views
6

Sto usando un'istanza di emacs locale (aquamacs) per eseguire processi R su un server remoto, e mi piacerebbe automatizzare il processo di connessione al mio server. Il processo è il seguente:Come posso automatizzare questi comandi emacs ESS (ess-remote)?

[in emacs]

M-x shell 

[nella console risultante]

TERM=xterm 
ssh -Y -C <my remote server> 
screen -rd [and/or] R 

[in emacs]

M-x ess-remote 
r 

ho scoperto questo approccio generale qui: http://blog.nguyenvq.com/2010/07/11/using-r-ess-remote-with-screen-in-emacs/. Le opzioni -Y -C ti permettono di usare xterm per visualizzare i grafici. Non conosco la chiarezza e così ho cercato su Google un po ', non riesco a ricostruire insieme come definire una funzione per automatizzarla (ad esempio, in .emacs.el). Qualcuno ha implementato qualcosa di simile?

risposta

6

Supponiamo che vogliate solo chiamare shell nel codice. In Lisp, tutto è notazione di prefisso circondata da parentesi. Così entriamo questo in un buffer (ad esempio, il buffer scratch):

(shell) 

spostare il puntatore alla fine della riga, dopo i primi parentesi e digitare <C-x C-e> per eseguire il codice Lisp. Dovresti vedere che viene chiamata la funzione shell.

Ora, facciamo una funzione, in modo che possiamo aggiungere altre cose ad esso. Il comando per creare una funzione è defun, e prende il nome della funzione, la lista degli argomenti (tra parentesi), e poi il corpo della funzione:

(defun automate-connection() 
    (shell)) 

Spostare il cursore alla fine del codice , premere <C-x C-e> e la funzione verrà definita. Si può chiamare da Lisp eseguendo

(automate-connection) 

Ok, ora abbiamo solo bisogno di mettere un po 'di testo nel buffer di shell.

(defun automate-connection() 
    (shell) 
    (insert "TERM=xterm")) 

Ora, quando lo eseguiamo, otteniamo "TERM = xterm" messo nel buffer di shell. Ma in realtà non invia il comando. Proviamo a mettere una newline.

(defun automate-connection() 
    (shell) 
    (insert "TERM=xterm\n")) 

Inserisce una nuova riga, ma in realtà non esegue il comando. Perchè no? Vediamo cosa fa la chiave di invio. Vai al tuo buffer *shell* e digita <C-h c>, quindi premi il tasto Invio. (<C-h c> esegue describe-key-briefly, che stampa il nome della funzione invocata premendo la chiave specificata). Questo dice che quando si preme RET, non sta mettendo una newline, ma in realtà chiama comint-send-input. Allora, facciamo che:

(defun automate-connection() 
    (shell) 
    (insert "TERM=xterm") 
    (comint-send-input)) 

Ora, quando si esegue `(automatizzare-connessione) da qualsiasi codice Lisp, si dovrebbe ottenere la cosa dato inviato. Lascio come un esercizio al lettore per aggiungere i tuoi altri comandi.

Ma aspetta! Non abbiamo davvero finito, vero? Presumo che non vogliate passare a un buffer scratch Lisp, digitare (automate-connection), quindi valutare quel codice. Probabilmente vuoi solo digitare e chiamarlo un giorno.Non è possibile farlo per impostazione predefinita con la funzione appena creata. Per fortuna, è semplice per permettere che: basta aggiungere una chiamata a (interactive) nella funzione:

(defun automate-connection() 
    (interactive) 
    (shell) 
    (insert "TERM=xterm") 
    (comint-send-input)) 

Ora si può chiamare come si vuole, e si aprirà il buffer *shell*, inserire nel testo, e dire Emacs per dire alla shell di eseguire quel testo.

+0

questo è estremamente utile, grazie. Ora ho: '(defun automatate-connection() (interattivo) (shell) (inserisci" TERM = xterm \ n ssh -Y -C \ n screen -rd ") (comint-send-input) (ess-remote) ) ' ma' (ess-remote) 'non sembra funzionare a meno che non sia già in esecuzione un processo R-in-shell. Immagino di dover fare qualcosa tra "(comint-send-input)" e "(ess-remote)" – Solomon

Problemi correlati