diff --git a/.github/workflows/make-release.yml b/.github/workflows/make-release.yml index 4f936bf..2c542ca 100644 --- a/.github/workflows/make-release.yml +++ b/.github/workflows/make-release.yml @@ -16,6 +16,8 @@ jobs: packages: "git" version: 1.0 - uses: actions/checkout@v4 + with: + fetch-tags: true - name: Check Version Changed id: check-ver-changed @@ -27,6 +29,7 @@ jobs: echo "ERR: Git tag matches makefile, did you bump Makefile up?" >&2 exit 1 fi + echo "VERSION=$MAKE_TAG" >> "$GITHUB_OUTPUT" @@ -70,7 +73,6 @@ jobs: needs: [ release-checks, release ] steps: - run: pacman -Sy --noconfirm git github-cli base-devel pacman-contrib - - uses: actions/checkout@v4 - run: | @@ -96,3 +98,37 @@ jobs: --body "*This PR was created automatically*" env: GH_TOKEN: ${{ github.token }} + + nix-update: + name: Update NixOS module + runs-on: ubuntu-24.04 + permissions: write-all + needs: [ release-checks, release ] + steps: + - uses: cachix/install-nix-action@v31 + - uses: actions/checkout@v4 + with: + fetch-tags: true + + - run: | + tmpdir=$(mktemp -d) + git archive v${{ needs.release-checks.outputs.VERSION }} | tar -xC "$tmpdir" + sha256sum=$(nix hash path "$tmpdir") + + sed -i -E 's/(.*version\s*=\s*")[0-9.]*(".*)/\1'${{ needs.release-checks.outputs.VERSION }}'\2/' assets/pkg/nix/module.nix + sed -i -E 's/(.*sha256\s*=\s*")[^"]*(".*)/\1'"$sha256sum"'\2/' assets/pkg/nix/module.nix + # would be cool to be able to check the new module.nix builds + + - run: | + BRANCH=actions/update-nix-${{ needs.release-checks.outputs.VERSION }} + git config --global --add safe.directory $GITHUB_WORKSPACE + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + git checkout -b $BRANCH + git commit -am "Update NixOS module to v${{ needs.release-checks.outputs.VERSION }}" + git push -u origin $BRANCH + gh pr create --head $BRANCH \ + --title "[Nix update]: Bump to ${{ needs.release-checks.outputs.VERSION }}" \ + --body "*This PR was created automatically*" + env: + GH_TOKEN: ${{ github.token }} diff --git a/INSTALL.md b/INSTALL.md index 8f2ce27..dcc0de9 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -4,6 +4,7 @@ - [Installing from Source](#installing-from-source) - [AUR](#aur) - [Nix Flake](#nix-flake) +- [Nix Module](#nix-module) > [!CAUTION] > I encourage you to read the manual installation steps to understand what will get installed in your computer by this package. @@ -73,3 +74,57 @@ nix run github:javalsai/lidm > [!CAUTION] > This doesn't include [service files](./assets/pkg/aur#services) neither + +# Nix Module + +
+Sidenote + +The nix module lacks on several aspects, if you know much about nix and know +how to improve this package, feel free to open an issue or a PR to help. The +nix package maintainer position is open too. + +
+ +Lidm includes a nix module in `assets/pkg/nix/module.nix` that you can add +(along the included nix files) and import in your `configuration.nix`. + +Once imported you'll need to add: + +```nix +services.displayManager.enable = true; +systemd.services.lidm.enable = true; +``` + +Optionally, you can configure it setting `services.lidm.config`. You can either +pass: + +* A string to copy the config from a theme in `themes/` with said name + (**name**, e.g `"cherry"`). +* An attribute tree with the same names as the config file, e.g: + +```nix +with config.lidm.keysEnum; { + strings = { + f_poweroff = "custom_poweroff"; + }; + + behavior = { + include_defshell = true; + source = [ + "path1" + "path2" + ]; + }; + + functions = { poweroff = F1; }; + + # etc... +}; +``` + +> *it's not necessary to cover all keys and anything can be put there, even if +> its not valid config* + +> [!NOTE] +> [service files](./assets/pkg/aur#services) **are** included and enabled diff --git a/Makefile b/Makefile index 365760d..77bce10 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,9 @@ PREFIX=/usr CC?=gcc CFLAGS?=-O3 -Wall -ALLFLAGS=$(CFLAGS) -I$(IDIR) +# C PreProcessor flags, not C Plus Plus +CPPFLAGS?= +ALLFLAGS=$(CFLAGS) $(CPPFLAGS) -I$(IDIR) LIBS=-lpam diff --git a/assets/pkg/nix/get-cfg-file.nix b/assets/pkg/nix/get-cfg-file.nix new file mode 100644 index 0000000..06f339e --- /dev/null +++ b/assets/pkg/nix/get-cfg-file.nix @@ -0,0 +1,23 @@ +{ + cfg, + src, + lib, + ... +}: +let + maker = import ./make-cfg.nix { + inherit lib; + keys-h-file = builtins.readFile "${src}/include/keys.h"; + }; +in +{ + inherit maker; + file = builtins.toFile "lidm.conf" ( + if builtins.isString cfg then + builtins.readFile "${src}/themes/${cfg}.ini" + else if builtins.isAttrs cfg then + maker.make cfg + else + builtins.throw "invalid cfg type, expected str or attrs" + ); +} diff --git a/assets/pkg/nix/lidm.nix b/assets/pkg/nix/lidm.nix new file mode 100644 index 0000000..26656fa --- /dev/null +++ b/assets/pkg/nix/lidm.nix @@ -0,0 +1,50 @@ +{ + config, + pkgs, + lib, + ... +}: +let + get-cfg = + if config.cfg != null then + import ./get-cfg-file.nix { + inherit lib; + inherit (config) cfg src; + } + else + null; + cfg-file = get-cfg.file; + maker = get-cfg.maker; +in +pkgs.stdenv.mkDerivation rec { + pname = "lidm"; + version = config.version; + src = config.src; + + nativeBuildInputs = with pkgs; [ + gcc + gnumake + linux-pam + ]; + + makeFlags = + [ + "DESTDIR=$(out)" + "PREFIX=" + ] + ++ lib.optional ( + config.xsessions != null + ) "CPPFLAGS+=-DSESSIONS_XSESSIONS=\\\"${config.xsessions}\\\"" + ++ lib.optional ( + config.wayland-sessions != null + ) "CPPFLAGS+=-DSESSIONS_WAYLAND=\\\"${config.wayland-sessions}\\\"" + ++ lib.optional (cfg-file != null) "CPPFLAGS+=-DLIDM_CONF_PATH=\\\"${cfg-file}\\\""; + + fixupPhase = '' + rm -rf $out/etc + ''; + + passthru = { + keysEnum = maker.keys-enum; + }; +} diff --git a/assets/pkg/nix/make-cfg.nix b/assets/pkg/nix/make-cfg.nix new file mode 100644 index 0000000..8114c71 --- /dev/null +++ b/assets/pkg/nix/make-cfg.nix @@ -0,0 +1,73 @@ +{ lib, keys-h-file }: + +let + double-match-to-nameval = dmatch: { + name = builtins.elemAt dmatch 0; + value = builtins.elemAt dmatch 1; + }; + + keys-enum = + let + key-names = builtins.replaceStrings [ "\n" " " ] [ "" "" ] ( + builtins.elemAt (builtins.match ".*KEY_NAMES\\[][[:blank:]]*=[[:blank:]]*\\{([^}]*)}.*" keys-h-file) 0 + ); + + keys-2d-list = builtins.map (builtins.match "\\[(.*)]=\"(.*)\"") ( + builtins.filter (s: builtins.isString s && s != "") (builtins.split "," key-names) + ); + + in + builtins.listToAttrs ( + builtins.map ( + k: + k + // { + value = { + __enum_key = k.value; + }; + } + ) (builtins.map double-match-to-nameval keys-2d-list) + ); +in +{ + inherit keys-enum; + make = + let + name-val-to-attrs = (name: value: { inherit name value; }); + map-attrs = attrset: fn: lib.map fn (lib.attrsets.mapAttrsToList name-val-to-attrs attrset); + + try-foldl' = + op: nul: list: + if (builtins.length list) == 0 then "" else builtins.foldl' op nul list; + concat-with = sepr: list: try-foldl' (x: y: if x == null then y else x + sepr + y) null list; + + ser-bool = bool: if bool then "true" else "false"; + ser-str = str: "\"${builtins.replaceStrings [ "\n" "\"" ] [ "\\n" "\\\"" ] str}\""; + ser-kvs = + { name, value }: + if builtins.isList value then + concat-with "\n" (builtins.map (value: ser-kvs { inherit name value; }) value) + else + "${name} = ${ + if builtins.isString value then + ser-str value + else if builtins.isInt value then + builtins.toString value + else if builtins.isBool value then + ser-bool value + else if builtins.isAttrs value then + value.__enum_key + else + builtins.throw "type not supported" + }"; + + ser-table = + table': + let + tname = table'.name; + table = table'.value; + in + "[${tname}]\n" + (concat-with "\n" (map-attrs table ser-kvs)); + in + cfg: concat-with "\n\n" (map-attrs cfg ser-table); +} diff --git a/assets/pkg/nix/module.nix b/assets/pkg/nix/module.nix new file mode 100644 index 0000000..362fb02 --- /dev/null +++ b/assets/pkg/nix/module.nix @@ -0,0 +1,73 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.services.lidm; + + dmcfg = config.services.displayManager; + desktops = dmcfg.sessionData.desktops; + + version = "1.2.1"; + lidmPkg = pkgs.callPackage ./lidm.nix { + inherit pkgs; + config = { + inherit version lib; + cfg = cfg.config; + src = pkgs.fetchFromGitHub { + owner = "javalsai"; + repo = "lidm"; + rev = "v${version}"; + sha256 = "sha256-3CgUI8PUs4c1bfBrykPw87SSa4lzrh4E4Hug7cGRKFk="; + }; + + xsessions = "${desktops}/share/xsessions"; + wayland-sessions = "${desktops}/share/wayland-sessions"; + }; + }; +in +{ + options = { + lidm.keysEnum = lib.mkOption { + type = with lib.types; attrs; + default = lidm.passthru.keysEnum; + readOnly = true; + description = "Keys enum constants"; + }; + services.lidm.config = lib.mkOption { + type = + with lib.types; + oneOf [ + str + attrs + ]; + default = { }; + description = "Config options for lidm | Either attr tree or name of bundled themes"; + }; + }; + config = { + services.displayManager.defaultSession = "lidm"; + + systemd.services.lidm = { + description = "TUI display manager"; + aliases = [ "display-manager.service" ]; + after = [ + "systemd-user-sessions.service" + "plymouth-quit-wait.service" + ]; + serviceConfig = { + Type = "idle"; + ExecStart = "${lidmPkg}/bin/lidm 7"; + StandardInput = "tty"; + StandardOutput = "tty"; + StandardError = "tty"; + TTYPath = "/dev/tty7"; + TTYReset = "yes"; + TTYVHangup = "yes"; + }; + }; + }; +} diff --git a/assets/services/systemd.service b/assets/services/systemd.service index 39ef026..c34e89d 100644 --- a/assets/services/systemd.service +++ b/assets/services/systemd.service @@ -5,9 +5,9 @@ After=systemd-user-sessions.service plymouth-quit-wait.service [Service] Type=idle ExecStart=/usr/bin/lidm 7 -StandardError=journal StandardInput=tty StandardOutput=tty +StandardError=tty TTYPath=/dev/tty7 TTYReset=yes TTYVHangup=yes diff --git a/flake.lock b/flake.lock index 5e1e2f1..69ad071 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1724224976, - "narHash": "sha256-Z/ELQhrSd7bMzTO8r7NZgi9g5emh+aRKoCdaAv5fiO0=", + "lastModified": 1751637120, + "narHash": "sha256-xVNy/XopSfIG9c46nRmPaKfH1Gn/56vQ8++xWA8itO4=", "owner": "nixos", "repo": "nixpkgs", - "rev": "c374d94f1536013ca8e92341b540eba4c22f9c62", + "rev": "5c724ed1388e53cc231ed98330a60eb2f7be4be3", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index ecd90a1..2d9a490 100644 --- a/flake.nix +++ b/flake.nix @@ -1,46 +1,46 @@ { + description = "A ✨fully✨ colorful customizable TUI display manager made in C for simplicity."; + inputs = { flake-utils.url = "github:numtide/flake-utils"; nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; }; + outputs = - { flake-utils, nixpkgs, ... }: + { + flake-utils, + nixpkgs, + self, + }: flake-utils.lib.eachDefaultSystem ( system: let pkgs = import nixpkgs { inherit system; }; name = "lidm"; - version = "0.0.2"; - - lidm = ( - pkgs.stdenv.mkDerivation { - pname = name; - version = version; + version = builtins.elemAt (builtins.match "VERSION[[:blank:]]*=[[:space:]]*([^\n]*)\n.*" (builtins.readFile ./Makefile)) 0; + lidm = pkgs.callPackage assets/pkg/nix/lidm.nix { + inherit pkgs; + lib = pkgs.lib; + config = { + inherit version; src = ./.; - - nativeBuildInputs = with pkgs; [ - gcc - gnumake - linux-pam - ]; - - makeFlags = [ - "DESTDIR=$(out)" - "PREFIX=" - ]; - - fixupPhase = '' - rm -rf $out/etc - ''; - } - ); + xsessions = null; + wayland-sessions = null; + cfg = null; + # cfg = "cherry"; + }; + }; in rec { defaultApp = flake-utils.lib.mkApp { drv = defaultPackage; }; defaultPackage = lidm; devShell = pkgs.mkShell { buildInputs = lidm.nativeBuildInputs ++ [ pkgs.clang-tools ]; }; + formatter = nixpkgs.legacyPackages.${system}.nixfmt-tree; } - ); + ) + // { + nixosModules.lidm = assets/pkg/nix/module.nix; + }; } diff --git a/include/macros.h b/include/macros.h index 56f3fb3..9915636 100644 --- a/include/macros.h +++ b/include/macros.h @@ -1,6 +1,11 @@ #ifndef MACROSH_ #define MACROSH_ +// More like constants but I'm not making yet another header file just for this +#ifndef LIDM_CONF_PATH + #define LIDM_CONF_PATH "/etc/lidm.ini" +#endif + // Do we just replace the compiler with clang?? #if defined(__clang__) #define NULLABLE _Nullable diff --git a/src/config.c b/src/config.c index ea71559..fc11b11 100644 --- a/src/config.c +++ b/src/config.c @@ -12,6 +12,7 @@ #include "config.h" #include "desktop.h" #include "log.h" +#include "macros.h" #include "util.h" #define UPPER_HALF_BYTE 4 @@ -240,12 +241,10 @@ struct status config_line_handler(void* _config, char* table, char* k, int parse_config(struct config* NNULLABLE config, char* NNULLABLE path) { FILE* fd = fopen(path, "r"); if (fd == NULL) { - perror("fopen"); - (void)fputs( - "Please place a config file at /etc/lidm.ini or set the LIDM_CONF " - "env variable", - stderr); - return -1; + log_perror("fopen"); + log_printf(" [I] No config, place one at " LIDM_CONF_PATH + " or set the LIDM_CONF env variable"); + return 0; // Its fine now anyways } bool ret = read_desktop(fd, config, config_line_handler); diff --git a/src/desktop.c b/src/desktop.c index 04c96c0..1244d48 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -66,7 +66,8 @@ int read_desktop(FILE* fd, void* ctx, buf_start[eq_idx] = '\0'; // the equal key = trim_str(key); char* value = &buf_start[eq_idx + 1]; - buf_start[read_size - 1] = '\0'; // the newline + if(buf_start[read_size - 1] == '\n') + buf_start[read_size - 1] = '\0'; value = trim_str(value); // Callback diff --git a/src/main.c b/src/main.c index c67072c..4a8aa29 100644 --- a/src/main.c +++ b/src/main.c @@ -72,9 +72,10 @@ int main(int argc, char* argv[]) { chvt_str(argv[1]); } + // Copy struct config config = DEFAULT_CONFIG; char* conf_override = getenv("LIDM_CONF"); - char* conf_path = conf_override ? conf_override : "/etc/lidm.ini"; + char* conf_path = conf_override ? conf_override : LIDM_CONF_PATH; if (parse_config(&config, conf_path) != 0) { (void)fputs("error parsing config\n", stderr); return 1; diff --git a/src/sessions.c b/src/sessions.c index f8f09b3..4d36bc5 100644 --- a/src/sessions.c +++ b/src/sessions.c @@ -16,9 +16,16 @@ struct source_dir { enum session_type type; char* dir; }; + +#ifndef SESSIONS_XSESSIONS + #define SESSIONS_XSESSIONS "/usr/share/xsessions" +#endif +#ifndef SESSIONS_WAYLAND + #define SESSIONS_WAYLAND "/usr/share/wayland-sessions" +#endif static const struct source_dir SOURCES[] = { - {XORG, "/usr/share/xsessions"}, - {WAYLAND, "/usr/share/wayland-sessions"}, + {XORG, SESSIONS_XSESSIONS}, + {WAYLAND, SESSIONS_WAYLAND}, }; static struct Vector* cb_sessions = NULL;