diff options
Diffstat (limited to 'src/detection/editor')
| -rw-r--r-- | src/detection/editor/editor.c | 160 | ||||
| -rw-r--r-- | src/detection/editor/editor.h | 14 |
2 files changed, 174 insertions, 0 deletions
diff --git a/src/detection/editor/editor.c b/src/detection/editor/editor.c new file mode 100644 index 0000000..b84f279 --- /dev/null +++ b/src/detection/editor/editor.c @@ -0,0 +1,160 @@ +#include "editor.h" +#include "common/processing.h" +#include "common/library.h" +#include "common/strutil.h" +#include "common/path.h" +#include "common/binary.h" + +#include <stdlib.h> + +static bool extractNvimVersionFromBinary(const char* str, FF_A_UNUSED uint32_t len, void* userdata) { + if (!ffStrStartsWith(str, "NVIM v")) { + return true; + } + ffStrbufSetS((FFstrbuf*) userdata, str + strlen("NVIM v")); + return false; +} + +static bool extractVimVersionFromBinary(const char* str, FF_A_UNUSED uint32_t len, void* userdata) { + if (!ffStrStartsWith(str, "VIM - Vi IMproved ")) { + return true; + } + ffStrbufSetS((FFstrbuf*) userdata, str + strlen("VIM - Vi IMproved ")); + ffStrbufSubstrBeforeFirstC(userdata, ' '); + return false; +} + +static bool extractNanoVersionFromBinary(const char* str, FF_A_UNUSED uint32_t len, void* userdata) { + if (!ffStrStartsWith(str, "GNU nano ")) { + return true; + } + ffStrbufSetS((FFstrbuf*) userdata, str + strlen("GNU nano ")); + return false; +} + +const char* ffDetectEditor(FFEditorResult* result) { + ffStrbufSetS(&result->name, getenv("VISUAL")); + if (result->name.length) { + result->type = "Visual"; + } else { + ffStrbufSetS(&result->name, getenv("EDITOR")); + if (result->name.length) { + result->type = "Editor"; + } else { + return "$VISUAL or $EDITOR not set"; + } + } + + if (ffIsAbsolutePath(result->name.chars)) { + ffStrbufSet(&result->path, &result->name); + } else { + const char* error = ffFindExecutableInPath(result->name.chars, &result->path); + if (error) { + return NULL; + } + } + + { + char buf[PATH_MAX + 1]; + if (!realpath(result->path.chars, buf)) { + return NULL; + } + + // WIN32: Should we handle scoop shim exe here? + +#ifdef __linux__ + if (!ffStrEndsWith(buf, "/snap")) +#endif + ffStrbufSetS(&result->path, buf); + } + + { + uint32_t index = ffStrbufLastIndexC(&result->path, +#ifndef _WIN32 + '/' +#else + '\\' +#endif + ); + if (index == result->path.length) { + return NULL; + } + ffStrbufSetS(&result->exe, &result->path.chars[index + 1]); + if (!result->exe.length) { + return NULL; + } + +#ifdef _WIN32 + if (ffStrbufEndsWithS(&result->exe, ".exe")) { + ffStrbufSubstrBefore(&result->exe, result->exe.length - 4); + } +#endif + } + + if (!instance.config.general.detectVersion) { + return NULL; + } + + if (ffStrbufEqualS(&result->exe, "nvim")) { + ffBinaryExtractStrings(result->path.chars, extractNvimVersionFromBinary, &result->version, (uint32_t) strlen("NVIM v0.0.0")); + } else if (ffStrbufEqualS(&result->exe, "vim") || ffStrbufStartsWithS(&result->exe, "vim.")) { + ffBinaryExtractStrings(result->path.chars, extractVimVersionFromBinary, &result->version, (uint32_t) strlen("VIM - Vi IMproved 0.0")); + } else if (ffStrbufEqualS(&result->exe, "nano")) { + ffBinaryExtractStrings(result->path.chars, extractNanoVersionFromBinary, &result->version, (uint32_t) strlen("GNU nano 0.0")); + } + + if (result->version.length > 0) { + return NULL; + } + + const char* param = NULL; + if ( + ffStrbufEqualS(&result->exe, "nano") || + ffStrbufEqualS(&result->exe, "vim") || + ffStrbufStartsWithS(&result->exe, "vim.") || // vim.basic/vim.tiny + ffStrbufEqualS(&result->exe, "nvim") || + ffStrbufEqualS(&result->exe, "micro") || + ffStrbufEqualS(&result->exe, "emacs") || + ffStrbufStartsWithS(&result->exe, "emacs-") || // emacs-29.3 + ffStrbufEqualS(&result->exe, "hx") || + ffStrbufEqualS(&result->exe, "code") || + ffStrbufEqualS(&result->exe, "pluma") || + ffStrbufEqualS(&result->exe, "sublime_text") || + ffStrbufEqualS(&result->exe, "zeditor")) { + param = "--version"; + } else if ( + ffStrbufEqualS(&result->exe, "kak") || + ffStrbufEqualS(&result->exe, "pico")) { + param = "-version"; + } else if ( + ffStrbufEqualS(&result->exe, "ne")) { + param = "-h"; + } else { + return NULL; + } + + ffProcessAppendStdOut(&result->version, (char* const[]) { + result->path.chars, + (char*) param, + NULL, + }); + + if (result->version.length == 0) { + return NULL; + } + + ffStrbufSubstrBeforeFirstC(&result->version, '\n'); + const char* versionStart = strpbrk(result->version.chars, "0123456789"); + if (versionStart != NULL) { + const char* versionEnd = strpbrk(versionStart, " \t\v\f\r"); + if (versionEnd != NULL) { + ffStrbufSubstrBefore(&result->version, (uint32_t) (versionEnd - result->version.chars)); + } + + if (versionStart != result->version.chars) { + ffStrbufSubstrAfter(&result->version, (uint32_t) (versionStart - result->version.chars - 1)); + } + } + + return NULL; +} diff --git a/src/detection/editor/editor.h b/src/detection/editor/editor.h new file mode 100644 index 0000000..ae315c0 --- /dev/null +++ b/src/detection/editor/editor.h @@ -0,0 +1,14 @@ +#pragma once + +#include "fastfetch.h" +#include "modules/editor/option.h" + +typedef struct FFEditorResult { + const char* type; + FFstrbuf name; + FFstrbuf exe; + FFstrbuf path; + FFstrbuf version; +} FFEditorResult; + +const char* ffDetectEditor(FFEditorResult* result); |