Как заставить Emacs использовать мой файл.bashrc?

Мне нужно использовать мой $PATH в Emacs запустить несколько команд. Как я могу заставить Emacs использовать это? Я установил Emacs из репозиториев Ubuntu.

9 ответов

Решение

Вот трюк, который я использую, чтобы мой графический интерфейс Emacs всегда видел одинаково $PATH что я попал внутрь раковины:

(defun set-exec-path-from-shell-PATH ()
  (let ((path-from-shell (replace-regexp-in-string
                          "[ \t\n]*$"
                          ""
                          (shell-command-to-string "$SHELL --login -i -c 'echo $PATH'"))))
    (setenv "PATH" path-from-shell)
    (setq eshell-path-env path-from-shell) ; for eshell users
    (setq exec-path (split-string path-from-shell path-separator))))

(when window-system (set-exec-path-from-shell-PATH))

В частности, в OS X графический Emacs не будет использовать определение оболочки пользователя $PATHТаким образом, этот трюк помогает мне на этой платформе.

Обновление: этот код был опубликован в виде библиотеки elisp под названием https://github.com/purcell/exec-path-from-shell, и в MELPA доступны устанавливаемые пакеты.

Более общее решение (установить все переменные и псевдонимы, а не только PATH) указан в /questions/1056437/est-li-sposob-zastavit-moi-emacs-raspoznavat-moi-psevdonimyi-bash-i-polzovatelskie-funktsii-kogda-ya-zapuskayu-komandu-obolochki/1056456#1056456 - ключ должен быть установлен:

(setq shell-command-switch "-ic")

который отменяет значение по умолчанию "-c" (выполните следующую команду). Добавление "-i" переводит оболочку bash в интерактивный режим, что приводит к ~/.bashrc,

Если ваши env vars не собраны, это может быть связано с тем, как запускается emacs. Проверьте пункт меню или что-то еще и попробуйте изменить emacs в bash -c emacs,

Вы можете добавить настройки пути в /etc/profile.d, такие как

# /etc/profile.d/path.sh
export PATH="$PATH:/usr/local"

В Ubuntu, я помню все сеансы источника вашего ~/.xsessionrc, так что вы также можете установить путь в этом файле для приложений с графическим интерфейсом.

Я придумал что-то похожее для поиска моего.bash_profile. Если вы заботитесь только о PATH, один из других ответов выше проще.

Это работает, выполняя source ~/.bash_profile ; echo post-env; env затем отбрасывает все перед "post-env", а затем анализирует значения в формате "ключ = значение", которые печатает команда "env".

Вероятно, он не справляется с каждым случаем идеально, но работает достаточно хорошо для меня.

;;-------------------------------------------------------
;; begin sourcing of .bash_profile

;; only do this on Mac OS X
(when (string= system-type "darwin")
  ;; require common lisp extensions, for search
  (require 'cl)


  (defun src-shell-unescape (string)
    ;; replace \n \t \r \b \a \v \\
    ;; and octal escapes of the form \0nn

    (replace-regexp-in-string
     "\\\\\\([ntrbav]\\|\\(\\\\\\)\\|\\(0[0-7][0-7]\\)\\)"
     (lambda (str)
       ;; interpret octal expressions
       ;; of the form "\0nn"
       (let ((char1 (aref str 1)))
     (cond ((= ?0 (aref str 1))
        (byte-to-string
         (+ (* (- (aref str 2) ?0) 8)
            (- (aref str 3) ?0))))
           ((eq char1 ?n) "\n")
           ((eq char1 ?t) "\t")
           ((eq char1 ?r) "\r")
           ((eq char1 ?b) "\b")
           ((eq char1 ?a) "\a")
           ((eq char1 ?v) "\v")
           ((eq char1 ?\\) "\\\\")
           (t "")))) string))

  (defun src-set-environment-from-env-output(env-output)
    ;; set the environment from shell's "env" output
    (let ((lines (split-string env-output "\n" t)))
      (dolist (line lines)
    (let ((idx-equals (search "=" line)))
      (when (and (not (eq idx-equals nil))
             (> idx-equals 1))
        (let  ((key (substring line 0 idx-equals))
           (value (substring line (+ idx-equals 1))))
          (setenv key (src-shell-unescape value))
          ;; (message "%s = %s" key value)
          ))))))

  (defun src-source-shell-file (file-name)
    ;; if your shell is sh rather than bash, the "source " may need
    ;; to be ". " instead
    (let* ((command (concat "source '"  file-name "'; echo 'post-env'; env"))
       (output (shell-command-to-string command))
       (idx-post-env (search "post-env" output)))
      (if (eq nil idx-post-env)
      (message "Didn't find expected output after sourcing %s. Found: %s" file-name output)
    (let ((trimmed-output (substring output idx-post-env)))
      ;; (message "trimmed-output: %s" trimmed-output)
      (src-set-environment-from-env-output trimmed-output)))))



  (src-source-shell-file (expand-file-name "~/.bash_profile")))


;; end sourcing of .bash_profile
;;-------------------------------------------------------

Это действительно должен быть комментарий, но форматирование не сработало. Ответ от @Hueges сработал для меня, за исключением того, что он вызвал проблемы сdiredрежим. Кто-то с более сильным elisp мог бы добиться большего успеха, но это сработало для меня.

      ;; temporarily set shell-command-switch to -ic until function completes
(defun wrap-shell-command (func &rest args) 
  (let ((current-shell-command-switch shell-command-switch)) 
    (setq shell-command-switch "-ic") 
    (apply func args) 
    (setq shell-command-switch current-shell-command-switch)))

;; usage
(wrap-shell-command 'shell-command "func-define-in-bashrc" "other" "args")

Есть много пакетов Emacs, которые обновляют переменную окружения $PATH и 'exec-path'. Это потому, что Emacs не принимает определений в файлах, связанных с BASH, таких как '~/.bashrc'.

Все определения, которые вам нужны в любой программе, не выполняемой из оболочки терминала, необходимо переместить в '~/.profile', они загружаются при запуске системы.

Некоторым старым системам необходимо вручную загружать профиль пользователя из /etc/profile.

      ;; set shell-command-switch to -ic only for async-shell-command
(defun pre-command-hook-fn ()
  "."
  (if (string= current-minibuffer-command "async-shell-command")
      (setq shell-command-switch "-ic")
    (setq shell-command-switch "-c")
    )
  )

(add-hook 'minibuffer-setup-hook 'pre-command-hook-fn)

ЗАДАЧА: Измените «exec-path», чтобы завершение минибуфера использовало PATH интерактивной оболочки.

Если $PATH установлен в терминале, с которого вы запускаете emacs, вы можете выполнять системные команды через команду M-! <your command> RET,

Другие вопросы по тегам