diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2692e0a --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Created by https://www.toptal.com/developers/gitignore/api/go +# Edit at https://www.toptal.com/developers/gitignore?templates=go + +### Go ### +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work + +# End of https://www.toptal.com/developers/gitignore/api/go + +# nix +result +hyprman +nimbledeps +nimble.develop +nimble.paths diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7048b81 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Daylin Morgan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b9d2ffe --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# hyprman diff --git a/config.nims b/config.nims new file mode 100644 index 0000000..fa68af4 --- /dev/null +++ b/config.nims @@ -0,0 +1,8 @@ + +task build, "build": + selfExec "c --outdir:bin src/hyprman.nim" + +# begin Nimble config (version 2) +when withDir(thisDir(), system.fileExists("nimble.paths")): + include "nimble.paths" +# end Nimble config diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..2eba74d --- /dev/null +++ b/flake.lock @@ -0,0 +1,48 @@ +{ + "nodes": { + "nim2nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1725469705, + "narHash": "sha256-4/iSUwB3XKmybdt4R87VhBPiD3z4BL6RrD9LyrrkesM=", + "owner": "daylinmorgan", + "repo": "nim2nix", + "rev": "42af12ca45025c7146bc24e27f5d8b65b003d663", + "type": "github" + }, + "original": { + "owner": "daylinmorgan", + "repo": "nim2nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1727716680, + "narHash": "sha256-uMVkVHL4r3QmlZ1JM+UoJwxqa46cgHnIfqGzVlw5ca4=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "b5b22b42c0d10c7d2463e90a546c394711e3a724", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nim2nix": "nim2nix", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..957bb57 --- /dev/null +++ b/flake.nix @@ -0,0 +1,56 @@ +{ + description = "hyprman"; + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + nim2nix.url = "github:daylinmorgan/nim2nix"; + nim2nix.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = + { + nim2nix, + nixpkgs, + self, + ... + }: + let + inherit (nixpkgs.lib) genAttrs cleanSource; + supportedSystems = [ + "x86_64-linux" + "x86_64-darwin" + "aarch64-linux" + "aarch64-darwin" + ]; + forAllSystems = + f: + genAttrs supportedSystems ( + system: + f ( + import nixpkgs { + inherit system; + overlays = [ nim2nix.overlays.default ]; + } + ) + ); + in + { + devShells = forAllSystems (pkgs: { + default = pkgs.mkShell { + packages = with pkgs; [ + nim + nimble + ]; + }; + }); + packages = forAllSystems (pkgs: { + default = self.packages.${pkgs.system}.hyprman; + hyprman = pkgs.buildNimblePackage { + pname = "hyprman"; + version = "${self.shortRev or "dirty"}"; + src = cleanSource ./.; + nimbleDepsHash = "sha256-EQ3gdxIluE+e3Qzqk9v0Q3mBa6nOKR1C1EWyjwSmQSQ="; + }; + }); + formatter = forAllSystems (pkgs: pkgs.nixfmt-rfc-style); + }; +} diff --git a/hyprman.nimble b/hyprman.nimble new file mode 100644 index 0000000..4c8fe92 --- /dev/null +++ b/hyprman.nimble @@ -0,0 +1,16 @@ +# Package + +version = "0.1.0" +author = "Daylin Morgan" +description = "hyrpman " +license = "MIT" +srcDir = "src" +bin = @["hyprman"] + + +# Dependencies + +requires "nim >= 2.0.8" +requires "cligen" +requires "yaml" +requires "https://github.com/daylinmorgan/hwylterm#HEAD" diff --git a/src/hyprman.nim b/src/hyprman.nim new file mode 100644 index 0000000..85049db --- /dev/null +++ b/src/hyprman.nim @@ -0,0 +1,17 @@ +## hyprman, the hyprland companion + +import ./mako + +when isMainModule: + import hwylterm/cligen, cligen + hwylCli(clCfg) + const + config = //{"config": "path/to/config"} + makoHelp = config // { + "count" : "# of notifications", + "json" : "output as json", + "reverse": "swap notification order" + } + dispatchMulti( + [makoCmd, cmdName = "mako", usage = clCfg.use, help = makoHelp] + ) diff --git a/src/mako.nim b/src/mako.nim new file mode 100644 index 0000000..8bfa545 --- /dev/null +++ b/src/mako.nim @@ -0,0 +1,57 @@ +import std/[algorithm, strutils, json, osproc, wordwrap, terminal] +import hwylterm +type + MakoNotificationData = object + `type`, data: string + MakoNotification = object + `app-name`, summary, body: MakoNotificationData + MakoHistory = object + `type`: string + data: seq[seq[MakoNotification]] + Notification = object + appName, summary, body: string + History = object + notifications: seq[Notification] + +func toNotification(mn: MakoNotification): Notification = + result.appName = mn.`app-name`.data + result.summary = mn.summary.data + result.body = mn.body.data + +func toHistory(mh: MakoHistory): History = + for mn in mh.data[0]: + result.notifications.add mn.toNotification() + + +func filter(h: History, reverse: bool, count: int): History = + result.notifications = h.notifications + if reverse: + result.notifications.reverse() + let high = min(count, h.notifications.len - 1) + result.notifications = + result.notifications[0..high] + +proc getMakoHistory(): MakoHistory = + let (output, errCode) = execCmdEx("makoctl history") + if errCode != 0: quit output, errCode + result = parseJson(output).to(MakoHistory) + + +proc bb(n: Notification): BbString = + template border(style: string): untyped = "[" & style & "]" & "┃ [/]" + var raw: string + raw.add border("magenta") & "[yellow]" & n.appName & "[/]\n" + raw.add border("green") & "[b]" & n.summary & "[/]\n" + for line in n.body.wrapWords(maxLineWidth = terminalWidth()-2).splitLines(): + raw.add border("default") & line & "\n" + result = bb(raw) + +proc makoCmd*(config = "", count = 10, json = false, reverse = false) = + ## interact with mako + let history = getMakoHistory().toHistory().filter(reverse, count) + if json: + echo $(%* history) + else: + for n in history.notifications: + echo $bb(n) + diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..a5c100b --- /dev/null +++ b/todo.md @@ -0,0 +1,6 @@ +# hyprman todo's + +- [ ] include in class the 'other' active monitor? + + +