-
-
Notifications
You must be signed in to change notification settings - Fork 899
Editor
Print information about the default editor (
$VISUALor$EDITOR)
| Module type | editor |
| Default order | 16 (only used by --gen-config) |
| Module source | src/modules/editor/editor.c |
| Detection source | src/detection/editor/ |
Prints the editor named by $VISUAL (preferred) or $EDITOR, together with its version when one
could be determined. The version is printed only when the resolved executable name is known.
Both variables hold a shell command line rather than a bare name, so only the first word of the
value is used: EDITOR="code -w" reports code. A value that does not name a runnable program is
an error, not something the module echoes back.
Editor: nano 9.2
Editor: nvim 0.10.2
Editor: vim
The module is platform-independent. src/detection/editor/editor.c is a single file listed in
the common source list (CMakeLists.txt:484), there is no editor_nosupport.c, and no platform
block in CMakeLists.txt mentions detection/editor — the same code runs everywhere.
| Platform | Implementation | Notes |
|---|---|---|
| All ten supported platforms | editor.c |
Reads $VISUAL / $EDITOR, resolves the path, optionally runs the binary |
The only platform-conditional lines in the file are the path separator (/ versus \), the
stripping of a trailing .exe on Windows, and a snap carve-out on Linux (see below).
| Key | Type | Default | Description |
|---|---|---|---|
key |
string | module name | Module key. A single space hides the key and the separator. |
keyColor |
color | – | Overrides display.color.keys. |
keyWidth |
integer | – | Overrides display.key.width. |
keyIcon |
string | built-in glyph | Printed when display.key.type includes the icon bit. Any glyph works, "" prints none. |
outputColor |
color | – | Overrides display.color.output. |
format |
string | – | Custom output format (see below). |
condition |
object | – | Show the module only if the conditions match. |
There are no module-specific keys. The editor to report is chosen by the environment, not by
configuration — there is no editor or command option.
Run fastfetch -h editor-format for the authoritative list.
| Variable | Description |
|---|---|
{type} |
Visual when $VISUAL was used, Editor when $EDITOR was |
{name} |
First word of the environment value — the name that was looked up |
{exe-name} |
Basename of the resolved path |
{path} |
Full resolved path of the editor |
{version} |
Version string, empty when it could not be determined |
Note the key order and naming: the resolved basename is exe here but {exe-name} in a format
string, and name is the first word of the environment value, not the editor's display name.
{ "type": "editor", "format": "{type}: {exe-name} {version}" }{ "type": "editor", "key": "EDITOR", "format": "{path}" }-
The value is split on whitespace, so a path containing a space cannot be used. Only the first word is taken as the program name. That is what makes
EDITOR="code -w"work, but it also means a value such asEDITOR='/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code'is cut down to
/Applications/Visual, which then failsrealpath(). Point the variable at a launcher on$PATH(code) or at a path without spaces. Quoting inside the variable does not help — the split happens before anything is looked up, and the quotes are not stripped. -
A value that does not name an executable is an error. If the name is not on
$PATH, ifrealpath()fails, or if the resolved path has no basename, detection fails and the message names the variable that was actually read:EDITOR=bogus -> Editor: $EDITOR does not point to an executable VISUAL=' ' -> Editor: $VISUAL does not point to an executableAn absolute
$EDITORis copied intopathbefore it is validated, so a path that does not exist is caught here too rather than being handed to a consumer unchecked.{path}therefore always refers to something that existed at detection time. -
A failed detection prints nothing by default. The error goes through
ffPrintError(), which returns early whiledisplay.showErrorsisfalse— the built-in default. A line that fails is simply absent from the output, so the module can look like it was never requested. Use--format json, which reports"error"unconditionally, or setdisplay.showErrors: truein the config to see the message. -
{type}is neverUnknown. It is set toVisualorEditorbefore any of the early returns, so the"Unknown"initialiser inffPrintEditor()is unreachable. It is the only field that is always meaningful. -
{version}only exists for a fixed list of editors. Version detection knowsnvim,vim(includingvim.basic/vim.tiny),nano,micro,emacs(includingemacs-29.3),hx,code,pluma,sublime_text,zeditor,kak,picoandne. Any other editor prints its name alone. -
Version detection executes the editor.
nvim,vimandnanoare first probed by scanning the binary for a version literal, but the rest are run — with--version,-version, or-hforne. Setgeneral.detectVersiontofalseto keep fastfetch side-effect free. -
The version is a guess from the first line. After the probe, the output is cut at the first newline, then the first run of digits is taken as the version and terminated at the next whitespace. An editor whose
--versionprints a banner before the version, or whose version has no digits, yields an empty or wrong{version}. -
A snap-installed editor keeps its unresolved path on Linux. The
realpath()result is discarded when it ends in/snap, so{path}stays the symlink path for snap wrappers while{exe-name}is still derived from it. -
The
$VISUAL/$EDITORprecedence is the standard one, with an empty value treated as unset. The check is on the value's length, soVISUAL= EDITOR=nanoreportsnanowith{type}set toEditor. Only when both are empty does the module print$VISUAL or $EDITOR not set. A value that is nothing but whitespace (VISUAL=' ') is non-empty and therefore wins the precedence, but it splits down to an empty name and is then reported as not an executable — the$EDITORit shadowed is never consulted.
ffDetectEditor() is a short pipeline:
-
Pick the variable.
getenv("VISUAL")first; if the result has non-zero length,typeis set to"Visual". Otherwisegetenv("EDITOR")is tried andtypebecomes"Editor". If both are empty the function returns the one genuine error string,$VISUAL or $EDITOR not set. -
Take the first word. The value is truncated at the first whitespace character, so arguments
such as
-wor-fare dropped andnameends up holding the program name alone. Which variable the value came from is remembered in a flag, so every failure further down can name it. -
Resolve the path. An absolute value is copied into
pathas-is; anything else goes throughffFindExecutableInPath(), which searches$PATH. Both failure modes — name not found, and the empty name a whitespace-only value leaves behind — return the same$VISUAL/$EDITOR does not point to an executablemessage. -
Canonicalise.
realpath()is called onpathand its failure is reported, since an absolute value was copied intopathbefore being checked. On Linux the result is only stored when it does not end in/snap, which keeps snap's wrapper symlink visible instead of the versioned binary inside the snap. -
Derive the executable name. Everything after the last
/(or\on Windows) becomesexe, with a trailing.exestripped on Windows. The two guards around this — no separator in the path, empty basename — return a distinctFailed to determine the executable name, because anullptrhere would have been read as success. -
Version. Skipped entirely unless
instance.config.general.detectVersionis true.nvim,vimandnanouseffBinaryExtractStrings()with a literal prefix (NVIM v,VIM - Vi IMproved,GNU nano); forvimthe extracted string is additionally cut at the first space. Every other known editor is executed with the argument from a fixed table, and the first line of its output is reduced to the first numeric token bystrpbrk()on digits and then on whitespace.
The module also #includes detection/libc/libc.h (editor.c:4) and never calls a single symbol
from it. Classifying platform support by includes rather than by symbol usage would wrongly mark
Editor as unsupported on the BSDs, Solaris and Haiku, where the libc subsystem has no
implementation.
ffPrintEditor() and ffGenerateEditorJsonResult() each call ffDetectEditor() and each free the
four strbufs through a shared destroyEditorResult(). The error path frees them too — it is now a
path that is actually taken, not an unreachable one, and it used to leak all four buffers.
{ "type": "Editor", "result": { "type": "Visual", "name": "nano", "path": "/usr/bin/nano", "exe": "nano", "version": "9.2" } }