Skip to content

Commit 1bb7860

Browse files
docs: add build-plugin.md (WIP)
1 parent 1cc8b90 commit 1bb7860

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

docs/build-plugin.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# How to develop a customfetch plugin (still WIP)
2+
3+
Thanks to the new update since `v2.0.0-beta1`, customfetch is no longer just another neofetch-like program that fetches only system information. But it was made possible to develop and load user-made plugins for fetching any other information the user would like.
4+
5+
Instead of installing different neofetch-like tools for different info fetching, e.g [onefetch](https://github.com/o2sh/onefetch) for viewing git tree infos or [githubfetch](https://github.com/isa-programmer/githubfetch) for viewing a GitHub user infos, you can use one neofetch-like tool (customfetch) and be able to view as many different infos as you would like to.
6+
7+
It's required having a knowledge about C++ programming (basic/mid) for creating a customfetch plugin.
8+
9+
## What are customfetch plugins used for?
10+
11+
Customfetch plugins are used for loading info tag `$<>` external modules, where at parsing it calls the module function automatically. For now, it doesn't let the user modify more the aspect of customfetch generally, but just fetching external infos other than system ones.
12+
13+
## Developing and building the plugin
14+
15+
### Initializing
16+
17+
To make your plugins installable through customfetch's own plugin manager `cufetchpm`, you'll need to first create a git repository and a manifest file called `cufetchpm.toml`.
18+
19+
1. Create a git repository (`git init`)
20+
21+
2. run `cufetchpm gen-manifest` for generating a manifest template with comments explaning each config
22+
23+
After doing that, modify the manifest template with your repository name and url and other changes if needed.
24+
25+
### Developing
26+
27+
Now it's time to actually start developing the plugin. At the moment it's only compatible with C++ API, thus external languages such as C or Rust or Go, cannot create a binding of the libcufetch API.
28+
29+
In this example, we gonna create repository that contains only one plugin, but `cufetchpm` supports installing multiple plugins in the same repository, you can checkout https://github.com/Toni500github/customfetch-plugin-github/ for creating a repository with multiple plguins.
30+
31+
Let's create a simple `test-plugin.cc` source file. We're going to include the required libcufetch headers
32+
33+
```c++
34+
#include <libcufetch/common.hh>
35+
#include <libcufetch/config.hh>
36+
#include <libcufetch/cufetch.hh>
37+
```
38+
39+
<details>
40+
<summary><b>Click to expand for details about each header</b></summary>
41+
42+
* `<libcufetch/common.hh>` will include logging calls `die`, `error`, `warn`, `info` and `debug` (only if customfetch is run with `--debug=1`)
43+
and also macros such as `APICALL`, `EXPORT`, `PLUGIN_INIT` and `PLUGIN_FINISH`, which can be useful for facilitating the plugin development.
44+
* `<libcufetch/config.hh>` will include the `ConfigBase` class which is used for accessing the configs of the config file customfetch uses.
45+
* `<libcufetch/cufetch.hh>` will include the important structs `moduleArgs_t`, `callbackInfo_t`, `module_t` and `cfRegisterModule()` for creating/registering modules that will be called from the config file.
46+
</details>
47+
48+
And let's create our handler callback function:
49+
50+
```c++
51+
std::string test_submod_func(const callbackInfo_t* cb) {
52+
return "Sub module";
53+
}
54+
```
55+
56+
An handler function must return a `std::string` and take in parameters a `const callbackInfo_t*`.
57+
58+
59+
60+
Now the important part starts here. We going to create our plugin main start entry function, which will be called once the plugin got loaded successfully:
61+
62+
```c++
63+
APICALL EXPORT PLUGIN_INIT(void *handle, const ConfigBase& config) {
64+
    
65+
}
66+
```
67+
68+
* `handle` is the plugin (library) main handler from `dlopen()`.
69+
70+
* `config` is the instance of the parsed config file from customfetch, where you can get parsed values of the whole file.
71+
72+
Inside the main start entry (canonically `void start()`) we're going to declare and register all the modules the user can use.
73+
74+
Since it's possible to create recursive modules, we're going to start defining modules from bottom to top
75+
76+
```c++
77+
/* Here we create the 'submod' submodule. in customfetch there's no practical difference between a parent module and a submodule. So we just define it like any other module. */
78+
/* We will not register this, it will be implicitly added through its parent module (so we can't directly invoke `submod`, we can only invoke `root.submod`) */
79+
module_t submod_module = {"submod", "a generic submodule description", {}, test_submod_func};
80+
81+
/* And here we create the 'root' module. This is what we're actually going to register and it will include the 'submod' module as a submodule. */
82+
/* This module doesn't have a handler, so it can't be used in the config (`root` won't work). We'll instead use `root.submod` in the config (which does have a handler). */
83+
module_t root_module = { "root", "root module description", { std::move(submod_module) }, NULL };
84+
85+
/* Register the module. */
86+
/* This will take the root module, recursively add it and its submodules to the list, and continue until its finished everything. */
87+
cfRegisterModule(root_module);
88+
```
89+
90+
### Building
91+
Building a customfetch plugin doesn't require any specific build-system such as cmake or meson, heck you can straight just put `c++ test-plugin.cc -std=c++17 -shared -fPIC -o test-plugin.so -Wl,--export-dynamic -Wl,-undefined,dynamic_lookup` in your plugin table `build-steps` section if it's a super simple Linux/android plugin.

0 commit comments

Comments
 (0)