summaryrefslogtreecommitdiffstats
path: root/src/detection/editor
diff options
context:
space:
mode:
Diffstat (limited to 'src/detection/editor')
-rw-r--r--src/detection/editor/editor.c160
-rw-r--r--src/detection/editor/editor.h14
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);