Skip to content

Commit 743a936

Browse files
committed
DotfileManager: add initial dotfile manager detection
1 parent 50ea515 commit 743a936

File tree

14 files changed

+255
-0
lines changed

14 files changed

+255
-0
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ set(LIBFASTFETCH_SRC
376376
src/detection/disk/disk.c
377377
src/detection/diskio/diskio.c
378378
src/detection/displayserver/displayserver.c
379+
src/detection/dotfilemanager/dotfilemanager.c
379380
src/detection/editor/editor.c
380381
src/detection/font/font.c
381382
src/detection/gpu/gpu.c
@@ -420,6 +421,7 @@ set(LIBFASTFETCH_SRC
420421
src/modules/de/de.c
421422
src/modules/disk/disk.c
422423
src/modules/diskio/diskio.c
424+
src/modules/dotfilemanager/dotfilemanager.c
423425
src/modules/dns/dns.c
424426
src/modules/editor/editor.c
425427
src/modules/font/font.c

doc/json_schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@
190190
"description": "Output format of the module `DiskIO`. See Wiki for formatting syntax\n 1. {size-read}: Size of data read [per second] (formatted)\n 2. {size-written}: Size of data written [per second] (formatted)\n 3. {name}: Device name\n 4. {dev-path}: Device raw file path\n 5. {bytes-read}: Size of data read [per second] (in bytes)\n 6. {bytes-written}: Size of data written [per second] (in bytes)\n 7. {read-count}: Number of reads\n 8. {write-count}: Number of writes",
191191
"type": "string"
192192
},
193+
"dotfileManagerFormat": {
194+
"description": "Output format of the module `DotfileManager`. See Wiki for formatting syntax\n 1. {name}: Name",
195+
"type": "string"
196+
},
193197
"dnsFormat": {
194198
"description": "Output format of the module `DNS`. See Wiki for formatting syntax\n 1. {result}: DNS result",
195199
"type": "string"
@@ -978,6 +982,7 @@
978982
"disk",
979983
"diskio",
980984
"de",
985+
"dotfileManager",
981986
"dns",
982987
"editor",
983988
"font",

presets/all.jsonc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"processes",
2222
"packages",
2323
"shell",
24+
"dotfileManager",
2425
"editor",
2526
"display",
2627
"brightness",

src/common/modules.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ static FFModuleBaseInfo* D[] = {
3636
(FFModuleBaseInfo*) &instance.config.modules.display,
3737
(FFModuleBaseInfo*) &instance.config.modules.disk,
3838
(FFModuleBaseInfo*) &instance.config.modules.diskIo,
39+
(FFModuleBaseInfo*) &instance.config.modules.dotfileManager,
3940
(FFModuleBaseInfo*) &instance.config.modules.dns,
4041
NULL,
4142
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Dotfile Manager
2+
3+
This module attempts to detect the user's dotfile manager. Many [popular dotfile
4+
managers](https://dotfiles.github.io/utilities/) are supported.
5+
6+
## Supported dotfile managers
7+
8+
* [Bare git repository](https://www.atlassian.com/git/tutorials/dotfiles)
9+
* [chezmoi](https://chezmoi.io)
10+
* [YADM](https://yadm.io)
11+
12+
## Unsupported dotfile managers
13+
14+
### Dotbot
15+
16+
As [Dotbot](https://github.com/anishathalye/dotbot) is usually imported as a
17+
submodule inside the user's dotfile repository, there is no reliable way to
18+
detect if the user is using it.
19+
20+
### GNU Stow
21+
22+
[GNU Stow](https://www.gnu.org/software/stow/) has no standard configuration, so
23+
there is no reliable way to detect if the user is using it.
24+
25+
### Home manager
26+
27+
[Home manager](https://github.com/nix-community/home-manager) has no standard
28+
configuration.
29+
30+
### Mackup
31+
32+
[Mackup](https://github.com/lra/mackup) does not work on macOS since version 14
33+
(Sonoma, released September 2023).
34+
35+
### rcm
36+
37+
[rcm](https://thoughtbot.github.io/rcm/rcm.7.html) has no standard
38+
configuration.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include "common/io/io.h"
2+
#include "dotfilemanager.h"
3+
4+
static bool detectBareGitRepository(FFDotfileManagerResult* result)
5+
{
6+
FF_STRBUF_AUTO_DESTROY fullPath = ffStrbufCreate();
7+
ffStrbufSet(&fullPath, &instance.state.platform.homeDir);
8+
ffStrbufAppendS(&fullPath, ".git");
9+
10+
if (ffPathExists(fullPath.chars, FF_PATHTYPE_DIRECTORY)) {
11+
ffStrbufSetS(&result->name, "bare git repository");
12+
return true;
13+
}
14+
15+
return false;
16+
}
17+
18+
static bool detectChezmoi(FFDotfileManagerResult* result)
19+
{
20+
FF_LIST_FOR_EACH(FFstrbuf, dataDir, instance.state.platform.dataDirs)
21+
{
22+
FF_STRBUF_AUTO_DESTROY fullPath = ffStrbufCreate();
23+
ffStrbufSet(&fullPath, dataDir);
24+
ffStrbufAppendS(&fullPath, "chezmoi");
25+
26+
if (ffPathExists(fullPath.chars, FF_PATHTYPE_DIRECTORY)) {
27+
ffStrbufSetS(&result->name, "chezmoi");
28+
return true;
29+
}
30+
}
31+
32+
return false;
33+
}
34+
35+
static bool detectYADM(FFDotfileManagerResult* result)
36+
{
37+
FF_LIST_FOR_EACH(FFstrbuf, configDir, instance.state.platform.configDirs)
38+
{
39+
FF_STRBUF_AUTO_DESTROY fullPath = ffStrbufCreate();
40+
ffStrbufSet(&fullPath, configDir);
41+
ffStrbufAppendS(&fullPath, "yadm");
42+
43+
if (ffPathExists(fullPath.chars, FF_PATHTYPE_DIRECTORY)) {
44+
ffStrbufSetS(&result->name, "yadm");
45+
return true;
46+
}
47+
}
48+
49+
return false;
50+
}
51+
52+
const char* ffDetectDotfileManager(FFDotfileManagerResult* result)
53+
{
54+
if (detectBareGitRepository(result)) return NULL;
55+
if (detectChezmoi(result)) return NULL;
56+
if (detectYADM(result)) return NULL;
57+
58+
return NULL;
59+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma once
2+
3+
#include "fastfetch.h"
4+
5+
typedef struct FFDotfileManagerResult
6+
{
7+
FFstrbuf name;
8+
} FFDotfileManagerResult;
9+
10+
const char* ffDetectDotfileManager(FFDotfileManagerResult* result);
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#include "common/printing.h"
2+
#include "common/jsonconfig.h"
3+
#include "detection/libc/libc.h"
4+
#include "detection/dotfilemanager/dotfilemanager.h"
5+
#include "modules/dotfilemanager/dotfilemanager.h"
6+
#include "util/stringUtils.h"
7+
8+
void ffPrintDotfileManager(FFDotfileManagerOptions* options)
9+
{
10+
FFDotfileManagerResult result = {
11+
.name = ffStrbufCreate(),
12+
};
13+
const char* error = ffDetectDotfileManager(&result);
14+
15+
if (error)
16+
{
17+
ffPrintError(FF_DOTFILEMANAGER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
18+
return;
19+
}
20+
21+
if (options->moduleArgs.outputFormat.length == 0)
22+
{
23+
ffPrintLogoAndKey(FF_DOTFILEMANAGER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
24+
ffStrbufWriteTo(&result.name, stdout);
25+
putchar('\n');
26+
}
27+
else
28+
{
29+
FF_PRINT_FORMAT_CHECKED(FF_DOTFILEMANAGER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){
30+
FF_FORMAT_ARG(result.name, "name"),
31+
}));
32+
}
33+
34+
ffStrbufDestroy(&result.name);
35+
}
36+
37+
bool ffParseDotfileManagerCommandOptions(FFDotfileManagerOptions* options, const char* key, const char* value)
38+
{
39+
const char* subKey = ffOptionTestPrefix(key, FF_DOTFILEMANAGER_MODULE_NAME);
40+
if (!subKey) return false;
41+
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
42+
return true;
43+
44+
return false;
45+
}
46+
47+
void ffParseDotfileManagerJsonObject(FFDotfileManagerOptions* options, yyjson_val* module)
48+
{
49+
yyjson_val *key_, *val;
50+
size_t idx, max;
51+
yyjson_obj_foreach(module, idx, max, key_, val)
52+
{
53+
const char* key = yyjson_get_str(key_);
54+
if(ffStrEqualsIgnCase(key, "type"))
55+
continue;
56+
57+
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
58+
continue;
59+
60+
ffPrintError(FF_DOTFILEMANAGER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key);
61+
}
62+
}
63+
64+
void ffGenerateDotfileManagerJsonConfig(FFDotfileManagerOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
65+
{
66+
__attribute__((__cleanup__(ffDestroyDotfileManagerOptions))) FFDotfileManagerOptions defaultOptions;
67+
ffInitDotfileManagerOptions(&defaultOptions);
68+
69+
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
70+
}
71+
72+
void ffGenerateDotfileManagerJsonResult(FF_MAYBE_UNUSED FFDotfileManagerOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
73+
{
74+
FFDotfileManagerResult result = {
75+
.name = ffStrbufCreate(),
76+
};
77+
78+
const char* error = ffDetectDotfileManager(&result);
79+
80+
if (error)
81+
{
82+
yyjson_mut_obj_add_str(doc, module, "error", error);
83+
return;
84+
}
85+
86+
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
87+
yyjson_mut_obj_add_strbuf(doc, obj, "name", &result.name);
88+
89+
ffStrbufDestroy(&result.name);
90+
}
91+
92+
static FFModuleBaseInfo ffModuleInfo = {
93+
.name = FF_DOTFILEMANAGER_MODULE_NAME,
94+
.description = "Print information about the dotfile manager",
95+
.parseCommandOptions = (void*) ffParseDotfileManagerCommandOptions,
96+
.parseJsonObject = (void*) ffParseDotfileManagerJsonObject,
97+
.printModule = (void*) ffPrintDotfileManager,
98+
.generateJsonResult = (void*) ffGenerateDotfileManagerJsonResult,
99+
.generateJsonConfig = (void*) ffGenerateDotfileManagerJsonConfig,
100+
.formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
101+
{"Name", "name"},
102+
}))
103+
};
104+
105+
void ffInitDotfileManagerOptions(FFDotfileManagerOptions* options)
106+
{
107+
options->moduleInfo = ffModuleInfo;
108+
ffOptionInitModuleArg(&options->moduleArgs, "󰣫");
109+
}
110+
111+
void ffDestroyDotfileManagerOptions(FFDotfileManagerOptions* options)
112+
{
113+
ffOptionDestroyModuleArg(&options->moduleArgs);
114+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
#include "fastfetch.h"
4+
5+
#define FF_DOTFILEMANAGER_MODULE_NAME "DotfileManager"
6+
7+
void ffPrintDotfileManager(FFDotfileManagerOptions* options);
8+
void ffInitDotfileManagerOptions(FFDotfileManagerOptions* options);
9+
void ffDestroyDotfileManagerOptions(FFDotfileManagerOptions* options);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
3+
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
4+
5+
#include "common/option.h"
6+
7+
typedef struct FFDotfileManagerOptions
8+
{
9+
FFModuleBaseInfo moduleInfo;
10+
FFModuleArgs moduleArgs;
11+
} FFDotfileManagerOptions;

0 commit comments

Comments
 (0)