Muat ulang variabel lingkungan

10

Pertanyaan ini telah diajukan di superuser apakah ada cara untuk memuat ulang variabel lingkungan di emacs , tetapi tidak ada solusi yang baik diberikan.

Saya menggunakan EmacsClient dengan sering lebih dari 30 buffer terbuka, jika saya mengubah variabel lingkungan di shell, saya harus keluar dari EmacsClient (dan membuka kembali semua buffer) atau saya harus secara manual mengatur variabel lingkungan juga di Emacs. Saya merasa menjengkelkan bahwa saya tidak dapat memperbarui variabel lingkungan dengan mudah di Emacs. Ada saran?

Håkon Hægland
sumber
Tidak ada cara langsung untuk melakukan ini, karena mengubah variabel lingkungan dalam proses induk tidak akan memperbarui nilainya seperti yang diekspor ke anak.
Erik Hetzner

Jawaban:

7

exec-path-from-shell menyediakan exec-path-from-shell-copy-envperintah, yang memungkinkan Anda menyalin nilai variabel lingkungan ke sesi Emacs. Misalnya, M-x exec-path-from-shell-copy-env RET FOOatur nilai $FOOdalam Emacs juga.

Perhatikan bahwa exec-path-from-shell-copy-envmemunculkan shell baru untuk mengekstrak nilai variabel lingkungan. Karenanya itu hanya akan berfungsi untuk variabel yang Anda atur di file konfigurasi shell Anda (mis. .bashrc), Tetapi tidak untuk variabel yang hanya diatur dalam sesi shell yang berjalan dengannya export. Mengekstrak variabel-variabel ini umumnya tidak mungkin tanpa peretasan berbelit-belit yang memeriksa /proc/atau API serupa untuk menjalankan proses.

lunaryorn
sumber
Mengenai nilai-nilai yang terakhir / sementara, jika Emacs berjalan sebagai server kemudian meneruskan nilai-nilai yang diperbarui melalui emacsclient langsung dari shell itu akan cukup mudah.
phils
@phils Terima kasih, lihat jawaban saya yang diperbarui ..
Håkon Hægland
5

Sebagai solusinya, berikut ini dapat digunakan (Linux, Bash):

  • Jalankan pertama printenv -0 > env.txtdari jendela terminal Bash,
  • Kemudian dari dalam Emacs, jalankan
(defun my-update-env ()
  (interactive)
  (let ((str 
         (with-temp-buffer
           (insert-file-contents "env.txt")
           (buffer-string))) lst)
    (setq lst (split-string str "\000"))
    (while lst
      (setq cur (car lst))
      (when (string-match "^\\(.*?\\)=\\(.*\\)" cur)
        (setq var (match-string 1 cur))
        (setq value (match-string 2 cur))
        (setenv var value))
      (setq lst (cdr lst)))))

Memperbarui

Saya ternyata ini bisa dilakukan dengan lebih elegan menggunakan --evalopsi emacsclientperintah: Tentukan skrip Bash update_emacs_env:

#! /bin/bash

fn=tempfile
printenv -0 > "$fn" 
emacsclient -s server_name -e '(my-update-env "'"$fn"'")' >/dev/null

di mana server_namenama server Emacs Anda, dan my-update-envmerupakan fungsi yang ditentukan oleh ~/.emacsfile Anda :

(defun my-update-env (fn)
  (let ((str 
         (with-temp-buffer
           (insert-file-contents fn)
           (buffer-string))) lst)
    (setq lst (split-string str "\000"))
    (while lst
      (setq cur (car lst))
      (when (string-match "^\\(.*?\\)=\\(.*\\)" cur)
        (setq var (match-string 1 cur))
        (setq value (match-string 2 cur))
        (setenv var value))
      (setq lst (cdr lst)))))

Sekarang Anda cukup mengetik update_emacs_envdari baris perintah shell untuk memperbarui variabel lingkungan Emacs ..

Håkon Hægland
sumber
Dan Anda dapat menjalankan "printenv" dari dalam fungsi juga ...
mankoff
@mankoff Sebenarnya, saya pikir Anda tidak bisa .. :) (Ini akan mencetak nilai-nilai lama)
Håkon Hægland
Tidak bisakah kamu menelurkan shell dengan flag login? Atau source.bashrc, .bash_profile, dll?
mankoff
Ya .. tapi itu tidak akan membantu untuk kasus khusus jika saya mengekspor dalam shell langsung dari baris perintah, menggunakanexport VAR=value
Håkon Hægland
Ya saya tidak memikirkan kasus itu. Solusi elegan dengan klien!
mankoff
3

Saya menggunakan ini:

function export-emacs {
    if [ "$(emacsclient -e t)" != 't' ]; then
        return 1
    fi

    for name in "${@}"; do
        value=$(eval echo \"\$${name}\")
        emacsclient -e "(setenv \"${name}\" \"${value}\")" >/dev/null
    done
}

Memungkinkan Anda mengekspor variabel bernama, EG:

export EDITOR=vim
export-emacs EDITOR
Phil Jackson
sumber