From b260234faf34b19227e87698bc2a1402c4ea76ac Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Tue, 18 Apr 2023 03:42:56 -0700 Subject: editing: add higher-precedence `SPACK_EDITOR` environment variable Other tools like git support `GIT_EDITOR` which takes higher precedence than the standard `VISUAL` or `EDITOR` variables. This adds similar support for Spack, in the `SPACK_EDITOR` env var. - [x] consolidate editor code from hooks into `spack.util.editor` - [x] add more editor tests - [x] add support for `SPACK_EDITOR` - [x] add a documentation section for controlling the editor and reference it --- lib/spack/docs/getting_started.rst | 3 ++- lib/spack/docs/packaging_guide.rst | 30 ++++++++++++++++++++++++++++-- lib/spack/spack/test/util/editor.py | 26 +++++++++++++++++++++++++- lib/spack/spack/util/editor.py | 2 ++ 4 files changed, 57 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/spack/docs/getting_started.rst b/lib/spack/docs/getting_started.rst index 3c847b876e..46bf657d62 100644 --- a/lib/spack/docs/getting_started.rst +++ b/lib/spack/docs/getting_started.rst @@ -368,7 +368,8 @@ Manual compiler configuration If auto-detection fails, you can manually configure a compiler by editing your ``~/.spack//compilers.yaml`` file. You can do this by running -``spack config edit compilers``, which will open the file in your ``$EDITOR``. +``spack config edit compilers``, which will open the file in +:ref:`your favorite editor `. Each compiler configuration in the file looks like this: diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst index 0b1e596abf..d7d63f634e 100644 --- a/lib/spack/docs/packaging_guide.rst +++ b/lib/spack/docs/packaging_guide.rst @@ -229,7 +229,8 @@ always choose to download just one tarball initially, and run Spack automatically creates a directory in the appropriate repository, generates a boilerplate template for your package, and opens up the new -``package.py`` in your favorite ``$EDITOR``: +``package.py`` in your favorite ``$EDITOR`` (see :ref:`controlling-the-editor` +for details): .. code-block:: python :linenos: @@ -335,6 +336,31 @@ The rest of the tasks you need to do are as follows: :ref:`installation_process` is covered in detail later. + +.. _controlling-the-editor: + +^^^^^^^^^^^^^^^^^^^^^^^^^ +Controlling the editor +^^^^^^^^^^^^^^^^^^^^^^^^^ + +When Spack needs to open an editor for you (e.g., for commands like +:ref:`cmd-spack-create` or :ref:`cmd-spack-edit`, it looks at several environment variables +to figure out what to use. The order of precedence is: + +* ``SPACK_EDITOR``: highest precedence, in case you want something specific for Spack; +* ``VISUAL``: standard environment variable for full-screen editors like ``vim`` or ``emacs``; +* ``EDITOR``: older environment variable for your editor. + +You can set any of these to the command you want to run, e.g., in ``bash`` you might run +one of these:: + + export VISUAL=vim + export EDITOR="emacs -nw" + export SPACK_EDITOR=nano + +If Spack finds none of these variables set, it will look for ``vim``, ``vi``, ``emacs``, +``nano``, and ``notepad``, in that order. + ^^^^^^^^^^^^^^^^^^^^^^^^^ Non-downloadable software ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1787,7 +1813,7 @@ for instructions on setting up a mirror. After running ``spack install pgi``, the first thing that will happen is Spack will create a global license file located at ``$SPACK_ROOT/etc/spack/licenses/pgi/license.dat``. It will then open up the -file using the editor set in ``$EDITOR``, or vi if unset. It will look like +file using :ref:`your favorite editor `. It will look like this: .. code-block:: sh diff --git a/lib/spack/spack/test/util/editor.py b/lib/spack/spack/test/util/editor.py index 18d19ff1d6..745c40ba85 100644 --- a/lib/spack/spack/test/util/editor.py +++ b/lib/spack/spack/test/util/editor.py @@ -19,7 +19,7 @@ pytestmark = [ # env vars that control the editor -EDITOR_VARS = ["VISUAL", "EDITOR"] +EDITOR_VARS = ["SPACK_EDITOR", "VISUAL", "EDITOR"] @pytest.fixture(scope="module", autouse=True) @@ -107,6 +107,30 @@ def test_editor_gvim_special_case(gvim_exe): assert ed.editor("/path/to/file", exec_fn=assert_exec) +def test_editor_precedence(good_exe, gvim_exe, vim_exe, bad_exe): + """Ensure we prefer editor variables in order of precedence.""" + os.environ["SPACK_EDITOR"] = good_exe + os.environ["VISUAL"] = gvim_exe + os.environ["EDITOR"] = vim_exe + correct_exe = good_exe + + def assert_callback(exe, args): + result = ed.executable(exe, args) + if result == 0: + assert exe == correct_exe + return result + + ed.editor(exec_fn=assert_callback) + + os.environ["SPACK_EDITOR"] = bad_exe + correct_exe = gvim_exe + ed.editor(exec_fn=assert_callback) + + os.environ["VISUAL"] = bad_exe + correct_exe = vim_exe + ed.editor(exec_fn=assert_callback) + + def test_find_exe_from_env_var_no_editor(): if "FOO" in os.environ: os.environ.unset("FOO") diff --git a/lib/spack/spack/util/editor.py b/lib/spack/spack/util/editor.py index 90644c7627..50e6b272c2 100644 --- a/lib/spack/spack/util/editor.py +++ b/lib/spack/spack/util/editor.py @@ -127,6 +127,8 @@ def editor(*args: List[str], exec_fn: Callable[[str, List[str]], int] = os.execv return try_exec(exe, full_args, var) # try standard environment variables + if try_env_var("SPACK_EDITOR"): + return True if try_env_var("VISUAL"): return True if try_env_var("EDITOR"): -- cgit v1.2.3-60-g2f50