about summary refs log tree commit diff
path: root/users/Profpatsch
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2022-05-05T19·10+0200
committerProfpatsch <mail@profpatsch.de>2022-05-05T20·18+0000
commit2a6928fb4cde593c530c3dd49cb9f80126c8df42 (patch)
tree04674c2c818f6acbbeb36a30d490fff590d4e98e /users/Profpatsch
parentf0e52f31cd33fd321f71eda0bc1d6cd965b5997c (diff)
feat(users/Profpatsch): init initial aerc config r/4009
aerc is a mail client. It needs some ini files to work.
This is an initial attempt at generating them.

Change-Id: I087955f19d2c4527275500a1e13eeb071c98a7b9
Reviewed-on: https://cl.tvl.fyi/c/depot/+/5526
Tested-by: BuildkiteCI
Reviewed-by: Profpatsch <mail@profpatsch.de>
Diffstat (limited to 'users/Profpatsch')
-rw-r--r--users/Profpatsch/aerc-no-config-perms.patch12
-rw-r--r--users/Profpatsch/aerc.dhall253
-rw-r--r--users/Profpatsch/aerc.nix70
3 files changed, 335 insertions, 0 deletions
diff --git a/users/Profpatsch/aerc-no-config-perms.patch b/users/Profpatsch/aerc-no-config-perms.patch
new file mode 100644
index 0000000000..86b41cd74b
--- /dev/null
+++ b/users/Profpatsch/aerc-no-config-perms.patch
@@ -0,0 +1,12 @@
+diff --git a/config/config.go b/config/config.go
+index 0472daf..5eed379 100644
+--- a/config/config.go
++++ b/config/config.go
+@@ -779,6 +779,7 @@ func (config *AercConfig) LoadBinds(binds *ini.File, baseName string, baseGroup
+ // checkConfigPerms checks for too open permissions
+ // printing the fix on stdout and returning an error
+ func checkConfigPerms(filename string) error {
++        return nil;
+ 	info, err := os.Stat(filename)
+ 	if err != nil {
+ 		return nil // disregard absent files
diff --git a/users/Profpatsch/aerc.dhall b/users/Profpatsch/aerc.dhall
new file mode 100644
index 0000000000..5385a39838
--- /dev/null
+++ b/users/Profpatsch/aerc.dhall
@@ -0,0 +1,253 @@
+let
+    -- DSL for building INI files
+    ToIniFns =
+      λ ( Ini
+        : { -- A Section in the ini
+            Section : Type
+          , -- A couple of sections
+            SectionList : Type
+          }
+        ) →
+        { -- Create a new section
+          newSection : Ini.Section
+        , -- Add a key/value pair to the section
+          add : Text → Text → Ini.Section → Ini.Section
+        , -- Add all these key/value pairs to the section
+          addAll :
+            List { name : Text, value : Text } → Ini.Section → Ini.Section
+        , -- Create a new SectionList
+          newSectionList : Ini.SectionList
+        , -- Add a section to the list of sections
+          addSection : Text → Ini.Section → Ini.SectionList → Ini.SectionList
+        }
+
+in  λ ( imports
+      : { -- concatenate a list with newlines
+          concatNewline : List Text → Text
+        , -- Take an aerc filter from the aerc distribution /share directory
+          aercFilter : Text → Text
+        , -- given a dsl of functions to create an Ini, render the ini file
+          toIni :
+            ( ∀(Ini : { Section : Type, SectionList : Type }) →
+              ToIniFns Ini →
+                { globalSection : Ini.Section, sections : Ini.SectionList }
+            ) →
+              Text
+        }
+      ) →
+      let List/foldLeft
+          : ∀(a : Type) →
+            List a →
+            ∀(list : Type) →
+            ∀(cons : list → a → list) →
+            ∀(nil : list) →
+              list
+          = λ(a : Type) →
+            λ(xs : List a) →
+            λ(list : Type) →
+            λ(cons : list → a → list) →
+            λ(nil : list) →
+              List/fold
+                a
+                xs
+                (list → list)
+                (λ(x : a) → λ(f : list → list) → λ(l : list) → f (cons l x))
+                (λ(l : list) → l)
+                nil
+
+      let List/map
+          : ∀(a : Type) → ∀(b : Type) → (a → b) → List a → List b
+          = λ(a : Type) →
+            λ(b : Type) →
+            λ(f : a → b) →
+            λ(xs : List a) →
+              List/build
+                b
+                ( λ(list : Type) →
+                  λ(cons : b → list → list) →
+                    List/fold a xs list (λ(x : a) → cons (f x))
+                )
+
+      let
+          -- A builder is a list of “build methods” that go from (a -> a) and change the a step by step.
+          Builder/build =
+            λ(a : Type) →
+            λ(init : a) →
+            λ(builders : List (a → a)) →
+              List/foldLeft
+                (a → a)
+                builders
+                a
+                (λ(acc : a) → λ(f : a → a) → f acc)
+                init
+
+      in  { accounts =
+              imports.toIni
+                ( λ(Ini : { Section : Type, SectionList : Type }) →
+                  λ(ini : ToIniFns Ini) →
+                    { globalSection = ini.newSection
+                    , sections =
+                        ini.addSection
+                          "mail"
+                          ( ini.addAll
+                              [ { name = "archive", value = "Archive" }
+                              , { name = "copy-to", value = "Sent" }
+                              , { name = "default", value = "INBOX" }
+                              , { name = "from"
+                                , value = "Profpatsch <mail@profpatsch.de>"
+                                }
+                              , { name = "source"
+                                , value = "maildir://~/.Mail/mail"
+                                }
+                              , { name = "postpone", value = "Drafts" }
+                              ]
+                              ini.newSection
+                          )
+                          ini.newSectionList
+                    }
+                )
+          , aerc =
+              imports.toIni
+                ( λ(Ini : { Section : Type, SectionList : Type }) →
+                  λ(ini : ToIniFns Ini) →
+                    { globalSection = ini.newSection
+                    , sections =
+                        ini.addSection
+                          "filters"
+                          ( Builder/build
+                              Ini.Section
+                              ini.newSection
+                              [ ini.add "text/html" (imports.aercFilter "html")
+                              , let _ =
+                                      "-- TODO: this awk should be taken from nix!"
+
+                                in  ini.add
+                                      "text/*"
+                                      "awk -f ${imports.aercFilter "plaintext"}"
+                              ]
+                          )
+                          ini.newSectionList
+                    }
+                )
+          , binds =
+              let
+                  -- keybinding and command to run
+                  Key =
+                    { ctrl : Bool, key : Text, cmd : Text }
+
+              in  let
+                      -- render a key to config format
+                      renderKey =
+                        λ(k : Key) →
+                          if    k.ctrl
+                          then  "<C-${k.key}> = ${k.cmd}"
+                          else  "${k.key} = ${k.cmd}"
+
+                  let
+
+                      -- render a list of keys to config format
+                      renderKeys =
+                        λ(keys : List Key) → List/map Key Text renderKey keys
+
+                  let
+                      -- create a section whith a name and a list of keys
+                      sect =
+                        λ(section : Text) →
+                        λ(keys : List Key) →
+                          { section, keys = renderKeys keys }
+
+                  let
+
+                      -- set key without modifiers
+                      key =
+                        λ(key : Text) → { key }
+
+                  let
+                      -- set special key without modifiers
+                      special =
+                        λ(key : Text) → { key = "<${key}>" }
+
+                  let
+                      -- no modifier
+                      none =
+                        { ctrl = False }
+
+                  let
+                      -- set control key
+                      ctrl =
+                        { ctrl = True }
+
+                  let
+                      -- set a command to execute
+                      cmd =
+                        λ(cmd : Text) → { cmd = ":${cmd}<Enter>" }
+
+                  let
+                      -- set a command, but stay on the prompt
+                      prompt =
+                        λ(cmd : Text) → { cmd = ":${cmd}<Space>" }
+
+                  let config =
+                        { globalSection =
+                            renderKeys
+                              [ ctrl ∧ key "p" ∧ cmd "prev-tab"
+                              , ctrl ∧ key "n" ∧ cmd "next-tab"
+                              , ctrl ∧ key "t" ∧ cmd "term"
+                              ]
+                        , sections =
+                          [ sect
+                              "messages"
+                              [ ctrl ∧ key "q" ∧ cmd "quit"
+                              , none ∧ special "Up" ∧ cmd "prev"
+                              , none ∧ special "Down" ∧ cmd "next"
+                              , none ∧ special "PgUp" ∧ cmd "prev 100%"
+                              , none ∧ special "PgDn" ∧ cmd "next 100%"
+                              , none ∧ key "g" ∧ cmd "select 0"
+                              , none ∧ key "G" ∧ cmd "select -1"
+                              , ctrl ∧ key "Up" ∧ cmd "prev-folder"
+                              , ctrl ∧ key "Down" ∧ cmd "next-folder"
+                              , none ∧ key "v" ∧ cmd "mark -t"
+                              , none ∧ key "V" ∧ cmd "mark -v"
+                              , none ∧ special "Enter" ∧ cmd "view"
+                              , none ∧ key "c" ∧ cmd "compose"
+                              , none ∧ key "|" ∧ prompt "pipe"
+                              , none ∧ key "t" ∧ prompt "term"
+                              , none ∧ key "/" ∧ prompt "search"
+                              , none ∧ key "n" ∧ cmd "next-result"
+                              , none ∧ key "N" ∧ cmd "prev-result"
+                              , none ∧ special "Esc" ∧ cmd "clear"
+                              ]
+                          , sect "view" [ none ∧ key "q" ∧ cmd "close" ]
+                          ]
+                        }
+
+                  let Section = { section : Text, keys : List Text }
+
+                  let iniToJson =
+                        λ ( ini
+                          : { globalSection : List Text
+                            , sections : List Section
+                            }
+                          ) →
+                          let mkKeys = imports.concatNewline
+
+                          let
+                              -- TODO: escaping section header?
+                              mkSection =
+                                λ(section : Section) →
+                                      ''
+                                      [${section.section}]
+                                      ''
+                                  ++  mkKeys section.keys
+
+                          in      mkKeys ini.globalSection
+                              ++  mkKeys
+                                    ( List/map
+                                        Section
+                                        Text
+                                        mkSection
+                                        ini.sections
+                                    )
+
+                  in  iniToJson config
+          }
diff --git a/users/Profpatsch/aerc.nix b/users/Profpatsch/aerc.nix
new file mode 100644
index 0000000000..d37d10eb46
--- /dev/null
+++ b/users/Profpatsch/aerc.nix
@@ -0,0 +1,70 @@
+{ depot, pkgs, lib, ... }:
+
+let
+  aerc-patched = pkgs.aerc.overrideAttrs (old: {
+    patches = old.patches or [ ] ++ [
+      ./aerc-no-config-perms.patch
+    ];
+  });
+
+  bins = depot.nix.getBins aerc-patched [ "aerc" ];
+
+  config =
+    depot.users.Profpatsch.importDhall.importDhall
+      {
+        root = ./.;
+        files = [
+          "aerc.dhall"
+        ];
+        main = "aerc.dhall";
+        deps = [ ];
+      }
+      {
+        concatNewline = lib.concatStringsSep "\n";
+        aercFilter = name: "${aerc-patched}/share/aerc/filters/${name}";
+        toIni = getSections:
+          lib.generators.toINIWithGlobalSection { }
+            (getSections { } toIniDhall);
+      };
+
+  toIniDhall = {
+    newSection = { };
+    add = key: val: sect: sect // { ${key} = val; };
+    addAll = keyVals: sect: sect // builtins.listToAttrs keyVals;
+    newSectionList = { };
+    addSection = key: val: sect: sect // { ${key} = val; };
+  };
+
+
+  ini-file = name: ini: lib.pipe ini [
+    (lib.generators.toINI { })
+    (pkgs.writeText name)
+  ];
+
+  binds-file = name: binds: pkgs.writeText name binds;
+
+  aerc-config = pkgs.linkFarm "alacritty-config" [
+    {
+      name = "aerc/accounts.conf";
+      path = pkgs.writeText "accounts.conf" config.accounts;
+    }
+    {
+      name = "aerc/aerc.conf";
+      path = pkgs.writeText "aerc.conf" config.aerc;
+    }
+    {
+      name = "aerc/binds.conf";
+      path = binds-file "binds.conf" config.binds;
+    }
+  ];
+
+  aerc = depot.nix.writeExecline "aerc" { } [
+    "export"
+    "XDG_CONFIG_HOME"
+    aerc-config
+    bins.aerc
+    "$@"
+  ];
+
+in
+aerc