Personal emacs config
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
3.2 KiB

5 years ago
  1. ;;; inheritenv.el --- Make temp buffers inherit buffer-local environment variables -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2021 Steve Purcell
  3. ;; Author: Steve Purcell <steve@sanityinc.com>
  4. ;; URL: https://github.com/purcell/inheritenv
  5. ;; Package-Version: 0.1
  6. ;; Package-Commit: bc680a2670156cd482edba83d8c81142282174ba
  7. ;; Package-Requires: ((emacs "24.4"))
  8. ;; Version: 0.1-pre
  9. ;; Keywords: unix
  10. ;; This program is free software; you can redistribute it and/or modify
  11. ;; it under the terms of the GNU General Public License as published by
  12. ;; the Free Software Foundation, either version 3 of the License, or
  13. ;; (at your option) any later version.
  14. ;; This program is distributed in the hope that it will be useful,
  15. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ;; GNU General Public License for more details.
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. ;;; Commentary:
  21. ;; There's a fairly common pitfall when Emacs libraries run background
  22. ;; processes on behalf of a user: the library should honour any
  23. ;; environment variables set buffer-locally, but many such libraries run
  24. ;; processes in temporary buffers that do not inherit the calling
  25. ;; buffer's environment.
  26. ;; An example is the Emacs built-in command
  27. ;; `shell-command-to-string'. Whatever buffer-local `process-environment'
  28. ;; (or `exec-path') the user has set, that command will always use the
  29. ;; Emacs-wide default. This is *specified* behaviour, but not *expected*
  30. ;; or *helpful*, particularly if one uses a library like
  31. ;; `envrc' with "direnv".
  32. ;; `inheritenv' provides a couple of tools for dealing with this
  33. ;; issue:
  34. ;; 1. Library authors can wrap code that plans to execute processes in
  35. ;; temporary buffers with the `inheritenv' macro.
  36. ;; 2. End users can modify commands like `shell-command-to-string' using
  37. ;; the `inheritenv-add-advice' macro.
  38. ;;; Code:
  39. (require 'cl-lib)
  40. ;;;###autoload
  41. (defun inheritenv-apply (func &rest args)
  42. "Apply FUNC such that the environment it sees will match the current value.
  43. This is useful if FUNC creates a temp buffer, because that will
  44. not inherit any buffer-local values of variables `exec-path' and
  45. `process-environment'.
  46. This function is designed for convenient use as an \"around\" advice.
  47. ARGS is as for ORIG."
  48. (cl-letf* (((default-value 'process-environment) process-environment)
  49. ((default-value 'exec-path) exec-path))
  50. (apply func args)))
  51. ;;;###autoload
  52. (defmacro inheritenv (&rest body)
  53. "Wrap BODY so that the environment it sees will match the current value.
  54. This is useful if BODY creates a temp buffer, because that will
  55. not inherit any buffer-local values of variables `exec-path' and
  56. `process-environment'."
  57. `(inheritenv-apply (lambda () ,@body)))
  58. ;;;###autoload
  59. (defmacro inheritenv-add-advice (func)
  60. "Advise function FUNC with `inheritenv-apply'.
  61. This will ensure that any buffers (including temporary buffers)
  62. created by FUNC will inherit the caller's environment."
  63. `(advice-add ,func :around 'inheritenv-apply))
  64. (provide 'inheritenv)
  65. ;;; inheritenv.el ends here