summaryrefslogtreecommitdiffstats
path: root/pkgs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2023-09-11 18:24:28 +0200
committertv <tv@krebsco.de>2023-09-13 18:07:11 +0200
commit0c4f3acb281be6290c55a6e96bc29fab5b5c7a11 (patch)
treedadaec00477a095273475ac345b2066b4748c399 /pkgs
parentab1d0479e90f11806d4703ec6fffed3d5f782914 (diff)
stockholm -> hrm
Diffstat (limited to 'pkgs')
-rw-r--r--pkgs/compat/default.nix1
-rw-r--r--pkgs/default.nix24
-rw-r--r--pkgs/haskell/default.nix31
-rw-r--r--pkgs/haskell/th-env/default.nix10
-rw-r--r--pkgs/haskell/th-env/src/THEnv.hs49
-rw-r--r--pkgs/haskell/th-env/th-env.cabal20
-rw-r--r--pkgs/haskell/xmonad-tv/default.nix16
-rw-r--r--pkgs/haskell/xmonad-tv/shell.nix83
-rw-r--r--pkgs/haskell/xmonad-tv/src/Shutdown.hs113
-rw-r--r--pkgs/haskell/xmonad-tv/src/XMonad/Extra.hs14
-rw-r--r--pkgs/haskell/xmonad-tv/src/XMonad/Hooks/EwmhDesktops/Extra.hs117
-rw-r--r--pkgs/haskell/xmonad-tv/src/main.hs227
-rw-r--r--pkgs/haskell/xmonad-tv/src/xmonad-tv.cabal29
-rw-r--r--pkgs/override/alacritty.nix16
-rw-r--r--pkgs/override/anbox.nix72
-rw-r--r--pkgs/override/default.nix11
-rw-r--r--pkgs/override/fzf/complete1.patch77
-rw-r--r--pkgs/override/fzf/default.nix7
-rw-r--r--pkgs/override/gitAndTools.nix5
-rw-r--r--pkgs/override/input-fonts.nix13
-rw-r--r--pkgs/override/iosevka-tv-1.nix20
-rw-r--r--pkgs/override/iosevka-tv-2.nix20
-rw-r--r--pkgs/override/jc.nix21
-rw-r--r--pkgs/override/uqmi.nix10
-rw-r--r--pkgs/rpi/433Utils/RPi_utils.codesend.codestring.patch24
-rw-r--r--pkgs/rpi/433Utils/default.nix42
-rw-r--r--pkgs/rpi/433Utils/rc-switch.protocols.patch10
-rw-r--r--pkgs/rpi/433Utils/src.json7
-rw-r--r--pkgs/rpi/WiringPi/default.nix61
-rw-r--r--pkgs/rpi/WiringPi/src.json6
-rw-r--r--pkgs/rpi/default.nix11
-rw-r--r--pkgs/simple/alacritty-tv.nix155
-rw-r--r--pkgs/simple/bash-fzf-history.nix107
-rw-r--r--pkgs/simple/cr.nix16
-rw-r--r--pkgs/simple/default.nix22
-rw-r--r--pkgs/simple/diff-so-fancy.nix50
-rw-r--r--pkgs/simple/disko.nix13
-rw-r--r--pkgs/simple/editor-input.nix18
-rw-r--r--pkgs/simple/ff.nix8
-rw-r--r--pkgs/simple/field.nix6
-rw-r--r--pkgs/simple/flameshot-once-tv.nix48
-rw-r--r--pkgs/simple/font-size-alacritty.nix67
-rwxr-xr-xpkgs/simple/fzmenu/bin/otpmenu44
-rwxr-xr-xpkgs/simple/fzmenu/bin/passmenu45
-rw-r--r--pkgs/simple/fzmenu/default.nix50
-rw-r--r--pkgs/simple/hc.nix39
-rw-r--r--pkgs/simple/iosevka-tv-1.nix18
-rw-r--r--pkgs/simple/iosevka-tv-2.nix20
-rw-r--r--pkgs/simple/libinput-tv.nix11
-rw-r--r--pkgs/simple/mpvterm/default.nix8
-rw-r--r--pkgs/simple/mpvterm/mpvterm.patch146
-rw-r--r--pkgs/simple/pinentry-urxvt/default.nix127
-rw-r--r--pkgs/simple/q/default.nix176
-rw-r--r--pkgs/simple/rox-filer.nix95
-rw-r--r--pkgs/simple/rxvt-unicode-256color-terminfo/default.nix16
-rw-r--r--pkgs/simple/rxvt-unicode-256color-terminfo/rxvt-unicode-256color.terminfobin0 -> 2239 bytes
-rw-r--r--pkgs/simple/stardict/default.nix235
-rw-r--r--pkgs/simple/viljetic-pages/default.nix17
-rw-r--r--pkgs/simple/viljetic-pages/index.html11
-rw-r--r--pkgs/simple/viljetic-pages/logo.xpm24
-rw-r--r--pkgs/simple/weechat-tv.nix9
-rw-r--r--pkgs/simple/xdpytools/default.nix31
-rwxr-xr-xpkgs/simple/xdpytools/src/xdpychvt11
-rwxr-xr-xpkgs/simple/xdpytools/src/xdpysel49
-rw-r--r--pkgs/simple/xkiller.nix25
-rw-r--r--pkgs/simple/xtoggledpms.nix16
-rw-r--r--pkgs/vim/default.nix15
-rw-r--r--pkgs/vim/elixir.nix9
-rw-r--r--pkgs/vim/file-line.nix10
-rw-r--r--pkgs/vim/fzf.nix11
-rw-r--r--pkgs/vim/hack.nix48
-rw-r--r--pkgs/vim/jq.nix10
-rw-r--r--pkgs/vim/nix.nix224
-rw-r--r--pkgs/vim/showsyntax.nix26
-rw-r--r--pkgs/vim/tv.nix42
-rw-r--r--pkgs/vim/vim.nix21
76 files changed, 3316 insertions, 0 deletions
diff --git a/pkgs/compat/default.nix b/pkgs/compat/default.nix
new file mode 100644
index 0000000..0d1e61b
--- /dev/null
+++ b/pkgs/compat/default.nix
@@ -0,0 +1 @@
+self: super: {}
diff --git a/pkgs/default.nix b/pkgs/default.nix
new file mode 100644
index 0000000..41e17c8
--- /dev/null
+++ b/pkgs/default.nix
@@ -0,0 +1,24 @@
+self: super:
+
+let
+ inherit (super) lib;
+
+ mylib = import ../lib/pure.nix {
+ inherit lib;
+ };
+
+ pushBack = x: xs:
+ if builtins.elem x xs then
+ lib.remove x xs ++ [ x ]
+ else
+ xs;
+in
+
+# Import files and subdirectories like they are overlays.
+lib.fix
+ (builtins.foldl' (lib.flip lib.extends) (_: super)
+ (map
+ (name: import (./. + "/${name}"))
+ (pushBack "override"
+ (builtins.attrNames
+ (lib.filterAttrs mylib.isNixDirEntry (builtins.readDir ./.))))))
diff --git a/pkgs/haskell/default.nix b/pkgs/haskell/default.nix
new file mode 100644
index 0000000..7baaa89
--- /dev/null
+++ b/pkgs/haskell/default.nix
@@ -0,0 +1,31 @@
+let
+ overrides = { lib, mylib }: self: super:
+ mylib.mapNixDir (path: self.callPackage path {}) [
+ ./.
+ ] // {
+ xmonad-tv = self.callPackage ./xmonad-tv {
+ pager = self.desktop-pager;
+ };
+ };
+in
+ self: super: let
+ inherit (super) lib;
+ mylib = import ../../lib/pure.nix {
+ inherit lib;
+ };
+ in {
+ haskell = super.haskell // {
+ packages = lib.mapAttrs (name: value:
+ if builtins.hasAttr "override" value
+ then value.override (old: {
+ overrides =
+ lib.composeExtensions (old.overrides or (_: _: { })) (overrides { inherit lib mylib; });
+ })
+ else value
+ ) super.haskell.packages;
+ };
+ haskellPackages = super.haskellPackages.override (old: {
+ overrides =
+ lib.composeExtensions (old.overrides or (_: _: { })) (overrides { inherit lib mylib; });
+ });
+ }
diff --git a/pkgs/haskell/th-env/default.nix b/pkgs/haskell/th-env/default.nix
new file mode 100644
index 0000000..158fb16
--- /dev/null
+++ b/pkgs/haskell/th-env/default.nix
@@ -0,0 +1,10 @@
+{ mkDerivation, base, lib, template-haskell, text }:
+mkDerivation {
+ pname = "th-env";
+ version = "1.0.0";
+ src = ./.;
+ libraryHaskellDepends = [ base template-haskell text ];
+ homepage = "https://stackoverflow.com/q/57635686";
+ license = "unknown";
+ hydraPlatforms = lib.platforms.none;
+}
diff --git a/pkgs/haskell/th-env/src/THEnv.hs b/pkgs/haskell/th-env/src/THEnv.hs
new file mode 100644
index 0000000..b04f2ce
--- /dev/null
+++ b/pkgs/haskell/th-env/src/THEnv.hs
@@ -0,0 +1,49 @@
+{-# LANGUAGE TemplateHaskell #-}
+module THEnv
+ (
+ -- * Compile-time configuration
+ lookupCompileEnv
+ , lookupCompileEnvExp
+ , getCompileEnv
+ , getCompileEnvExp
+ , fileAsString
+ ) where
+
+import Control.Monad
+import qualified Data.Text as T
+import qualified Data.Text.IO as T
+import Language.Haskell.TH
+import Language.Haskell.TH.Syntax (Lift(..))
+import System.Environment (getEnvironment)
+
+-- Functions that work with compile-time configuration
+
+-- | Looks up a compile-time environment variable.
+lookupCompileEnv :: String -> Q (Maybe String)
+lookupCompileEnv key = lookup key `liftM` runIO getEnvironment
+
+-- | Looks up a compile-time environment variable. The result is a TH
+-- expression of type @Maybe String@.
+lookupCompileEnvExp :: String -> Q Exp
+lookupCompileEnvExp = (`sigE` [t| Maybe String |]) . lift <=< lookupCompileEnv
+ -- We need to explicly type the result so that things like `print Nothing`
+ -- work.
+
+-- | Looks up an compile-time environment variable and fail, if it's not
+-- present.
+getCompileEnv :: String -> Q String
+getCompileEnv key =
+ lookupCompileEnv key >>=
+ maybe (fail $ "Environment variable " ++ key ++ " not defined") return
+
+-- | Looks up an compile-time environment variable and fail, if it's not
+-- present. The result is a TH expression of type @String@.
+getCompileEnvExp :: String -> Q Exp
+getCompileEnvExp = lift <=< getCompileEnv
+
+-- | Loads the content of a file as a string constant expression.
+-- The given path is relative to the source directory.
+fileAsString :: FilePath -> Q Exp
+fileAsString = do
+ -- addDependentFile path -- works only with template-haskell >= 2.7
+ stringE . T.unpack . T.strip <=< runIO . T.readFile
diff --git a/pkgs/haskell/th-env/th-env.cabal b/pkgs/haskell/th-env/th-env.cabal
new file mode 100644
index 0000000..b9a2cff
--- /dev/null
+++ b/pkgs/haskell/th-env/th-env.cabal
@@ -0,0 +1,20 @@
+name: th-env
+version: 1.0.0
+-- license: https://creativecommons.org/licenses/by-sa/4.0/
+license: OtherLicense
+author: https://stackoverflow.com/users/9348482
+homepage: https://stackoverflow.com/q/57635686
+maintainer: tv <tv@krebsco.de>
+build-type: Simple
+cabal-version: >=1.10
+
+library
+ hs-source-dirs: src
+ build-depends:
+ base,
+ template-haskell,
+ text
+ exposed-modules:
+ THEnv
+ default-language: Haskell2010
+ ghc-options: -O2 -Wall
diff --git a/pkgs/haskell/xmonad-tv/default.nix b/pkgs/haskell/xmonad-tv/default.nix
new file mode 100644
index 0000000..f42f97c
--- /dev/null
+++ b/pkgs/haskell/xmonad-tv/default.nix
@@ -0,0 +1,16 @@
+{ mkDerivation, aeson, base, bytestring, containers, directory
+, extra, filepath, lib, pager, unix, X11, xmonad, xmonad-contrib
+}:
+mkDerivation {
+ pname = "xmonad-tv";
+ version = "1.0.0";
+ src = ./src;
+ isLibrary = false;
+ isExecutable = true;
+ executableHaskellDepends = [
+ aeson base bytestring containers directory extra filepath pager
+ unix X11 xmonad xmonad-contrib
+ ];
+ license = lib.licenses.mit;
+ mainProgram = "xmonad";
+}
diff --git a/pkgs/haskell/xmonad-tv/shell.nix b/pkgs/haskell/xmonad-tv/shell.nix
new file mode 100644
index 0000000..6ca00bc
--- /dev/null
+++ b/pkgs/haskell/xmonad-tv/shell.nix
@@ -0,0 +1,83 @@
+{ compiler ? "default" }: let
+
+ stockholm = import <stockholm>;
+
+ inherit (stockholm.systems.${lib.krops.getHostName}) config pkgs;
+ inherit (stockholm) lib;
+
+ haskellPackages =
+ if compiler == "default"
+ then pkgs.haskellPackages
+ else pkgs.haskell.packages.${compiler};
+
+ xmonadDrv = haskellPackages.callPackage (import ./.) {};
+
+in
+
+ lib.overrideDerivation xmonadDrv.env (oldAttrs: {
+ shellHook = ''
+ pkg_name=${lib.shell.escape (lib.baseNameOf (toString ./.))}
+
+ WORKDIR=${toString ./src}
+ CACHEDIR=$HOME/tmp/$pkg_name
+ HISTFILE=$CACHEDIR/bash_history
+
+ mkdir -p "$CACHEDIR"
+
+ config_XMONAD_CACHE_DIR=${lib.shell.escape
+ config.systemd.services.xmonad.environment.XMONAD_CACHE_DIR
+ }
+
+ xmonad=$CACHEDIR/xmonad-${lib.currentSystem}
+
+ xmonad_build() {(
+ set -efu
+ cd "$WORKDIR"
+ options=$(
+ ${pkgs.cabal-read}/bin/ghc-options "$WORKDIR/$pkg_name.cabal" xmonad
+ )
+ ghc $options \
+ -odir "$CACHEDIR" \
+ -hidir "$CACHEDIR" \
+ -o "$xmonad" \
+ main.hs
+ )}
+
+ xmonad_restart() {(
+ set -efu
+ cd "$WORKDIR"
+ if systemctl --quiet is-active xmonad; then
+ sudo systemctl stop xmonad
+ cp -b "$config_XMONAD_CACHE_DIR"/xmonad.state "$CACHEDIR"/
+ echo "xmonad.state: $(cat "$CACHEDIR"/xmonad.state)"
+ else
+ "$xmonad" --shutdown || :
+ fi
+ "$xmonad" &
+ echo xmonad pid: $! >&2
+ )}
+
+ xmonad_yield() {(
+ set -efu
+ if ! systemctl --quiet is-active xmonad; then
+ "$xmonad" --shutdown
+ cp -b "$CACHEDIR"/xmonad.state "$config_XMONAD_CACHE_DIR"/
+ sudo systemctl start xmonad
+ else
+ echo "xmonad.service is already running" >&2
+ exit -1
+ fi
+ )}
+
+ export PATH=${config.systemd.services.xmonad.path}:$PATH
+ export SHELL=/run/current-system/sw/bin/bash
+
+ export XMONAD_CACHE_DIR="$CACHEDIR"
+ export XMONAD_DATA_DIR="$CACHEDIR"
+ export XMONAD_CONFIG_DIR=/var/empty
+
+ unset XMONAD_STARTUP_HOOK
+
+ cd "$WORKDIR"
+ '';
+ })
diff --git a/pkgs/haskell/xmonad-tv/src/Shutdown.hs b/pkgs/haskell/xmonad-tv/src/Shutdown.hs
new file mode 100644
index 0000000..d4a4d93
--- /dev/null
+++ b/pkgs/haskell/xmonad-tv/src/Shutdown.hs
@@ -0,0 +1,113 @@
+{-# LANGUAGE LambdaCase #-}
+
+module Shutdown
+ ( newShutdownEventHandler
+ , shutdown
+ )
+ where
+
+import Control.Applicative ((<|>), empty)
+import Control.Concurrent (threadDelay)
+import Control.Monad (forever, guard, when)
+import Data.Monoid (All(All))
+import System.Directory (XdgDirectory(XdgData), createDirectoryIfMissing, doesFileExist, getAppUserDataDirectory, getXdgDirectory)
+import System.Exit (exitSuccess)
+import System.Environment (lookupEnv)
+import System.FilePath ((</>))
+import System.IO.Error (isDoesNotExistError, tryIOError)
+import System.IO (hPutStrLn, stderr)
+import System.Posix.Process (getProcessID)
+import System.Posix.Signals (nullSignal, signalProcess)
+import System.Posix.Types (ProcessID)
+import XMonad hiding (getXMonadDataDir)
+
+
+-- XXX this is for compatibility with both xmonad<0.17 and xmonad>=0.17
+getXMonadDataDir :: IO String
+getXMonadDataDir = xmEnvDir <|> xmDir <|> xdgDir
+ where
+ -- | Check for xmonad's environment variables first
+ xmEnvDir :: IO String
+ xmEnvDir =
+ maybe empty pure =<< lookupEnv "XMONAD_DATA_DIR"
+
+ -- | Check whether the config file or a build script is in the
+ -- @~\/.xmonad@ directory
+ xmDir :: IO String
+ xmDir = do
+ d <- getAppUserDataDirectory "xmonad"
+ conf <- doesFileExist $ d </> "xmonad.hs"
+ build <- doesFileExist $ d </> "build"
+ pid <- doesFileExist $ d </> "xmonad.pid"
+
+ -- Place *everything* in ~/.xmonad if yes
+ guard $ conf || build || pid
+ pure d
+
+ -- | Use XDG directories as a fallback
+ xdgDir :: IO String
+ xdgDir = do
+ d <- getXdgDirectory XdgData "xmonad"
+ d <$ createDirectoryIfMissing True d
+
+
+newShutdownEventHandler :: IO (Event -> X All)
+newShutdownEventHandler = do
+ writeProcessIDToFile
+ return handleShutdownEvent
+
+handleShutdownEvent :: Event -> X All
+handleShutdownEvent = \case
+ ClientMessageEvent { ev_message_type = mt } -> do
+ isShutdownEvent <- (mt ==) <$> getAtom "XMONAD_SHUTDOWN"
+ when isShutdownEvent $ do
+ broadcastMessage ReleaseResources
+ writeStateToFile
+ io exitSuccess >> return ()
+ return (All (not isShutdownEvent))
+ _ ->
+ return (All True)
+
+sendShutdownEvent :: IO ()
+sendShutdownEvent = do
+ dpy <- openDisplay ""
+ rw <- rootWindow dpy $ defaultScreen dpy
+ a <- internAtom dpy "XMONAD_SHUTDOWN" False
+ allocaXEvent $ \e -> do
+ setEventType e clientMessage
+ setClientMessageEvent e rw a 32 0 currentTime
+ sendEvent dpy rw False structureNotifyMask e
+ sync dpy False
+
+shutdown :: IO ()
+shutdown = do
+ pid <- readProcessIDFromFile
+ sendShutdownEvent
+ hPutStrLn stderr ("waiting for: " <> show pid)
+ result <- tryIOError (waitProcess pid)
+ if isSuccess result
+ then hPutStrLn stderr ("result: " <> show result <> " [AKA success^_^]")
+ else hPutStrLn stderr ("result: " <> show result)
+ where
+ isSuccess = either isDoesNotExistError (const False)
+
+waitProcess :: ProcessID -> IO ()
+waitProcess pid = forever (signalProcess nullSignal pid >> threadDelay 10000)
+
+--
+-- PID file stuff
+--
+
+getProcessIDFileName :: IO FilePath
+getProcessIDFileName = (</> "xmonad.pid") <$> getXMonadDataDir
+
+writeProcessIDToFile :: IO ()
+writeProcessIDToFile = do
+ pidFileName <- getProcessIDFileName
+ pid <- getProcessID
+ writeFile pidFileName (show pid)
+
+readProcessIDFromFile :: IO ProcessID
+readProcessIDFromFile = do
+ pidFileName <- getProcessIDFileName
+ read <$> readFile pidFileName
diff --git a/pkgs/haskell/xmonad-tv/src/XMonad/Extra.hs b/pkgs/haskell/xmonad-tv/src/XMonad/Extra.hs
new file mode 100644
index 0000000..7422271
--- /dev/null
+++ b/pkgs/haskell/xmonad-tv/src/XMonad/Extra.hs
@@ -0,0 +1,14 @@
+module XMonad.Extra where
+
+import XMonad
+import qualified Data.Map as Map
+import qualified XMonad.StackSet as W
+
+
+isFloating :: Window -> WindowSet -> Bool
+isFloating w =
+ Map.member w . W.floating
+
+isFloatingX :: Window -> X Bool
+isFloatingX w =
+ isFloating w <$> gets windowset
diff --git a/pkgs/haskell/xmonad-tv/src/XMonad/Hooks/EwmhDesktops/Extra.hs b/pkgs/haskell/xmonad-tv/src/XMonad/Hooks/EwmhDesktops/Extra.hs
new file mode 100644
index 0000000..bf84314
--- /dev/null
+++ b/pkgs/haskell/xmonad-tv/src/XMonad/Hooks/EwmhDesktops/Extra.hs
@@ -0,0 +1,117 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE NamedFieldPuns #-}
+
+module XMonad.Hooks.EwmhDesktops.Extra where
+
+import Control.Monad (when)
+import Data.Maybe (fromMaybe)
+import Data.Monoid (All)
+import Data.Tuple.Extra (both)
+import Graphics.X11.EWMH (getDesktopNames, setDesktopNames)
+import Graphics.X11.EWMH.Atom (_NET_DESKTOP_NAMES)
+import Graphics.X11.Xlib.Display.Extra (withDefaultDisplay)
+import XMonad hiding (workspaces)
+import XMonad.Actions.DynamicWorkspaces (addHiddenWorkspace, removeEmptyWorkspaceByTag)
+import XMonad.StackSet (mapWorkspace, tag, workspaces)
+import XMonad.Util.WorkspaceCompare (getSortByIndex)
+import qualified Data.Map.Strict as Map
+import qualified Data.Set as Set
+import qualified XMonad
+
+
+ewmhExtra :: XConfig a -> IO (XConfig a)
+ewmhExtra c = do
+ -- XMonad.Hooks.EwmhDesktops.setDesktopViewport uses _NET_DESKTOP_VIEWPORT
+ -- only if it exists. This seems to be a harmless issue, but by creating
+ -- the atom here, we suppress the error message:
+ --
+ -- xmonad: X11 error: BadAtom (invalid Atom parameter),
+ -- request code=18, error code=5
+ --
+ _ <-
+ withDefaultDisplay $ \dpy -> internAtom dpy "_NET_DESKTOP_VIEWPORT" False
+
+ initialWorkspaces <-
+ Data.Maybe.fromMaybe (XMonad.workspaces def)
+ <$> withDefaultDisplay getDesktopNames
+
+ return
+ c { handleEventHook = ewmhDesktopsExtraEventHook <> handleEventHook c
+ , rootMask = rootMask c .|. propertyChangeMask
+ , XMonad.workspaces = initialWorkspaces
+ }
+
+ewmhDesktopsExtraEventHook :: Event -> X All
+ewmhDesktopsExtraEventHook = \case
+ PropertyEvent{ev_window, ev_atom} -> do
+ r <- asks theRoot
+ when (ev_window == r && ev_atom == _NET_DESKTOP_NAMES) $
+ withDisplay $ \dpy -> do
+ sort <- getSortByIndex
+
+ oldNames <- gets $ map tag . sort . workspaces . windowset
+ newNames <- fromMaybe oldNames <$> io (getDesktopNames dpy)
+
+ let
+ (renamesFrom, renamesTo) = both Set.fromList $ unzip renames
+
+ renames = go oldNames newNames where
+ go old@(headOld : tailOld) new@(headNew : tailNew) = do
+ let
+ deleteOld = Set.member headOld deleteNameSet
+ createNew = Set.member headNew createNameSet
+
+ if
+ | headOld == headNew ->
+ -- assert (not deleteOld && not createNew)
+ go tailOld tailNew
+
+ | deleteOld && createNew ->
+ (headOld, headNew) :
+ go tailOld tailNew
+
+ | deleteOld ->
+ go tailOld new
+
+ | createNew ->
+ go old tailNew
+
+ | otherwise ->
+ -- assert (headOld == headNew)
+ go tailOld tailNew
+
+ go _ _ = []
+
+ oldNameSet = Set.fromList oldNames
+ newNameSet = Set.fromList newNames
+ deleteNameSet = Set.difference oldNameSet newNameSet
+ createNameSet = Set.difference newNameSet oldNameSet
+
+ deleteNames = Set.toAscList $
+ Set.difference deleteNameSet renamesFrom
+ createNames = Set.toAscList $
+ Set.difference createNameSet renamesTo
+
+ mapM_ addHiddenWorkspace createNames
+ mapM_ removeEmptyWorkspaceByTag deleteNames
+ when (not (null renames)) $ do
+ let
+ renameMap = Map.fromList renames
+ rename w =
+ case Map.lookup (tag w) renameMap of
+ Just newName -> w { tag = newName }
+ Nothing -> w
+
+ modifyWindowSet $ mapWorkspace rename
+
+ names <- gets $ map tag . sort . workspaces . windowset
+
+ when (names /= newNames) $ do
+ trace $ "setDesktopNames " <> show names
+ io (setDesktopNames names dpy)
+
+ mempty
+
+ _ ->
+ mempty
diff --git a/pkgs/haskell/xmonad-tv/src/main.hs b/pkgs/haskell/xmonad-tv/src/main.hs
new file mode 100644
index 0000000..7256963
--- /dev/null
+++ b/pkgs/haskell/xmonad-tv/src/main.hs
@@ -0,0 +1,227 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE PatternSynonyms #-}
+
+module Main (main) where
+
+import System.Exit (exitFailure)
+import XMonad.Hooks.EwmhDesktops (ewmh)
+import XMonad.Hooks.EwmhDesktops.Extra (ewmhExtra)
+import XMonad.Hooks.RefocusLast (refocusLastLayoutHook, toggleFocus)
+
+import Control.Monad.Extra (whenJustM)
+import qualified Data.Aeson
+import qualified Data.ByteString.Char8
+import qualified Data.List
+import qualified Data.Maybe
+import Graphics.X11.ExtraTypes.XF86
+import XMonad
+import XMonad.Extra (isFloatingX)
+import System.IO (hPutStrLn, stderr)
+import System.Environment (getArgs, getEnv, getEnvironment, lookupEnv)
+import System.Posix.Process (executeFile)
+import XMonad.Actions.DynamicWorkspaces ( addWorkspacePrompt, renameWorkspace
+ , removeEmptyWorkspace)
+import XMonad.Actions.CycleWS (toggleWS)
+import XMonad.Layout.Gaps (Direction2D(U,R,D,L), gaps)
+import XMonad.Layout.NoBorders ( smartBorders )
+import XMonad.Layout.ResizableTile (ResizableTall(ResizableTall))
+import XMonad.Layout.ResizableTile (MirrorResize(MirrorExpand,MirrorShrink))
+import XMonad.Layout.StateFull (pattern StateFull)
+import qualified XMonad.Prompt
+import qualified XMonad.StackSet as W
+import Data.Map (Map)
+import qualified Data.Map as Map
+import XMonad.Hooks.UrgencyHook
+ ( BorderUrgencyHook(BorderUrgencyHook,urgencyBorderColor)
+ , RemindWhen(Dont)
+ , SuppressWhen(Never)
+ , UrgencyConfig(UrgencyConfig,remindWhen,suppressWhen)
+ , withUrgencyHookC
+ )
+import XMonad.Hooks.ManageHelpers (doCenterFloat,doRectFloat)
+import Data.Ratio
+import XMonad.Hooks.Place (placeHook, smart)
+import XMonad.Actions.PerWorkspaceKeys (chooseAction)
+
+import Shutdown (shutdown, newShutdownEventHandler)
+
+
+main :: IO ()
+main = getArgs >>= \case
+ [] -> mainNoArgs
+ ["--shutdown"] -> shutdown
+ args -> hPutStrLn stderr ("bad arguments: " <> show args) >> exitFailure
+
+
+(=??) :: Query a -> (a -> Bool) -> Query Bool
+(=??) x p = fmap p x
+
+readEnv :: Data.Aeson.FromJSON b => String -> IO b
+readEnv name =
+ readEnv' (error $ "could not get environment variable: " <> name) name
+
+readEnv' :: Data.Aeson.FromJSON b => b -> String -> IO b
+readEnv' defaultValue name =
+ Data.Maybe.fromMaybe defaultValue
+ . Data.Aeson.decodeStrict'
+ . Data.ByteString.Char8.pack
+ . Data.Maybe.fromMaybe mempty
+ <$> lookupEnv name
+
+mainNoArgs :: IO ()
+mainNoArgs = do
+ myScreenGaps <- readEnv' [] "XMONAD_SCREEN_GAPS" :: IO [Int]
+ myScreenWidth <- readEnv "XMONAD_SCREEN_WIDTH" :: IO Dimension
+ myTermFont <- getEnv "XMONAD_TERM_FONT"
+ myTermFontWidth <- readEnv "XMONAD_TERM_FONT_WIDTH" :: IO Dimension
+ myTermPadding <- readEnv "XMONAD_TERM_PADDING" :: IO Dimension
+ handleShutdownEvent <- newShutdownEventHandler
+ config <-
+ ewmhExtra
+ $ ewmh
+ $ withUrgencyHookC
+ BorderUrgencyHook
+ { urgencyBorderColor = "#ff0000"
+ }
+ UrgencyConfig
+ { remindWhen = Dont
+ , suppressWhen = Never
+ }
+ $ def
+ { terminal = {-pkg:alacritty-tv-}"alacritty"
+ , modMask = mod4Mask
+ , keys = myKeys myTermFont
+ , layoutHook =
+ refocusLastLayoutHook $
+ gaps (zip [U,R,D,L] myScreenGaps) $
+ smartBorders $
+ ResizableTall
+ 1
+ (fromIntegral (10 * myTermFontWidth) / fromIntegral myScreenWidth)
+ (fromIntegral (80 * myTermFontWidth + 2 * (myTermPadding + borderWidth def)) / fromIntegral myScreenWidth)
+ []
+ |||
+ StateFull
+ , manageHook =
+ composeAll
+ [ appName =? "fzmenu-urxvt" --> doCenterFloat
+ , appName =?? Data.List.isPrefixOf "pinentry" --> doCenterFloat
+ , appName =?? Data.List.isInfixOf "Float" --> doCenterFloat
+ , title =? "Upload to Imgur" -->
+ doRectFloat (W.RationalRect 0 0 (1 % 8) (1 % 8))
+ , placeHook (smart (1,0))
+ ]
+ , startupHook =
+ whenJustM (io (lookupEnv "XMONAD_STARTUP_HOOK"))
+ (\path -> forkFile path [] Nothing)
+ , normalBorderColor = "#1c1c1c"
+ , focusedBorderColor = "#f000b0"
+ , handleEventHook = handleShutdownEvent
+ }
+ directories <- getDirectories
+ launch config directories
+
+
+forkFile :: FilePath -> [String] -> Maybe [(String, String)] -> X ()
+forkFile path args env =
+ xfork (executeFile path True args env) >> return ()
+
+
+spawnRootTerm :: X ()
+spawnRootTerm =
+ forkFile
+ {-pkg:alacritty-tv-}"alacritty"
+ ["--profile=root", "-e", "/run/wrappers/bin/su", "-"]
+ Nothing
+
+
+myKeys :: String -> XConfig Layout -> Map (KeyMask, KeySym) (X ())
+myKeys font conf = Map.fromList $
+ [ ((_4 , xK_Escape ), forkFile {-pkg-}"slock" [] Nothing)
+ , ((_4S , xK_c ), kill)
+
+ , ((_4 , xK_o ), forkFile {-pkg:fzmenu-}"otpmenu" [] Nothing)
+ , ((_4 , xK_p ), forkFile {-pkg:fzmenu-}"passmenu" [] Nothing)
+
+ , ((_4 , xK_x ), forkFile {-pkg:alacritty-tv-}"alacritty" ["--singleton"] Nothing)
+ , ((_4C , xK_x ), spawnRootTerm)
+
+ , ((_C , xK_Menu ), toggleWS)
+
+ , ((_4 , xK_space ), withFocused $ \w -> ifM (isFloatingX w) xdeny $ sendMessage NextLayout)
+ , ((_4M , xK_space ), withFocused $ \w -> ifM (isFloatingX w) xdeny $ resetLayout)
+
+ , ((_4 , xK_l ), toggleFocus)
+
+ , ((_4 , xK_m ), windows W.focusMaster)
+ , ((_4 , xK_j ), windows W.focusDown)
+ , ((_4 , xK_k ), windows W.focusUp)
+
+ , ((_4S , xK_m ), windows W.swapMaster)
+ , ((_4S , xK_j ), windows W.swapDown)
+ , ((_4S , xK_k ), windows W.swapUp)
+
+ , ((_4M , xK_h ), sendMessage Shrink)
+ , ((_4M , xK_l ), sendMessage Expand)
+
+ , ((_4M , xK_j ), sendMessage MirrorShrink)
+ , ((_4M , xK_k ), sendMessage MirrorExpand)
+
+ , ((_4 , xK_t ), withFocused $ windows . W.sink)
+
+ , ((_4 , xK_comma ), sendMessage $ IncMasterN 1)
+ , ((_4 , xK_period ), sendMessage $ IncMasterN (-1))
+
+ , ((_4 , xK_a ), addWorkspacePrompt promptXPConfig)
+ , ((_4 , xK_r ), renameWorkspace promptXPConfig)
+ , ((_4 , xK_Delete ), removeEmptyWorkspace)
+
+ , ((_4 , xK_Return ), toggleWS)
+
+ , ((0, xF86XK_AudioLowerVolume), audioLowerVolume)
+ , ((0, xF86XK_AudioRaiseVolume), audioRaiseVolume)
+ , ((0, xF86XK_AudioMute), audioMute)
+ , ((0, xF86XK_AudioMicMute), audioMicMute)
+ , ((_4, xF86XK_AudioMute), pavucontrol [])
+
+ , ((_4, xK_Prior), forkFile {-pkg-}"xcalib" ["-invert", "-alter"] Nothing)
+
+ , ((0, xK_Print), forkFile {-pkg:flameshot-once-tv-}"flameshot-once" [] Nothing)
+
+ , ((_C, xF86XK_Forward), forkFile {-pkg:xdpytools-}"xdpychvt" ["next"] Nothing)
+ , ((_C, xF86XK_Back), forkFile {-pkg:xdpytools-}"xdpychvt" ["prev"] Nothing)
+ ]
+ where
+ _4 = mod4Mask
+ _C = controlMask
+ _S = shiftMask
+ _M = mod1Mask
+ _4C = _4 .|. _C
+ _4S = _4 .|. _S
+ _4M = _4 .|. _M
+ _4CM = _4 .|. _C .|. _M
+ _4SM = _4 .|. _S .|. _M
+
+ amixer args = forkFile {-pkg:alsaUtils-}"amixer" args Nothing
+ pavucontrol args = forkFile {-pkg-}"pavucontrol" args Nothing
+
+ audioLowerVolume = amixer ["-q", "sset", "Master", "5%-"]
+ audioRaiseVolume = amixer ["-q", "sset", "Master", "5%+"]
+ audioMute = amixer ["-q", "sset", "Master", "toggle"]
+ audioMicMute = amixer ["-q", "sset", "Capture", "toggle"]
+
+ resetLayout = setLayout $ XMonad.layoutHook conf
+
+ promptXPConfig =
+ def { XMonad.Prompt.font = font }
+
+ xdeny =
+ forkFile
+ {-pkg-}"xterm"
+ [ "-fn", font
+ , "-geometry", "300x100"
+ , "-name", "AlertFloat"
+ , "-bg", "#E4002B"
+ , "-e", "sleep", "0.05"
+ ]
+ Nothing
diff --git a/pkgs/haskell/xmonad-tv/src/xmonad-tv.cabal b/pkgs/haskell/xmonad-tv/src/xmonad-tv.cabal
new file mode 100644
index 0000000..f211627
--- /dev/null
+++ b/pkgs/haskell/xmonad-tv/src/xmonad-tv.cabal
@@ -0,0 +1,29 @@
+name: xmonad-tv
+version: 1.0.0
+license: MIT
+author: tv <tv@krebsco.de>
+maintainer: tv <tv@krebsco.de>
+build-type: Simple
+cabal-version: >=1.10
+
+executable xmonad
+ main-is: main.hs
+ build-depends:
+ base
+ , X11
+ , aeson
+ , bytestring
+ , containers
+ , directory
+ , extra
+ , filepath
+ , pager
+ , unix
+ , xmonad
+ , xmonad-contrib
+ other-modules:
+ Shutdown
+ XMonad.Extra
+ XMonad.Hooks.EwmhDesktops.Extra
+ default-language: Haskell2010
+ ghc-options: -O2 -Wall
diff --git a/pkgs/override/alacritty.nix b/pkgs/override/alacritty.nix
new file mode 100644
index 0000000..f864fff
--- /dev/null
+++ b/pkgs/override/alacritty.nix
@@ -0,0 +1,16 @@
+self: super:
+
+super.alacritty.overrideAttrs (old:
+ if self.lib.versions.majorMinor old.version == "0.12" then
+ {
+ version = "${old.version}-tv";
+ src = self.fetchFromGitHub {
+ owner = "4z3";
+ repo = "alacritty";
+ rev = "touchscreen-support-0.12";
+ hash = "sha256-yDG7IeQUmJhKMJebhMDzHLb3UHGLcO1FVZnmGe5Xr9w=";
+ };
+ }
+ else
+ builtins.trace "not overriding alacritty because unsupported version" {}
+)
diff --git a/pkgs/override/anbox.nix b/pkgs/override/anbox.nix
new file mode 100644
index 0000000..3940617
--- /dev/null
+++ b/pkgs/override/anbox.nix
@@ -0,0 +1,72 @@
+self: super:
+
+# https://github.com/NixOS/nixpkgs/pull/125600
+super.anbox.overrideAttrs (old:
+ assert old.version == "unstable-2020-11-29";
+ rec {
+ version = "unstable-2021-05-26";
+
+ src = self.fetchFromGitHub {
+ owner = old.pname;
+ repo = old.pname;
+ rev = "ad377ff25354d68b76e2b8da24a404850f8514c6";
+ sha256 = "1bj07ixwbkli4ycjh41mnqdbsjz9haiwg2nhf9anbi29z1d0819w";
+ fetchSubmodules = true;
+ };
+
+ postPatch = old.patchPhase;
+
+ # patchPhase() from <nixpkgs/pkgs/stdenv/generic/setup.sh>
+ # TODO patchPhase = default.patchPhase; or something
+ patchPhase = ''
+ runHook prePatch
+
+ for i in ''${patches:-}; do
+ header "applying patch $i" 3
+ local uncompress=cat
+ case "$i" in
+ *.gz)
+ uncompress="gzip -d"
+ ;;
+ *.bz2)
+ uncompress="bzip2 -d"
+ ;;
+ *.xz)
+ uncompress="xz -d"
+ ;;
+ *.lzma)
+ uncompress="lzma -d"
+ ;;
+ esac
+ # "2>&1" is a hack to make patch fail if the decompressor fails (nonexistent patch, etc.)
+ # shellcheck disable=SC2086
+ $uncompress < "$i" 2>&1 | patch ''${patchFlags:--p1}
+ done
+
+ runHook postPatch
+ '';
+
+ patches = [
+ # Fixes compatibility with lxc 4
+ (self.fetchpatch {
+ url = "https://git.alpinelinux.org/aports/plain/community/anbox/lxc4.patch?id=64243590a16aee8d4e72061886fc1b15256492c3";
+ sha256 = "1da5xyzyjza1g2q9nbxb4p3njj2sf3q71vkpvmmdphia5qnb0gk5";
+ })
+ # Wait 10× more time when starting
+ # Not *strictly* needed, but helps a lot on slower hardware
+ (self.fetchpatch {
+ url = "https://git.alpinelinux.org/aports/plain/community/anbox/give-more-time-to-start.patch?id=058b56d4b332ef3379551b343bf31e0f2004321a";
+ sha256 = "0iiz3c7fgfgl0dvx8sf5hv7a961xqnihwpz6j8r0ib9v8piwxh9a";
+ })
+ # Ensures generated desktop files work on store path change
+ (self.fetchpatch {
+ url = "https://raw.githubusercontent.com/NixOS/nixpkgs/fdf7b4be1a659ed8b96586c2fc8ff90850e25feb/pkgs/os-specific/linux/anbox/0001-NixOS-Use-anbox-from-PATH-in-desktop-files.patch";
+ sha256 = "173z84g1r8h367a2dgk6945is6vxg4j1hs2hkfd3m3bbpwfw9221";
+ })
+ # Provide window icons
+ (self.fetchpatch {
+ url = "https://github.com/samueldr/anbox/commit/2387f4fcffc0e19e52e58fb6f8264fbe87aafe4d.patch";
+ sha256 = "12lmr0kxw1n68g3abh1ak5awmpczfh75c26f53jc8qpvdvv1ywha";
+ })
+ ];
+})
diff --git a/pkgs/override/default.nix b/pkgs/override/default.nix
new file mode 100644
index 0000000..cf64142
--- /dev/null
+++ b/pkgs/override/default.nix
@@ -0,0 +1,11 @@
+self: super:
+
+let
+ inherit (super) lib;
+
+ mylib = import ../../lib/pure.nix {
+ inherit lib;
+ };
+in
+
+mylib.mapNixDir (path: import path self super) ./.
diff --git a/pkgs/override/fzf/complete1.patch b/pkgs/override/fzf/complete1.patch
new file mode 100644
index 0000000..3e3f2c4
--- /dev/null
+++ b/pkgs/override/fzf/complete1.patch
@@ -0,0 +1,77 @@
+commit 57cbd76c068121b685399fdb4649e7ba537983d6
+Author: tv <tv@krebsco.de>
+Date: Mon Dec 5 15:24:30 2022 +0100
+
+ Add --complete-1 option
+
+diff --git a/man/man1/fzf.1 b/man/man1/fzf.1
+index 79e7291..3b8a753 100644
+--- a/man/man1/fzf.1
++++ b/man/man1/fzf.1
+@@ -685,6 +685,9 @@ interactive finder and automatically select the only match
+ If there is no match for the initial query (\fB--query\fR), do not start
+ interactive finder and exit immediately
+ .TP
++.B "--complete-1"
++Exit interactive finder when there's exactly one match
++.TP
+ .BI "-f, --filter=" "STR"
+ Filter mode. Do not start interactive finder. When used with \fB--no-sort\fR,
+ fzf becomes a fuzzy-version of grep.
+diff --git a/src/core.go b/src/core.go
+index 2ddddc3..09afff2 100644
+--- a/src/core.go
++++ b/src/core.go
+@@ -337,8 +337,14 @@ func Run(opts *Options, version string, revision string) {
+ }
+ determine(val.final)
+ }
++ } else {
++ if opts.Complete1 && val.Length() == 1 {
++ opts.Printer(val.Get(0).item.AsString(opts.Ansi))
++ terminal.reqBox.Set(reqClose, nil)
++ } else {
++ terminal.UpdateList(val, clearSelection())
++ }
+ }
+- terminal.UpdateList(val, clearSelection())
+ }
+ }
+ }
+diff --git a/src/options.go b/src/options.go
+index 5400311..1e38fe4 100644
+--- a/src/options.go
++++ b/src/options.go
+@@ -108,6 +108,7 @@ const usage = `usage: fzf [options]
+ -1, --select-1 Automatically select the only match
+ -0, --exit-0 Exit immediately when there's no match
+ -f, --filter=STR Filter mode. Do not start interactive finder.
++ --complete-1 Exit interactive finder when there's exactly one match
+ --print-query Print query as the first line
+ --expect=KEYS Comma-separated list of keys to complete fzf
+ --read0 Read input delimited by ASCII NUL characters
+@@ -274,6 +275,7 @@ type Options struct {
+ Query string
+ Select1 bool
+ Exit0 bool
++ Complete1 bool
+ Filter *string
+ ToggleSort bool
+ Expect map[tui.Event]string
+@@ -342,6 +344,7 @@ func defaultOptions() *Options {
+ Query: "",
+ Select1: false,
+ Exit0: false,
++ Complete1: false,
+ Filter: nil,
+ ToggleSort: false,
+ Expect: make(map[tui.Event]string),
+@@ -1546,6 +1549,8 @@ func parseOptions(opts *Options, allArgs []string) {
+ opts.Exit0 = true
+ case "+0", "--no-exit-0":
+ opts.Exit0 = false
++ case "--complete-1":
++ opts.Complete1 = true
+ case "--read0":
+ opts.ReadZero = true
+ case "--no-read0":
diff --git a/pkgs/override/fzf/default.nix b/pkgs/override/fzf/default.nix
new file mode 100644
index 0000000..2254d45
--- /dev/null
+++ b/pkgs/override/fzf/default.nix
@@ -0,0 +1,7 @@
+self: super:
+
+super.fzf.overrideAttrs (old: {
+ patches = old.patches or [] ++ [
+ ./complete1.patch
+ ];
+})
diff --git a/pkgs/override/gitAndTools.nix b/pkgs/override/gitAndTools.nix
new file mode 100644
index 0000000..a460773
--- /dev/null
+++ b/pkgs/override/gitAndTools.nix
@@ -0,0 +1,5 @@
+self: super:
+
+super.gitAndTools // {
+ inherit (self) diff-so-fancy;
+}
diff --git a/pkgs/override/input-fonts.nix b/pkgs/override/input-fonts.nix
new file mode 100644
index 0000000..6ee7afa
--- /dev/null
+++ b/pkgs/override/input-fonts.nix
@@ -0,0 +1,13 @@
+self: super:
+
+super.input-fonts.overrideAttrs (old: rec {
+ src = self.fetchzip {
+ url = "http://xu.r/~tv/mirrors/input-fonts/Input-Font-2.zip";
+ sha256 = "1q58x92nm7dk9ylp09pvgj74nxkywvqny3xmfighnsl30dv42fcr";
+ stripRoot = false;
+ };
+ sourceRoot = null;
+ outputHash = null;
+ outputHashAlgo = null;
+ outputHashMode = null;
+})
diff --git a/pkgs/override/iosevka-tv-1.nix b/pkgs/override/iosevka-tv-1.nix
new file mode 100644
index 0000000..880160b
--- /dev/null
+++ b/pkgs/override/iosevka-tv-1.nix
@@ -0,0 +1,20 @@
+self: super:
+
+let
+ srcpkg = super.iosevka-tv-1;
+ binpkg = self.fetchzip {
+ inherit (srcpkg) pname version;
+ stripRoot = false;
+ hash = "sha256-QIuTS70vUQSvDDXjY4uI6SCcu1XT4HjvzpthvrNX4h0=";
+ urls = [
+ "https://c.krebsco.de/${srcpkg.name}.tar.gz"
+ "https://ni.krebsco.de/~tv/mirrors/iosevka/${srcpkg.name}.tar.gz"
+ ];
+ };
+in
+
+if srcpkg.version == binpkg.version then
+ binpkg
+
+else
+ srcpkg
diff --git a/pkgs/override/iosevka-tv-2.nix b/pkgs/override/iosevka-tv-2.nix
new file mode 100644
index 0000000..2eecf3c
--- /dev/null
+++ b/pkgs/override/iosevka-tv-2.nix
@@ -0,0 +1,20 @@
+self: super:
+
+let
+ srcpkg = super.iosevka-tv-2;
+ binpkg = self.fetchzip {
+ inherit (srcpkg) pname version;
+ stripRoot = false;
+ hash = "sha256-PuIrW1ftYD5PW4du6gq1XpUM3v0potwmj+vAxJImF/A=";
+ urls = [
+ "https://c.krebsco.de/${srcpkg.name}.tar.gz"
+ "https://ni.krebsco.de/~tv/mirrors/iosevka/${srcpkg.name}.tar.gz"
+ ];
+ };
+in
+
+if srcpkg.version == binpkg.version then
+ binpkg
+
+else
+ srcpkg
diff --git a/pkgs/override/jc.nix b/pkgs/override/jc.nix
new file mode 100644
index 0000000..346dd3e
--- /dev/null
+++ b/pkgs/override/jc.nix
@@ -0,0 +1,21 @@
+self: super:
+
+let
+ version = "1.21.0";
+in
+
+# Prevent downgrades.
+assert self.lib.versionAtLeast version super.jc.version;
+
+self.python3.pkgs.toPythonApplication
+ (self.python3.pkgs.jc.overrideAttrs
+ (oldAttrs: {
+ name = "jc-${version}";
+ version = version;
+ src = self.fetchFromGitHub {
+ owner = "kellyjonbrazil";
+ repo = "jc";
+ rev = "v${version}";
+ sha256 = "sha256-kS42WokR7ZIqIPi8LbX4tmtjn37tckea2ELbuqzTm2o";
+ };
+ }))
diff --git a/pkgs/override/uqmi.nix b/pkgs/override/uqmi.nix
new file mode 100644
index 0000000..1eaecbd
--- /dev/null
+++ b/pkgs/override/uqmi.nix
@@ -0,0 +1,10 @@
+self: super:
+
+super.uqmi.overrideAttrs (old: {
+ version = "unstable-2022-05-04";
+ src = self.fetchgit {
+ url = "https://git.openwrt.org/project/uqmi.git";
+ rev = "56cb2d4056fef132ccf78dfb6f3074ae5d109992";
+ hash = "sha256-PwnR24PbNKfLrsBlU5JTOHDzs/9Wgcuwfnu3dJuuZcM=";
+ };
+})
diff --git a/pkgs/rpi/433Utils/RPi_utils.codesend.codestring.patch b/pkgs/rpi/433Utils/RPi_utils.codesend.codestring.patch
new file mode 100644
index 0000000..447e42f
--- /dev/null
+++ b/pkgs/rpi/433Utils/RPi_utils.codesend.codestring.patch
@@ -0,0 +1,24 @@
+--- a/RPi_utils/codesend.cpp
++++ b/RPi_utils/codesend.cpp
+@@ -40,18 +40,18 @@ int main(int argc, char *argv[]) {
+ }
+
+ // Change protocol and pulse length accroding to parameters
+- int code = atoi(argv[1]);
++ const char *code = argv[1];
+ if (argc >= 3) protocol = atoi(argv[2]);
+ if (argc >= 4) pulseLength = atoi(argv[3]);
+
+ if (wiringPiSetup () == -1) return 1;
+- printf("sending code[%i]\n", code);
++ printf("sending code[%s]\n", code);
+ RCSwitch mySwitch = RCSwitch();
+ if (protocol != 0) mySwitch.setProtocol(protocol);
+ if (pulseLength != 0) mySwitch.setPulseLength(pulseLength);
+ mySwitch.enableTransmit(PIN);
+
+- mySwitch.send(code, 24);
++ mySwitch.send(code);
+
+ return 0;
+
diff --git a/pkgs/rpi/433Utils/default.nix b/pkgs/rpi/433Utils/default.nix
new file mode 100644
index 0000000..136e3db
--- /dev/null
+++ b/pkgs/rpi/433Utils/default.nix
@@ -0,0 +1,42 @@
+{ fetchFromGitHub, lib, stdenv
+, wiringPi ? WiringPi.wiringPi
+, wiringPiDev ? WiringPi.wiringPiDev
+, WiringPi ? rpiPackages.WiringPi
+, rpiPackages
+}:
+
+stdenv.mkDerivation {
+ pname = "433Utils-RPi_utils";
+ version = "2018-06-07";
+
+ src = fetchFromGitHub (lib.importJSON ./src.json);
+
+ patches = [
+ ./rc-switch.protocols.patch
+ ./RPi_utils.codesend.codestring.patch
+ ];
+
+ buildPhase = ''
+ runHook postBuild
+
+ make -C RPi_utils
+
+ runHook preBuild
+ '';
+
+ buildInputs = [
+ wiringPi
+ wiringPiDev
+ ];
+
+ installPhase = ''
+ runHook preInstall
+
+ mkdir -p $out/bin
+ for name in send codesend RFSniffer; do
+ cp RPi_utils/$name $out/bin/
+ done
+
+ runHook postInstall
+ '';
+}
diff --git a/pkgs/rpi/433Utils/rc-switch.protocols.patch b/pkgs/rpi/433Utils/rc-switch.protocols.patch
new file mode 100644
index 0000000..41304ef
--- /dev/null
+++ b/pkgs/rpi/433Utils/rc-switch.protocols.patch
@@ -0,0 +1,10 @@
+--- a/rc-switch/RCSwitch.cpp
++++ b/rc-switch/RCSwitch.cpp
+@@ -78,6 +78,7 @@ static const RCSwitch::Protocol PROGMEM proto[] = {
+ { 100, { 30, 71 }, { 4, 11 }, { 9, 6 } }, // protocol 3
+ { 380, { 1, 6 }, { 1, 3 }, { 3, 1 } }, // protocol 4
+ { 500, { 6, 14 }, { 1, 2 }, { 2, 1 } }, // protocol 5
++ { 136, { 1, 31 }, { 1, 3 }, { 3, 1 } }, // protocol 6
+ };
+
+ enum {
diff --git a/pkgs/rpi/433Utils/src.json b/pkgs/rpi/433Utils/src.json
new file mode 100644
index 0000000..3cf2327
--- /dev/null
+++ b/pkgs/rpi/433Utils/src.json
@@ -0,0 +1,7 @@
+{
+ "owner": "ninjablocks",
+ "repo": "433Utils",
+ "rev": "31c0ea4e158287595a6f6116b6151e72691e1839",
+ "sha256": "04r2qlkdsz46qgpnbizrfccz1i0qlkb1iqz0jzyq4fzvksqp9dg1",
+ "fetchSubmodules": true
+} \ No newline at end of file
diff --git a/pkgs/rpi/WiringPi/default.nix b/pkgs/rpi/WiringPi/default.nix
new file mode 100644
index 0000000..40fcaea
--- /dev/null
+++ b/pkgs/rpi/WiringPi/default.nix
@@ -0,0 +1,61 @@
+{ fetchFromGitHub, lib, runCommand, stdenv }:
+
+let
+ generic = name: extraAttrs:
+ stdenv.mkDerivation ({
+ pname = "WiringPi-${name}";
+ version = "2020-09-14";
+
+ src = fetchFromGitHub (lib.importJSON ./src.json);
+
+ buildPhase = ''
+ runHook postBuild
+
+ make -C ${name} all
+
+ runHook preBuild
+ '';
+
+ installPhase = ''
+ runHook preInstall
+
+ export DESTDIR=$out
+ export PREFIX=
+ export LDCONFIG=true
+
+ make -C ${name} install
+
+ runHook postInstall
+ '';
+ } // extraAttrs);
+
+ fakeutils = runCommand "fakeutils-1.0" {} /* sh */ ''
+ mkdir -p $out/bin
+ for name in chown chmod; do
+ touch $out/bin/$name
+ chmod +x $out/bin/$name
+ done
+ '';
+in
+
+rec {
+ wiringPi = generic "wiringPi" {};
+ wiringPiDev = generic "devLib" {
+ buildInputs = [
+ wiringPi
+ ];
+ };
+ gpio = generic "gpio" {
+ preInstall = ''
+ # fakeutils cannot be buildInputs because they have to override existing
+ # executables and therefore need to be prepended to the search path.
+ PATH=${fakeutils}/bin:$PATH
+
+ mkdir -p $out/bin
+ '';
+ buildInputs = [
+ wiringPi
+ wiringPiDev
+ ];
+ };
+}
diff --git a/pkgs/rpi/WiringPi/src.json b/pkgs/rpi/WiringPi/src.json
new file mode 100644
index 0000000..edf4e82
--- /dev/null
+++ b/pkgs/rpi/WiringPi/src.json
@@ -0,0 +1,6 @@
+{
+ "owner": "WiringPi",
+ "repo": "WiringPi",
+ "rev": "5c6bab7d4279e8c0cc890984eaa1a69ff3af1c99",
+ "sha256": "1jlx7lb3ybwv06b2dpmsr718d0xj85awl1dgdqc607k50kk25mjb"
+}
diff --git a/pkgs/rpi/default.nix b/pkgs/rpi/default.nix
new file mode 100644
index 0000000..50f8aad
--- /dev/null
+++ b/pkgs/rpi/default.nix
@@ -0,0 +1,11 @@
+self: super:
+
+let
+ mylib = import ../../lib/pure.nix {
+ inherit (super) lib;
+ };
+in
+
+{
+ rpiPackages = mylib.mapNixDir (path: self.callPackage path {}) ./.;
+}
diff --git a/pkgs/simple/alacritty-tv.nix b/pkgs/simple/alacritty-tv.nix
new file mode 100644
index 0000000..efbcc6e
--- /dev/null
+++ b/pkgs/simple/alacritty-tv.nix
@@ -0,0 +1,155 @@
+{ lib
+, pkgs
+, variant ? "x220"
+}:
+
+let
+ mylib = import ../../lib/pure.nix {
+ inherit lib;
+ };
+ font-size = arg: {
+ program = "${pkgs.font-size-alacritty}/bin/font-size-alacritty";
+ args = [arg];
+ };
+ configs.default = lib.recursiveUpdate variants.${variant} {
+ bell.animation = "EaseOut";
+ bell.duration = 50;
+ bell.color = "#ff00ff";
+ colors.cursor.cursor = "#f042b0";
+ colors.primary.background = "#202020";
+ colors.primary.foreground = "#d0d7d0";
+ colors.normal.black = "#000000";
+ colors.normal.red = "#cd0000";
+ colors.normal.green = "#00cd00";
+ colors.normal.yellow = "#bc7004";
+ colors.normal.blue = "#4343be";
+ colors.normal.magenta = "#cb06cb";
+ colors.normal.cyan = "#04c9c9";
+ colors.normal.white = "#bebebe";
+ colors.bright.black = "#727272";
+ colors.bright.red = "#fb6262";
+ colors.bright.green = "#72fb72";
+ colors.bright.yellow = "#fbfb72";
+ colors.bright.blue = "#7272fb";
+ colors.bright.magenta = "#fb53fb";
+ colors.bright.cyan = "#72fbfb";
+ colors.bright.white = "#fbfbfb";
+ draw_bold_text_with_bright_colors = true;
+ hints.enabled = [
+ {
+ regex = "(ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)[^\\u0000-\\u001F\\u007F-\\u009F<>\"\\s{-}\\^⟨⟩`]+";
+ mouse.enabled = true;
+ post_processing = true;
+ action = "Select";
+ }
+ ];
+ scrolling.multiplier = 8;
+ };
+ configs.root = lib.recursiveUpdate configs.default {
+ colors.primary.background = "#230000";
+ colors.primary.foreground = "#e0c0c0";
+ colors.normal.black = "#800000";
+ };
+ configs.fzmenu = lib.recursiveUpdate configs.default {
+ colors.primary.background = "#2A172A";
+ window.dimensions.columns = 70;
+ window.dimensions.lines = 9;
+ };
+ variants.hidpi = {
+ font.normal.family = "iosevka tv 2 Light";
+ font.italic.family = "iosevka tv 2 Light";
+ font.bold.family = "iosevka tv 2 Medium";
+ font.bold_italic.family = "iosevka tv 2 Medium";
+ font.size = 5;
+ key_bindings = [
+ { key = "Up"; mods = "Control"; action = "IncreaseFontSize"; }
+ { key = "Down"; mods = "Control"; action = "DecreaseFontSize"; }
+ { key = "Down"; mods = "Shift|Control"; action = "ResetFontSize"; }
+ ];
+ };
+ variants.x220 = {
+ font.normal.family = "Clean";
+ font.bold.family = "Clean";
+ font.bold.style = "Regular";
+ font.size = 10;
+ key_bindings = [
+ { key = "Up"; mods = "Shift|Control"; command = font-size "=14"; }
+ { key = "Up"; mods = "Control"; command = font-size "+1"; }
+ { key = "Down"; mods = "Control"; command = font-size "-1"; }
+ { key = "Down"; mods = "Shift|Control"; command = font-size "=0"; }
+ ];
+ };
+ writeProfile = name: config: let
+ config-file =
+ assert mylib.types.filename.check name;
+ pkgs.writeJSON "alacritty-tv-${name}.json" config;
+ in pkgs.writeText "alacritty-tv-${name}.profile" /* sh */ ''
+ # Use home so Alacritty can find the configuration without arguments.
+ # HOME will be reset once in Alacritty.
+ HOME=$XDG_RUNTIME_DIR/Alacritty-${name}
+ export HOME
+
+ # Tell Alacritty via XDG_RUNTIME_DIR where to create sockets.
+ # XDG_RUNTIME_DIR needs to be reset manually.
+ export ALACRITTY_XDG_RUNTIME_DIR="$XDG_RUNTIME_DIR"
+ export BASH_EXTRA_INIT=${pkgs.writeDash "alacritty-tv.cleanup.sh" ''
+ XDG_RUNTIME_DIR=$ALACRITTY_XDG_RUNTIME_DIR
+ unset ALACRITTY_XDG_RUNTIME_DIR
+ unset BASH_EXTRA_INIT
+ ''}
+ export XDG_RUNTIME_DIR="$HOME"
+
+ # Install stored configuration if it has changed.
+ # This allows for both declarative updates and runtime modifications.
+ # rust-xdg requires XDG_RUNTIME_DIR to be secure:
+ # https://docs.rs/xdg/2.4.1/src/xdg/lib.rs.html#311
+ ${pkgs.coreutils}/bin/mkdir -m 0700 -p "$HOME"
+ ref=$(! test -e "$HOME"/ref || ${pkgs.coreutils}/bin/cat "$HOME"/ref)
+ if test "$ref" != ${config-file}; then
+ echo ${config-file} > "$HOME"/ref
+ ${pkgs.coreutils}/bin/install -m 644 ${config-file} "$HOME"/.alacritty.yml
+ fi
+ '';
+in
+
+pkgs.symlinkJoin {
+ name = "alacritty-tv";
+ paths = [
+ (pkgs.writeDashBin "alacritty" ''
+ # usage:
+ # alacritty [--profile=PROFILE] [--singleton] [ARGS...]
+ # where
+ # PROFILE one of ${builtins.toJSON (builtins.attrNames configs)}
+
+ set -efu
+
+ case ''${1-} in
+ ${lib.concatMapStringsSep "\n" (name: /* sh */ ''
+ --${mylib.shell.escape name}|--profile=${mylib.shell.escape name})
+ shift
+ profile=${writeProfile name configs.${name}}
+ ;;
+ '') (builtins.attrNames configs)}
+ *)
+ profile=${writeProfile "default" configs.default}
+ ;;
+ esac
+
+
+ case ''${1-} in
+ --singleton)
+ shift
+ if ! ${pkgs.alacritty}/bin/alacritty msg create-window "$@"; then
+ . "$profile"
+ ${pkgs.alacritty}/bin/alacritty "$@" &
+ fi
+ ;;
+ *)
+ . "$profile"
+ exec ${pkgs.alacritty}/bin/alacritty "$@"
+ ;;
+ esac
+ '')
+ pkgs.alacritty
+ ];
+}
diff --git a/pkgs/simple/bash-fzf-history.nix b/pkgs/simple/bash-fzf-history.nix
new file mode 100644
index 0000000..f35d5e8
--- /dev/null
+++ b/pkgs/simple/bash-fzf-history.nix
@@ -0,0 +1,107 @@
+{ lib
+, pkgs
+
+, edit-key ? "ctrl-e"
+, exec-key ? "enter"
+, edit-mark ? "${mark-prefix}${edit-key}"
+, exec-mark ? "${mark-prefix}${exec-key}"
+, edit-command ? "\"\""
+, exec-command ? "accept-line"
+, mark-prefix ? " #FZFKEY:"
+, finish-keyseq ? "\\C-x\\C-p"
+, rebind-keyseq ? "\\C-x\\C-o"
+
+, start-keyseq ? "\\C-f"
+, load-keyseq ? start-keyseq
+}: let
+
+ mylib = import ../../lib/pure.nix {
+ inherit lib;
+ };
+
+ script = pkgs.writeBash "bash-fzf-history.sh" ''
+ if ! command -v fzf >/dev/null; then
+ # Alternatively rewrite ${pkgs.fzf}/share/fzf/* to use absolute paths.
+ fzf() {
+ ${pkgs.fzf}/bin/fzf "$@"
+ }
+ fi
+
+ . ${pkgs.fzf}/share/fzf/key-bindings.bash
+ . ${pkgs.fzf}/share/fzf/completion.bash
+
+ FZF_DEFAULT_OPTS='${toString [
+ /* sh */ "--height=40%"
+ /* sh */ "--inline-info"
+ /* sh */ "--min-height=4"
+ /* sh */ "--reverse"
+ ]}'
+
+ __fzf_history__() (
+ IFS=$'\n'
+ result=( $(
+ # To add "unknown timestamps" to each line of the history:
+ # sed -i '/^#[0-9]/{n;b};s/^/#1\n/' "$HISTFILE"
+ HISTTIMEFORMAT=$'\e[38;5;244m%Y-%m-%dT%H:%M:%S\e[m ' history |
+ ${pkgs.gnused}/bin/sed '
+ s/\(\x1b\[[0-9;]*\)244m1970-[0-9T:-]*/\1237m????-??-??T??:??:??/
+ ' |
+ FZF_DEFAULT_OPTS="${toString [
+ /* sh */ "--ansi"
+ /* sh */ "--tac"
+ /* sh */ "--sync"
+ /* sh */ "-n2..,.."
+ /* sh */ "--tiebreak=index"
+ /* sh */ "--bind=ctrl-r:toggle-sort"
+ /* sh */ "--expect=${edit-key},${exec-key}"
+ /* sh */ "$FZF_DEFAULT_OPTS"
+ /* sh */ "+m"
+ ]}" \
+ ${pkgs.fzf}/bin/fzf |
+ ${pkgs.gnused}/bin/sed '
+ /^ *[0-9]/{
+ s/^ *//
+ s/ \+/\n/;# index
+ s/ \+/\n/;# date
+ }
+ '
+ ) )
+ if test -n "$result"; then
+ key=''${result[0]}
+ index=''${result[1]}
+ date=''${result[2]}
+ command=''${result[3]}
+
+ echo "$command${mark-prefix}$key"
+ else
+ # Ensure no empty new line gets produced when fzf was aborted.
+ echo '${edit-mark}'
+ fi
+ )
+
+ __fzf_rebind_finish_keyseq__() {
+ local suffix=
+ case $READLINE_LINE in
+ *'${edit-mark}')
+ suffix='${edit-mark}'
+ bind '"${finish-keyseq}": ${edit-command}'
+ ;;
+ *'${exec-mark}')
+ suffix='${exec-mark}'
+ bind '"${finish-keyseq}": ${exec-command}'
+ ;;
+ esac
+ READLINE_LINE=${"\${READLINE_LINE:0:-\${#suffix}}"}
+ }
+ bind -x '"${rebind-keyseq}": __fzf_rebind_finish_keyseq__'
+
+ bind '"\C-r": reverse-search-history'
+ bind '"${start-keyseq}": " \C-e\C-u\C-y\ey\C-u`__fzf_history__`\e\C-e\er\e^${rebind-keyseq}${finish-keyseq}"'
+
+ echo '# fzf key bindings loaded:' >&2
+ bind -s | ${pkgs.gnugrep}/bin/grep __fzf_ >&2
+ '';
+in
+ script.overrideAttrs (old: rec {
+ bind = /* sh */ ''bind -x '"${load-keyseq}": . ${script}' '';
+ })
diff --git a/pkgs/simple/cr.nix b/pkgs/simple/cr.nix
new file mode 100644
index 0000000..048d779
--- /dev/null
+++ b/pkgs/simple/cr.nix
@@ -0,0 +1,16 @@
+{ pkgs }:
+
+pkgs.writeDashBin "cr" ''
+ set -efu
+ if test -n "''${XDG_RUNTIME_DIR-}"; then
+ cache_dir=$XDG_RUNTIME_DIR/chromium-disk-cache
+ else
+ cache_dir=/tmp/chromium-disk-cache_$LOGNAME
+ fi
+ export LC_TIME=de_DE.utf8
+ exec ${pkgs.chromium}/bin/chromium \
+ --ssl-version-min=tls1 \
+ --disk-cache-dir="$cache_dir" \
+ --disk-cache-size=50000000 \
+ "$@"
+''
diff --git a/pkgs/simple/default.nix b/pkgs/simple/default.nix
new file mode 100644
index 0000000..1c4a53b
--- /dev/null
+++ b/pkgs/simple/default.nix
@@ -0,0 +1,22 @@
+self: super:
+
+let
+ inherit (super) lib;
+
+ mylib = import ../../lib/pure.nix {
+ inherit lib;
+ };
+
+ # This callPackage will try to detect obsolete overrides.
+ callPackage = path: args: let
+ override = self.callPackage path args;
+ upstream = lib.optionalAttrs (override ? "name")
+ (super.${(builtins.parseDrvName override.name).name} or {});
+ in if upstream ? "name" &&
+ override ? "name" &&
+ builtins.compareVersions upstream.name override.name != -1
+ then builtins.trace "Upstream `${upstream.name}' gets overridden by `${override.name}'." override
+ else override;
+in
+
+ mylib.mapNixDir (path: callPackage path {}) ./.
diff --git a/pkgs/simple/diff-so-fancy.nix b/pkgs/simple/diff-so-fancy.nix
new file mode 100644
index 0000000..d57e6e7
--- /dev/null
+++ b/pkgs/simple/diff-so-fancy.nix
@@ -0,0 +1,50 @@
+{ fetchFromGitHub, lib, stdenv
+, coreutils, git, makeWrapper, ncurses, perl
+}:
+
+stdenv.mkDerivation rec {
+ name = "diff-so-fancy-${version}";
+ version = "ed8cf17";
+
+ src = fetchFromGitHub {
+ owner = "so-fancy";
+ repo = "diff-so-fancy";
+ rev = "ed8cf1763d38bdd79ceb55a73b9ce7e30f1e184d";
+ sha256 = "176qn0w2rn6mr5ymvkblyiznqq7yyibfsnnjfivcyhz69w6yr9r9";
+ };
+
+ # Perl is needed here for patchShebangs
+ nativeBuildInputs = [ perl makeWrapper ];
+
+ buildPhase = null;
+
+ installPhase = ''
+ mkdir -p $out/bin $out/lib/diff-so-fancy
+
+ # diff-so-fancy executable searches for it's library relative to
+ # itself, so we are copying executable to lib, and only symlink it
+ # from bin/
+ cp diff-so-fancy $out/lib/diff-so-fancy
+ cp -r lib $out/lib/diff-so-fancy
+ ln -s $out/lib/diff-so-fancy/diff-so-fancy $out/bin
+
+ # ncurses is needed for `tput`
+ wrapProgram $out/lib/diff-so-fancy/diff-so-fancy \
+ --prefix PATH : "${git}/share/git/contrib/diff-highlight" \
+ --prefix PATH : "${git}/bin" \
+ --prefix PATH : "${coreutils}/bin" \
+ --prefix PATH : "${ncurses.out}/bin"
+ '';
+
+ meta = with lib; {
+ homepage = https://github.com/so-fancy/diff-so-fancy;
+ description = "Good-looking diffs filter for git";
+ license = licenses.mit;
+ platforms = platforms.all;
+ longDescription = ''
+ diff-so-fancy builds on the good-lookin' output of git contrib's
+ diff-highlight to upgrade your diffs' appearances.
+ '';
+ maintainers = with maintainers; [ fpletz ];
+ };
+}
diff --git a/pkgs/simple/disko.nix b/pkgs/simple/disko.nix
new file mode 100644
index 0000000..de8f1df
--- /dev/null
+++ b/pkgs/simple/disko.nix
@@ -0,0 +1,13 @@
+{ fetchgit }:
+
+let
+ src = fetchgit {
+ url = https://cgit.krebsco.de/disko;
+ rev = "16cd458af06d3caf687eb7d80ca3df26b71fe28c";
+ sha256 = "16cd458af06d3caf687eb7d80ca3df26b71fe28c";
+ };
+in
+
+{
+ lib = import "${src}/lib";
+}
diff --git a/pkgs/simple/editor-input.nix b/pkgs/simple/editor-input.nix
new file mode 100644
index 0000000..931179a
--- /dev/null
+++ b/pkgs/simple/editor-input.nix
@@ -0,0 +1,18 @@
+{ pkgs }:
+pkgs.writeDashBin "editor-input" ''
+ exec \
+ ${pkgs.utillinux}/bin/setsid -f \
+ ${pkgs.with-tmpdir}/bin/with-tmpdir -t editor-input.XXXXXXXX \
+ ${pkgs.writeDash "editor-input.sh" ''
+ f=$TMPDIR/input
+ ${pkgs.rxvt_unicode}/bin/urxvt -name editor-input-urxvt -e \
+ ${pkgs.vim}/bin/vim --cmd ':set noeol binary' -c startinsert "$f"
+ if test -e "$f"; then
+ ${pkgs.xsel}/bin/xsel -ip < "$f"
+ ${pkgs.xsel}/bin/xsel -ib < "$f"
+ ${pkgs.xdotool}/bin/xdotool key --clearmodifiers shift+Insert
+ ${pkgs.xsel}/bin/xsel -dp
+ ${pkgs.xsel}/bin/xsel -db
+ fi
+ ''}
+''
diff --git a/pkgs/simple/ff.nix b/pkgs/simple/ff.nix
new file mode 100644
index 0000000..b6022c6
--- /dev/null
+++ b/pkgs/simple/ff.nix
@@ -0,0 +1,8 @@
+{ pkgs }:
+
+pkgs.writeDashBin "ff" ''
+ case $TOUCHSCREEN in 1)
+ export MOZ_USE_XINPUT2=1
+ esac
+ exec ${pkgs.firefox}/bin/firefox "$@"
+''
diff --git a/pkgs/simple/field.nix b/pkgs/simple/field.nix
new file mode 100644
index 0000000..7136239
--- /dev/null
+++ b/pkgs/simple/field.nix
@@ -0,0 +1,6 @@
+{ gawk, writeDashBin }:
+
+writeDashBin "field" ''
+ set -u
+ exec ${gawk}/bin/awk -v n="$1" '{print$n}'
+''
diff --git a/pkgs/simple/flameshot-once-tv.nix b/pkgs/simple/flameshot-once-tv.nix
new file mode 100644
index 0000000..e3a9f9a
--- /dev/null
+++ b/pkgs/simple/flameshot-once-tv.nix
@@ -0,0 +1,48 @@
+{ pkgs }:
+
+pkgs.flameshot-once.override {
+ name = "flameshot-once-tv";
+ config.imgur.enable = true;
+ config.imgur.createUrl = "http://ni.r/image";
+ config.imgur.deleteUrl = "http://ni.r/image/delete/%1";
+ config.imgur.xdg-open.browser = "/etc/profiles/per-user/tv/bin/cr";
+ config.settings.General = {
+ autoCloseIdleDaemon = true;
+ buttons = [
+ "TYPE_ARROW"
+ "TYPE_CIRCLE"
+ "TYPE_CIRCLECOUNT"
+ "TYPE_COPY"
+ "TYPE_DRAWER"
+ "TYPE_IMAGEUPLOADER"
+ "TYPE_MARKER"
+ "TYPE_MOVESELECTION"
+ "TYPE_PENCIL"
+ "TYPE_PIXELATE"
+ "TYPE_RECTANGLE"
+ "TYPE_SAVE"
+ "TYPE_SELECTION"
+ "TYPE_TEXT"
+ ];
+ checkForUpdates = false;
+ contrastOpacity = 220;
+ copyPathAfterSave = true;
+ disabledTrayIcon = true;
+ drawColor = "#E4002B";
+ drawThickness = 8;
+ filenamePattern = "%FT%T%z_flameshot";
+ fontFamily = "iosevka tv 2";
+ savePath = "/tmp";
+ savePathFixed = true;
+ showDesktopNotification = false;
+ showHelp = false;
+ showSidePanelButton = false;
+ showStartupLaunchMessage = false;
+ squareMagnifier = true;
+ uploadWithoutConfirmation = true;
+ };
+ config.settings.Shortcuts = {
+ TYPE_COPY = "Return";
+ TYPE_TOGGLE_PANEL = "`";
+ };
+}
diff --git a/pkgs/simple/font-size-alacritty.nix b/pkgs/simple/font-size-alacritty.nix
new file mode 100644
index 0000000..d37f0f0
--- /dev/null
+++ b/pkgs/simple/font-size-alacritty.nix
@@ -0,0 +1,67 @@
+{ pkgs }:
+
+pkgs.writeDashBin "font-size-alacritty" ''
+ # usage: font-size-alacritty (+N|-N|=N)
+ # Increase by, decrease by, or set font size to the value N.
+
+ set -efu
+
+ min_size=5
+
+ op=''${1%%[0-9]*}
+ op=''${op:-=}
+
+ value=''${1#[=+-]}
+
+ window_id=$(${pkgs.xdotool}/bin/xdotool getactivewindow)
+
+ current_size=$(
+ ${pkgs.xorg.xprop}/bin/xprop -notype -id $window_id FONT_SIZE |
+ ${pkgs.gnused}/bin/sed -rn 's/.* = ([0-9]+)$/\1/p'
+ )
+
+ # usage: set_font_size WINDOW_ID FONT_SIZE
+ set_font_size() {
+ ${pkgs.alacritty}/bin/alacritty msg config -w $1 font.size=$2
+ ${pkgs.xorg.xprop}/bin/xprop -id $1 -f FONT_SIZE 32c -set FONT_SIZE $2
+ }
+
+ # usage: reset_font_size WINDOW_ID
+ reset_font_size() {
+ ${pkgs.alacritty}/bin/alacritty msg config -w $1 font.size=$min_size
+ ${pkgs.xorg.xprop}/bin/xprop -id $1 -remove FONT_SIZE
+ }
+
+ # usage: make_next_size
+ make_next_size() {
+ case $op in
+ -) next_size=$(expr $current_size - $value) ;;
+ =) next_size=$value ;;
+ +)
+ next_size=$(expr $current_size + $value)
+ test $next_size -ge $min_size || next_size=$min_size
+ ;;
+ esac
+ }
+
+ if test -z "$current_size"; then
+ current_size=0
+ make_next_size
+ if test $next_size -ge $min_size; then
+ ${pkgs.alacritty}/bin/alacritty msg config -w $window_id \
+ font.normal.family='Input Mono' \
+ font.normal.style=Condensed \
+ font.bold.family='Input Mono' \
+ font.bold.style=Bold
+ set_font_size $window_id $next_size
+ fi
+ else
+ make_next_size
+ if test $next_size -ge $min_size; then
+ set_font_size $window_id $next_size
+ else
+ ${pkgs.alacritty}/bin/alacritty msg config -w $window_id -r
+ reset_font_size $window_id
+ fi
+ fi
+''
diff --git a/pkgs/simple/fzmenu/bin/otpmenu b/pkgs/simple/fzmenu/bin/otpmenu
new file mode 100755
index 0000000..273a408
--- /dev/null
+++ b/pkgs/simple/fzmenu/bin/otpmenu
@@ -0,0 +1,44 @@
+#! /bin/sh
+set -efu
+
+#PATH=
+
+case ${FZMENU_PHASE-0} in
+ 0)
+ export FZMENU_PHASE=1
+ exec setsid -f terminal dash "$0"
+ ;;
+ 1)
+ if result=$(
+ PASSWORD_STORE_DIR=${PASSWORD_STORE_DIR-$HOME/.password-store}
+ FZF_DEFAULT_OPTS=${FZMENU_FZF_DEFAULT_OPTS-}
+ if test -n "$FZF_DEFAULT_OPTS"; then
+ export FZF_DEFAULT_OPTS
+ fi
+ find -L "$PASSWORD_STORE_DIR" -type f -name 'otp.gpg' |
+ awk -F / -v PASSWORD_STORE_DIR="$PASSWORD_STORE_DIR" '
+ { n = length(PASSWORD_STORE_DIR "/") }
+ $NF == "otp.gpg" {
+ print substr($0, 1 + n, length($0)-length("/otp.gpg")-n)
+ }
+ ' |
+ exec fzf \
+ --history=/dev/null \
+ --no-sort \
+ --prompt='OTP: ' \
+ )
+ then
+ export FZMENU_PHASE=2
+ export FZMENU_RESULT="$result"
+ setsid -f "$0"
+ fi
+ ;;
+ 2)
+ pass=$(pass otp code "$FZMENU_RESULT/otp")
+ printf %s "$pass" |
+ xdotool type -f -
+ ;;
+ *)
+ echo "$0: error: bad phase: $FZMENU_PHASE" >&2
+ exit -1
+esac
diff --git a/pkgs/simple/fzmenu/bin/passmenu b/pkgs/simple/fzmenu/bin/passmenu
new file mode 100755
index 0000000..76153f5
--- /dev/null
+++ b/pkgs/simple/fzmenu/bin/passmenu
@@ -0,0 +1,45 @@
+#! /bin/sh
+set -efu
+
+#PATH=
+
+case ${FZMENU_PHASE-0} in
+ 0)
+ export FZMENU_PHASE=1
+ exec setsid -f terminal dash "$0"
+ ;;
+ 1)
+ if result=$(
+ PASSWORD_STORE_DIR=${PASSWORD_STORE_DIR-$HOME/.password-store}
+ FZF_DEFAULT_OPTS=${FZMENU_FZF_DEFAULT_OPTS-}
+ if test -n "$FZF_DEFAULT_OPTS"; then
+ export FZF_DEFAULT_OPTS
+ fi
+ find -L "$PASSWORD_STORE_DIR" -type f -name '*.gpg' |
+ awk -F / -v PASSWORD_STORE_DIR="$PASSWORD_STORE_DIR" '
+ { n = length(PASSWORD_STORE_DIR "/") }
+ $NF == "otp.gpg" { next }
+ /.*\.gpg$/ {
+ print substr($0, 1 + n, length($0)-length(".gpg")-n)
+ }
+ ' |
+ exec fzf \
+ --history=/dev/null \
+ --no-sort \
+ --prompt='pass: ' \
+ )
+ then
+ export FZMENU_PHASE=2
+ export FZMENU_RESULT="$result"
+ setsid -f "$0"
+ fi
+ ;;
+ 2)
+ pass=$(pass show "$FZMENU_RESULT")
+ printf %s "$pass" |
+ xdotool type -f -
+ ;;
+ *)
+ echo "$0: error: bad phase: $FZMENU_PHASE" >&2
+ exit -1
+esac
diff --git a/pkgs/simple/fzmenu/default.nix b/pkgs/simple/fzmenu/default.nix
new file mode 100644
index 0000000..1a285ee
--- /dev/null
+++ b/pkgs/simple/fzmenu/default.nix
@@ -0,0 +1,50 @@
+{ lib, pkgs, stdenv }:
+
+let
+ terminal = pkgs.writeDashBin "terminal" ''
+ # usage: terminal COMMAND [ARGS...]
+ exec ${pkgs.alacritty-tv}/bin/alacritty \
+ --profile=fzmenu \
+ --class AlacrittyFzmenuFloat \
+ -e "$@"
+ '';
+in
+
+pkgs.runCommand "fzmenu" {
+} /* sh */ ''
+ mkdir $out
+
+ cp -r ${./bin} $out/bin
+
+ substituteInPlace $out/bin/otpmenu \
+ --replace '#! /bin/sh' '#! ${pkgs.dash}/bin/dash' \
+ --replace '#PATH=' PATH=${lib.makeBinPath [
+ pkgs.coreutils
+ pkgs.dash
+ pkgs.findutils
+ pkgs.fzf
+ pkgs.gawk
+ (pkgs.pass.withExtensions (ext: [
+ ext.pass-otp
+ ]))
+ pkgs.utillinux
+ pkgs.xdotool
+ terminal
+ ]}
+
+ substituteInPlace $out/bin/passmenu \
+ --replace '#! /bin/sh' '#! ${pkgs.dash}/bin/dash' \
+ --replace '#PATH=' PATH=${lib.makeBinPath [
+ pkgs.coreutils
+ pkgs.dash
+ pkgs.findutils
+ pkgs.fzf
+ pkgs.gawk
+ (pkgs.pass.withExtensions (ext: [
+ ext.pass-otp
+ ]))
+ pkgs.utillinux
+ pkgs.xdotool
+ terminal
+ ]}
+''
diff --git a/pkgs/simple/hc.nix b/pkgs/simple/hc.nix
new file mode 100644
index 0000000..086445e
--- /dev/null
+++ b/pkgs/simple/hc.nix
@@ -0,0 +1,39 @@
+{ fetchgit, lib, makeWrapper, stdenv
+, coreutils, findutils, gawk, gnugrep, qrencode, texlive, utillinux, zbar
+}:
+
+stdenv.mkDerivation rec {
+ name = "hc-${meta.version}";
+
+ src = fetchgit {
+ url = "https://cgit.krebsco.de/hc";
+ rev = "refs/tags/v${meta.version}";
+ sha256 = "09349gja22p0j3xs082kp0fnaaada14bafszn4r3q7rg1id2slfb";
+ };
+
+ nativeBuildInputs = [ makeWrapper ];
+
+ buildPhase = null;
+
+ installPhase = ''
+ mkdir -p $out/bin
+
+ cp $src/bin/hc $out/bin/hc
+
+ wrapProgram $out/bin/hc \
+ --prefix PATH : ${lib.makeBinPath [
+ coreutils
+ findutils
+ gawk
+ gnugrep
+ qrencode
+ texlive.combined.scheme-full
+ utillinux
+ zbar
+ ]}
+ '';
+
+ meta = {
+ version = "1.0.0";
+ };
+}
diff --git a/pkgs/simple/iosevka-tv-1.nix b/pkgs/simple/iosevka-tv-1.nix
new file mode 100644
index 0000000..0f8b4d4
--- /dev/null
+++ b/pkgs/simple/iosevka-tv-1.nix
@@ -0,0 +1,18 @@
+{ pkgs }:
+
+pkgs.iosevka.override {
+ # https://typeof.net/Iosevka/customizer
+ privateBuildPlan = {
+ family = "iosevka tv 1";
+ spacing = "term";
+ serifs = "sans";
+ export-glyph-names = true;
+ no-ligation = true;
+ no-cv-ss = false;
+
+ widths.normal.shape = 600;
+ widths.normal.menu = 5;
+ widths.normal.css = "normal";
+ };
+ set = "tv-1";
+}
diff --git a/pkgs/simple/iosevka-tv-2.nix b/pkgs/simple/iosevka-tv-2.nix
new file mode 100644
index 0000000..888ba6a
--- /dev/null
+++ b/pkgs/simple/iosevka-tv-2.nix
@@ -0,0 +1,20 @@
+{ pkgs }:
+
+pkgs.iosevka.override {
+ # https://typeof.net/Iosevka/customizer
+ privateBuildPlan = {
+ family = "iosevka tv 2";
+ spacing = "term";
+ serifs = "sans";
+ export-glyph-names = true;
+ no-ligation = true;
+ no-cv-ss = false;
+
+ variants.inherits = "ss10";
+
+ widths.normal.shape = 600;
+ widths.normal.menu = 5;
+ widths.normal.css = "normal";
+ };
+ set = "tv-2";
+}
diff --git a/pkgs/simple/libinput-tv.nix b/pkgs/simple/libinput-tv.nix
new file mode 100644
index 0000000..6f08689
--- /dev/null
+++ b/pkgs/simple/libinput-tv.nix
@@ -0,0 +1,11 @@
+{ pkgs }:
+
+pkgs.libinput.overrideAttrs (old: {
+ patches = old.patches or [] ++ [
+ (pkgs.fetchurl {
+ name = "libinput-winmax2.patch";
+ url = "https://github.com/4z3/libinput/commit/2d0ff41.patch";
+ sha256 = "0ipsxzjf98g9w2m163gp49zl14wbxs84s0psdnvk7wfiivgcnm1f";
+ })
+ ];
+})
diff --git a/pkgs/simple/mpvterm/default.nix b/pkgs/simple/mpvterm/default.nix
new file mode 100644
index 0000000..66ad08a
--- /dev/null
+++ b/pkgs/simple/mpvterm/default.nix
@@ -0,0 +1,8 @@
+{ pkgs }:
+
+pkgs.mpv-unwrapped.overrideAttrs (old: rec {
+ pname = "mpvterm";
+ patches = old.patches or [] ++ [
+ ./mpvterm.patch
+ ];
+})
diff --git a/pkgs/simple/mpvterm/mpvterm.patch b/pkgs/simple/mpvterm/mpvterm.patch
new file mode 100644
index 0000000..1263688
--- /dev/null
+++ b/pkgs/simple/mpvterm/mpvterm.patch
@@ -0,0 +1,146 @@
+commit 5ded4dac370ce5d8d727c5d3891448f942edbfdf
+Author: tv <tv@krebsco.de>
+Date: Sat Feb 27 22:54:55 2021 +0100
+
+ x11: add input forwarding support
+
+diff --git a/video/out/x11_common.c b/video/out/x11_common.c
+index ac551fae8e..2e95451d7f 100644
+--- a/video/out/x11_common.c
++++ b/video/out/x11_common.c
+@@ -25,6 +25,10 @@
+ #include <string.h>
+ #include <assert.h>
+
++#include <stdarg.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++
+ #include <X11/Xmd.h>
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+@@ -1097,6 +1101,73 @@ static void release_all_keys(struct vo *vo)
+ x11->win_drag_button1_down = false;
+ }
+
++
++#define FORWARD_START 1
++#define FORWARD_READY 2
++#define FORWARD_ERROR 3
++static int forward_state = FORWARD_START;
++static int forward_fd, forward_len;
++static struct sockaddr_un forward_un;
++static char forward_buf[BUFSIZ];
++
++static void forward_start(void) {
++ const char *socket_path = getenv("FORWARD_SOCKET");
++ if (socket_path == NULL) {
++ fprintf(stderr, "forward_start: environment variable FORWARD_SOCKET not set\n");
++ forward_state = FORWARD_ERROR;
++ return;
++ }
++
++ if ((forward_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
++ perror("socket");
++ } else {
++ memset(&forward_un, 0, sizeof(forward_un));
++ forward_un.sun_family = AF_UNIX;
++ strcpy(forward_un.sun_path, socket_path);
++ forward_len = offsetof(struct sockaddr_un, sun_path) + strlen(socket_path);
++ forward_state = FORWARD_READY;
++ }
++}
++static void forward_send(const char *fmt, ...) {
++ if (forward_state != FORWARD_READY) return;
++
++ va_list argp;
++ va_start(argp, fmt);
++ int n1 = vsnprintf(forward_buf, BUFSIZ, fmt, argp);
++ if (n1 < BUFSIZ + 1) {
++ forward_buf[n1++] = '\n';
++ forward_buf[n1] = '\0';
++ int n2 = sendto(forward_fd, forward_buf, n1, 0, (struct sockaddr *)&forward_un, forward_len);
++ if (n2 < 0) {
++ perror("sendto");
++ }
++ }
++}
++static const char *forward_keyname(KeySym keySym) {
++ const char *name;
++ if (keySym == NoSymbol) {
++ name = "NoSymbol";
++ } else if (!(name = XKeysymToString(keySym))) {
++ name = "NoName";
++ }
++ return name;
++}
++static void forward_keydown(KeySym keySym) {
++ forward_send("xdotool keydown %s", forward_keyname(keySym));
++}
++static void forward_keyup(KeySym keySym) {
++ forward_send("xdotool keyup %s", forward_keyname(keySym));
++}
++static void forward_mousedown(int button) {
++ forward_send("xdotool mousedown %d", button);
++}
++static void forward_mouseup(int button) {
++ forward_send("xdotool mouseup %d", button);
++}
++static void forward_mousemove(int x, int y) {
++ forward_send("xdotool mousemove %d %d", x, y);
++}
++
+ void vo_x11_check_events(struct vo *vo)
+ {
+ struct vo_x11_state *x11 = vo->x11;
+@@ -1105,6 +1176,10 @@ void vo_x11_check_events(struct vo *vo)
+
+ xscreensaver_heartbeat(vo->x11);
+
++ if (forward_state == FORWARD_START) {
++ forward_start();
++ }
++
+ while (XPending(display)) {
+ XNextEvent(display, &Event);
+ MP_TRACE(x11, "XEvent: %d\n", Event.type);
+@@ -1146,6 +1221,7 @@ void vo_x11_check_events(struct vo *vo)
+ if (mpkey)
+ mp_input_put_key(x11->input_ctx, mpkey | modifiers);
+ }
++ forward_keydown(XLookupKeysym(&Event.xkey, 0));
+ break;
+ }
+ case FocusIn:
+@@ -1161,6 +1237,7 @@ void vo_x11_check_events(struct vo *vo)
+ break;
+ case KeyRelease:
+ release_all_keys(vo);
++ forward_keyup(XLookupKeysym(&Event.xkey, 0));
+ break;
+ case MotionNotify:
+ if (x11->win_drag_button1_down && !x11->fs &&
+@@ -1182,6 +1259,7 @@ void vo_x11_check_events(struct vo *vo)
+ Event.xmotion.y);
+ }
+ x11->win_drag_button1_down = false;
++ forward_mousemove(Event.xmotion.x, Event.xmotion.y);
+ break;
+ case LeaveNotify:
+ if (Event.xcrossing.mode != NotifyNormal)
+@@ -1204,6 +1282,7 @@ void vo_x11_check_events(struct vo *vo)
+ get_mods(Event.xbutton.state) | MP_KEY_STATE_DOWN);
+ long msg[4] = {XEMBED_REQUEST_FOCUS};
+ vo_x11_xembed_send_message(x11, msg);
++ forward_mousedown(Event.xbutton.button);
+ break;
+ case ButtonRelease:
+ if (Event.xbutton.button - 1 >= MP_KEY_MOUSE_BTN_COUNT)
+@@ -1213,6 +1292,7 @@ void vo_x11_check_events(struct vo *vo)
+ mp_input_put_key(x11->input_ctx,
+ (MP_MBTN_BASE + Event.xbutton.button - 1) |
+ get_mods(Event.xbutton.state) | MP_KEY_STATE_UP);
++ forward_mouseup(Event.xbutton.button);
+ break;
+ case MapNotify:
+ x11->window_hidden = false;
diff --git a/pkgs/simple/pinentry-urxvt/default.nix b/pkgs/simple/pinentry-urxvt/default.nix
new file mode 100644
index 0000000..7363f26
--- /dev/null
+++ b/pkgs/simple/pinentry-urxvt/default.nix
@@ -0,0 +1,127 @@
+{ lib, pkgs, ... }@args:
+
+let
+ mylib = import ../../../lib/pure.nix {
+ inherit lib;
+ };
+
+ # config cannot be declared in the input attribute set because that would
+ # cause callPackage to inject the wrong config. Instead, get it from ...
+ # via args.
+ config = args.config or {};
+
+ cfg = eval.config;
+
+ eval = lib.evalModules {
+ modules = lib.singleton {
+ _file = toString ./default.nix;
+ imports = lib.singleton config;
+ options = {
+ appName = lib.mkOption {
+ default = "pinentry-urxvt";
+ type = lib.types.str;
+ };
+ display = lib.mkOption {
+ default = null;
+ type = lib.types.nullOr lib.types.str;
+ };
+ xwud.className = lib.mkOption {
+ default = "PinentryUrxvtXwudFloat";
+ type = lib.types.str;
+ };
+ };
+ };
+ };
+
+
+in
+
+ # pinentry-urxvt - A mechanism for PIN entry utilizing rxvt-unicode
+ #
+ # This spawns a PIN entry terminal on top of a tinted screenshot of the
+ # current display's root window. The display for spawning the terminal can
+ # be predefined, in which case both the current and the predefined display
+ # will show the screenshot.
+ #
+ # The purpose of the screenshot, aside from looking nice, is to prevent entry
+ # of the PIN into the wrong window, e.g. by accidentally moving the cursor
+ # while typing. If necessary, the screenshot can be closed by sending 'q',
+ # 'Q', or ctrl-c while its focused.
+ #
+ pkgs.write "pinentry-urxvt" {
+ "/bin/pinentry".link = pkgs.writeDash "pinentry-urxvt-wrapper" ''
+ set -efu
+
+ trap cleanup EXIT
+
+ cleanup() {
+ ${pkgs.utillinux}/bin/kill -- $(${pkgs.coreutils}/bin/cat "$displayers")
+ rm "$displayers"
+ rm "$screenshot"
+ }
+
+ displayers=$(${pkgs.coreutils}/bin/mktemp -t pinentry-urxvt.$$.displayers.XXXXXXXX)
+ screenshot=$(${pkgs.coreutils}/bin/mktemp -t pinentry-urxvt.$$.screenshot.XXXXXXXX)
+
+ ${pkgs.xorg.xwd}/bin/xwd -root |
+ ${pkgs.imagemagick}/bin/convert xwd:- -fill \#424242 -colorize 80% xwd:"$screenshot"
+
+ display_screenshot() {
+ ${pkgs.exec "pinentry-urxvt.display_screenshot" {
+ filename = "${pkgs.xorg.xwud}/bin/xwud";
+ argv = [
+ cfg.xwud.className
+ "-noclick"
+ ];
+ }} < "$screenshot" &
+ wait_for_screenshot $! && echo $! >>"$displayers"
+ }
+
+ # Wait for the xwud window by trying to intercept the call to munmap().
+ # If it cannot be intercepted within 0.1s, assume that attaching strace
+ # wasn't fast enough or xwud doesn't call munmap() anymore. In either
+ # case fall back to search the window by class name, assuming there can
+ # be only one per display.
+ wait_for_screenshot() {
+ if ! \
+ ${pkgs.coreutils}/bin/timeout 0.1 \
+ ${pkgs.strace}/bin/strace -p "$1" -e munmap 2>&1 |
+ read -r _
+ then
+ until ${pkgs.xdotool}/bin/xdotool search \
+ --classname ${mylib.shell.escape cfg.xwud.className}
+ do
+ ${pkgs.coreutils}/bin/sleep 0.1
+ done
+ fi
+ }
+
+ display_screenshot
+
+ ${lib.optionalString (cfg.display != null) /* sh */ ''
+ if test "$DISPLAY" != ${mylib.shell.escape cfg.display}; then
+ export DISPLAY=${mylib.shell.escape cfg.display}
+ display_screenshot
+ fi
+ ''}
+
+ exec 3<&0 4>&1 5>&2
+ ${pkgs.rxvt_unicode}/bin/urxvt \
+ -name ${mylib.shell.escape cfg.appName} \
+ -e ${pkgs.writeDash "pinentry-urxvt-tty" ''
+ set -efu
+ exec 2>&5
+ TTY=$(${pkgs.coreutils}/bin/tty)
+ while read -r line <&3; do
+ case $line in
+ 'OPTION ttyname='*)
+ echo "OPTION ttyname=$TTY"
+ ;;
+ *)
+ echo "$line"
+ esac
+ done | ${pkgs.pinentry.tty}/bin/pinentry-tty "$@" >&4
+ ''} \
+ "$@"
+ '';
+ }
diff --git a/pkgs/simple/q/default.nix b/pkgs/simple/q/default.nix
new file mode 100644
index 0000000..03e924e
--- /dev/null
+++ b/pkgs/simple/q/default.nix
@@ -0,0 +1,176 @@
+{ lib
+, pkgs
+}:
+let
+ mylib = import ../../../lib/pure.nix {
+ inherit lib;
+ };
+
+ q-cal = let
+
+ # Maximum width of cal's output.
+ calwidth = 23;
+
+ # Number of space characters between two calendars.
+ hspace = 2;
+
+ # Return number of columns required to print n calenders side by side.
+ need_width = n: assert n >= 1; n * calwidth + (n - 1) * hspace;
+
+ in /* sh */ ''
+ cols=$(${pkgs.ncurses}/bin/tput cols)
+ if test $cols -ge ${toString (need_width 3)}; then
+ ${pkgs.utillinux}/bin/cal --color=always -mw3
+ elif test $cols -ge ${toString (need_width 2)}; then
+ ${pkgs.utillinux}/bin/cal --color=always -mw -n 2
+ elif test $cols -ge ${toString (need_width 1)}; then
+ ${pkgs.utillinux}/bin/cal --color=always -mw1
+ else
+ :
+ fi |
+ ${pkgs.gnused}/bin/sed -r '
+ # dim week numbers
+ s/((^| )[ 1-5][0-9])(( ..| \[7m..\[27m){7})/\1\3/g
+ # dim month and day names
+ s/^ *[A-Z].*/&/
+ # highlight current date
+ s/\[7m//
+ s/\[27m//
+ '
+ '';
+
+ q-isodate = TZ: color: /* sh */ ''
+ TZ=${mylib.shell.escape TZ} \
+ ${pkgs.coreutils}/bin/date \
+ '+%Y-%m-%dT[;'${mylib.shell.escape color}'m%H:%M:%S%:z'
+ '';
+
+ q-deudate = q-isodate "Europe/Berlin" "38;5;085";
+
+ # Singapore's red is #ED2E38
+ q-sgtdate = q-isodate "Asia/Singapore" "38;2;237;46;56";
+
+ q-thadate = q-isodate "Asia/Bangkok" "38;5;226";
+
+ q-utcdate = q-isodate "UTC" "38;5;065";
+
+ q-gitdir = /* sh */ ''
+ if test -d .git; then
+ #git status --porcelain
+ branch=$(
+ ${pkgs.git}/bin/git branch \
+ | ${pkgs.gnused}/bin/sed -rn 's/^\* (.*)/\1/p'
+ )
+ echo "± $LOGNAME@''${HOSTNAME-$(${pkgs.nettools}/bin/hostname)}:$PWD .git $branch"
+ fi
+ '';
+
+ q-intel_backlight = /* sh */ ''
+ cd /sys/class/backlight/intel_backlight
+ </dev/null exec ${pkgs.gawk}/bin/awk '
+ END {
+ getline actual_brightness < "actual_brightness"
+ getline max_brightness < "max_brightness"
+ getline brightness < "brightness"
+ printf "intel_backlight %d%% %d/%d\n" \
+ , actual_brightness / max_brightness * 100 \
+ , actual_brightness \
+ , max_brightness
+ }
+ '
+ '';
+
+ q-virtualization = /* sh */ ''
+ echo "VT: $(${pkgs.systemd}/bin/systemd-detect-virt)"
+ '';
+
+ q-net = /* sh */ ''
+ for dev in $(
+ ${pkgs.iproute}/bin/ip a |
+ ${pkgs.gnused}/bin/sed -rn 's/^[0-9]+: ([^:]+):.*/\1/p' |
+ ${pkgs.gnugrep}/bin/grep -Ev '^(lo|retiolum|wiregrill)$'
+ # TODO wiregrill ping ni.w, retiolum ping ni.r
+ ); do
+ {
+ inet=$(${pkgs.iproute}/bin/ip addr show $dev \
+ | ${pkgs.gnused}/bin/sed -n '
+ s/.*inet \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p
+ ')
+ ssid=$(${pkgs.iw}/bin/iw dev $dev link \
+ | ${pkgs.gnused}/bin/sed -n '
+ s/.*\tSSID: \(.*\)/\1/p
+ ')
+ latency=$(
+ /run/wrappers/bin/ping -W .25 -c 1 -I "$dev" ni.i 2>&1 |
+ ${pkgs.gnused}/bin/sed -rn '
+ s/.*time=([0-9.]+).*/online ni=\1/p
+ s/.*Network is unreachable.*/offline/p
+ s/.*100% packet loss.*/offline/p
+ '
+ )
+ echo "$dev''${inet:+ $inet}''${ssid:+ $ssid} $latency"
+ } &
+ done
+ wait
+ '';
+
+ q-thermal_zone = /* sh */ ''
+ for i in /sys/class/thermal/thermal_zone*; do
+ type=$(${pkgs.coreutils}/bin/cat $i/type)
+ temp=$(${pkgs.coreutils}/bin/cat $i/temp)
+ printf '%s %s°C\n' $type $(echo $temp / 1000 | ${pkgs.bc}/bin/bc)
+ done
+ '';
+
+ q-todo = /* sh */ ''
+ TODO_file=$PWD/TODO
+ if test -e "$TODO_file"; then
+ ${pkgs.jq}/bin/jq -Rrs <"$TODO_file" -f ${pkgs.writeJq "q-todo.jq" ''
+ split("\n") | map(
+ (match("^([0-9]+-\\d{2}-\\d{2})\\s+(.*)$").captures | map(.string))
+ as $captures |
+ ($captures[0] | strptime("%Y-%m-%d") | mktime) as $date |
+ $captures[1] as $text |
+
+ select(now >= $date) |
+
+ ($text | test("\\[URGENT]"; "i")) as $urgent |
+ (if $urgent then "38;5;196" else "38;5;208" end) as $sgr |
+ if $urgent then sub("\\s*\\[URGENT]\\s*"; " "; "i") else . end |
+
+ "\u001b[\($sgr)m\(.)\u001b[m"
+ ) |
+ if length == 0 then "nothing to remind" else .[] end
+ ''}
+ else
+ echo "$TODO_file: no such file or directory"
+ fi
+ '';
+
+in
+# bash needed for <(...)
+pkgs.writeBashBin "q" ''
+ set -eu
+ export PATH=/var/empty
+ ${q-cal}
+ ${q-utcdate}
+ ${q-deudate}
+ ${q-sgtdate}
+ (${q-gitdir}) &
+ (${q-intel_backlight}) &
+ ${pkgs.q-power_supply}/bin/q-power_supply &
+ (${q-virtualization}) &
+ (${q-net}) &
+ (${q-thermal_zone}) &
+ wait
+ if test "$PWD" != "$HOME" && test -e "$HOME/TODO"; then
+ TODO_home_entries=$(cd; (${q-todo}) | ${pkgs.coreutils}/bin/wc -l)
+ if test "$TODO_home_entries" = 1; then
+ TODO_format='There is %d entry in ~/TODO'
+ else
+ TODO_format='There are %d entries in ~/TODO'
+ fi
+ printf "\x1b[38;5;238m$TODO_format\x1b[m\n" "$TODO_home_entries"
+ fi
+ (${q-todo}) || :
+''
diff --git a/pkgs/simple/rox-filer.nix b/pkgs/simple/rox-filer.nix
new file mode 100644
index 0000000..b380bdf
--- /dev/null
+++ b/pkgs/simple/rox-filer.nix
@@ -0,0 +1,95 @@
+{ fetchFromGitLab, lib, stdenv
+, autoconf, pkgconfig, libxml2, libSM, shared-mime-info
+, libxslt, docbook_xml_dtd_412, docbook_xsl
+, gtk ? gtk2, gtk2
+}:
+
+stdenv.mkDerivation {
+ pname = "rox-filer";
+ version = "2.11-tv";
+
+ src = fetchFromGitLab {
+ owner = "seirios";
+ repo = "rox-filer";
+ rev = "3c3ad5d85a1ab548574bf450f730886b60092587";
+ sha256 = "0h743zpx1v9rrsaxn0q3nwpq8wkjf6icgzrg8jpqldsphw3ygkhr";
+ };
+
+ nativeBuildInputs = [
+ autoconf
+ docbook_xsl
+ libxslt
+ pkgconfig
+ ];
+
+ buildInputs = [ libxml2 gtk shared-mime-info libSM ];
+
+ # go to the source directory after unpacking the sources
+ setSourceRoot = "export sourceRoot=source/ROX-Filer";
+
+ # patch the main.c to disable the lookup of the APP_DIR environment variable,
+ # which is used to lookup the location for certain images when rox-filer
+ # starts; rather override the location with an absolute path to the directory
+ # where images are stored to prevent having to use a wrapper, which sets the
+ # APP_DIR environment variable prior to starting rox-filer
+ preConfigure = ''
+ (cd src && autoconf)
+ sed -i -e "s:g_strdup(getenv(\"APP_DIR\")):\"$out\":" src/main.c
+ mkdir build
+ cd build
+ '';
+
+ preBuild = ''
+ for f in \
+ ../src/Docs/Manual.xml \
+ ../src/Docs/Manual-fr.xml \
+ ../src/Docs/Manual-it.xml ;
+ do
+ substituteInPlace "$f" \
+ --replace \
+ /usr/share/sgml/docbook/dtd/xml/4.1.2/docbookx.dtd \
+ ${docbook_xml_dtd_412}/xml/dtd/docbook/docbookx.dtd
+ done
+ make -C ../src/Docs MAN=.. || exit 1
+ '';
+
+ configureScript = "../src/configure";
+
+ installPhase = ''
+ mkdir -p "$out"
+ cd ..
+ cp -av Help Messages Options.xml ROX images style.css .DirIcon "$out"
+
+ mkdir -p "$out/share/man/man1"
+ cp -av src/rox.1 "$out/share/man/man1"
+
+ # the main executable
+ mkdir "$out/bin/"
+ cp -v ROX-Filer "$out/bin/rox"
+
+ # mime types
+ mkdir -p "$out/ROX/MIME"
+ cd "$out/ROX/MIME"
+ ln -sv text-x-{diff,patch}.png
+ ln -sv application-x-font-{afm,type1}.png
+ ln -sv application-xml{,-dtd}.png
+ ln -sv application-xml{,-external-parsed-entity}.png
+ ln -sv application-{,rdf+}xml.png
+ ln -sv application-x{ml,-xbel}.png
+ ln -sv application-{x-shell,java}script.png
+ ln -sv application-x-{bzip,xz}-compressed-tar.png
+ ln -sv application-x-{bzip,lzma}-compressed-tar.png
+ ln -sv application-x-{bzip-compressed-tar,lzo}.png
+ ln -sv application-x-{bzip,xz}.png
+ ln -sv application-x-{gzip,lzma}.png
+ ln -sv application-{msword,rtf}.png
+ '';
+
+ meta = with lib; {
+ description = "Fast, lightweight, gtk2 file manager";
+ homepage = "http://rox.sourceforge.net/desktop";
+ license = with licenses; [ gpl2 lgpl2 ];
+ platforms = platforms.linux;
+ maintainers = [ maintainers.eleanor ];
+ };
+}
diff --git a/pkgs/simple/rxvt-unicode-256color-terminfo/default.nix b/pkgs/simple/rxvt-unicode-256color-terminfo/default.nix
new file mode 100644
index 0000000..d2f6f46
--- /dev/null
+++ b/pkgs/simple/rxvt-unicode-256color-terminfo/default.nix
@@ -0,0 +1,16 @@
+# This package is mainly intended for cross-built systems for which we cannot
+# or don't want to build pkgs.rxvt_unicode for some reason.
+#
+# ${./rxvt-unicode-256color.terminfo} was copied from a previously built
+# /run/current-system/sw/share/terminfo/r/rxvt-unicode-256color
+{ runCommand }:
+
+runCommand "rxvt-unicode-256color-terminfo" {} /* sh */ ''
+ mkdir -p $out/nix-support
+ mkdir -p $out/share/terminfo/r
+
+ ln -s ${./rxvt-unicode-256color.terminfo} \
+ $out/share/terminfo/r/rxvt-unicode-256color
+
+ echo "$out" >> $out/nix-support/propagated-user-env-packages
+''
diff --git a/pkgs/simple/rxvt-unicode-256color-terminfo/rxvt-unicode-256color.terminfo b/pkgs/simple/rxvt-unicode-256color-terminfo/rxvt-unicode-256color.terminfo
new file mode 100644
index 0000000..3f43d0d
--- /dev/null
+++ b/pkgs/simple/rxvt-unicode-256color-terminfo/rxvt-unicode-256color.terminfo
Binary files differ
diff --git a/pkgs/simple/stardict/default.nix b/pkgs/simple/stardict/default.nix
new file mode 100644
index 0000000..2135cc0
--- /dev/null
+++ b/pkgs/simple/stardict/default.nix
@@ -0,0 +1,235 @@
+{ lib, pkgs }:
+let
+ classicsDictionaries = {
+ Pape = pkgs.fetchzip {
+ url = "http://tovotu.de/data/stardict/pape_gr-de.zip";
+ sha256 = "1kmbdjqinrcxkc6jdyyrq5rl2wzhnrychyynnh91yhrjwjxlh44k";
+ };
+ Woodhouse = pkgs.fetchzip {
+ url = "https://c.krebsco.de/Woodhouse.zip";
+ sha256 = "1dvnc2679yb048q2f3hr2h34acvhan0n3iir6h9ajlrdzz48mlkq";
+ stripRoot = false;
+ };
+ LSJ = pkgs.fetchzip {
+ url = "https://github.com/nikita-moor/latin-dictionary/releases/download/2020-02-14/LiddellScott1940-stardict.zip";
+ sha256 = "13rprgd9jvnhxk9735c91xr6ywr0j5jiwkjnpm3qpvy93isyjbys";
+ };
+ GreekMorphology = pkgs.fetchzip {
+ url = "https://github.com/latin-dict/Morphologia-Graeca/releases/download/v0.5/morphology-mobile-goldendict.oxia.zip";
+ sha256 = "0m75cppjjjmvv18cs7yh9f4p7ckqzxfznnndgkiw3yrfd50k8p96";
+ };
+ Frisk = pkgs.fetchzip {
+ url = "https://github.com/latin-dict/Frisk1960/releases/download/v1.1/Frisk1960-stardict.zip";
+ sha256 = "1rk5a3n3fpfdcmg4bc5945m88s6ldxql8cjn4jqs33rgklh7n046";
+ };
+ Georges-De-Lat = pkgs.fetchzip {
+ url = "http://tovotu.de/data/stardict/georges_de-lat.zip";
+ sha256 = "1gx4vv64bi9lxw2zgd861j469jvw4f2hhfwy1gglb12id8r7rdrl";
+ };
+ Georges-Lat-De = pkgs.fetchzip { # TODO find out why this does not work with sdcv
+ url = "http://tovotu.de/data/stardict/georges_lat-de.zip";
+ sha256 = "0cc5xipn60anxvq8z2mw53d4gi1k92wbrj9m4ws3g9rh87fmkvgz";
+ };
+ LewisShort = pkgs.fetchzip {
+ url = "https://github.com/latin-dict/LewisShort1879/releases/download/v1.3/LewisShort1879-stardict.zip";
+ sha256 = "1y3ans47iv8bzzb1paimdqvcid8ms04ikjbqy3iw077i2js3qbjk";
+ };
+ DoederleinSynonymes = pkgs.fetchzip {
+ url = "https://github.com/latin-dict/Doederlein1874/releases/download/v1.1/Doederlein1875-stardict.zip";
+ sha256 = "0mhik7gjxl8ncr9g5z2l4pfk60k1c5n0gc1w0cnp2x1v6lqvb57h";
+ };
+ };
+
+ englishGermanDictionaries = {
+ Etymonline = pkgs.fetchzip {
+ url = "http://tovotu.de/data/stardict/etymonline.zip";
+ sha256 = "1bjja3n3layfd08xa1r0a6375dxh5zi6hlv7chkhgnx800cx7hxn";
+ };
+ Roget = builtins.fetchTarball {
+ url = "http://download.huzheng.org/bigdict/stardict-Roget_s_II_The_New_Thesaurus_3th_Ed-2.4.2.tar.bz2";
+ sha256 = "1szyny9497bpyyccf9l5kr3bnw0wvl4cnsd0n1zscxpyzlsrqqbz";
+ };
+ JargonFile = builtins.fetchTarball {
+ url = "http://download.huzheng.org/dict.org/stardict-dictd-jargon-2.4.2.tar.bz2";
+ sha256 = "096phar9qpmm0fnaqv5nz8x9lpxwnfj78g4vjfcfyd7kqp7iqla4";
+ };
+ Oxford-Collocations = builtins.fetchTarball {
+ url = "http://download.huzheng.org/bigdict/stardict-Oxford_Collocations_Dictionary_2nd_Ed-2.4.2.tar.bz2";
+ sha256 = "1zkfs0zxkcn21z2lhcabrs77v4ma9hpv7qm119hpyi1d8ajcw07q";
+ };
+ Langenscheidt-Deu-En = builtins.fetchTarball {
+ url = "http://download.huzheng.org/babylon/german/stardict-Handw_rterbuch_Deutsch_Englisc-2.4.2.tar.bz2";
+ sha256 = "12q9i5azq7ylyrpb6jqbaf1rxalc3kzcwjvbinvb0yabdxb80y30";
+ };
+ Langenscheidt-En-Deu = builtins.fetchTarball {
+ url = "http://download.huzheng.org/babylon/german/stardict-Handw_rterbuch_Englisch_Deutsc-2.4.2.tar.bz2";
+ sha256 = "087b05h155j5ldshfgx91pz81h6ijq2zaqjirg7ma8ig3l96zb59";
+ };
+ Duden_Das_Fremdworterbuch = builtins.fetchTarball {
+ url = "http://download.huzheng.org/babylon/german/stardict-Duden_Das_Fremdworterbuch-2.4.2.tar.bz2";
+ sha256 = "1zrcay54ccl031s6dvjwsah5slhanmjab87d81rxlcy8fx0xd8wq";
+ };
+ Duden_De_De = builtins.fetchTarball {
+ url = "http://download.huzheng.org/babylon/german/stardict-Duden_De_De-2.4.2.tar.bz2";
+ sha256 = "1fhay04w5aaj83axfmla2ql34nb60gb05dgv0k94ig7p8x4yxxlf";
+ };
+ ConciseOED = builtins.fetchTarball {
+ url = "http://download.huzheng.org/bigdict/stardict-Concise_Oxford_English_Dictionary-2.4.2.tar.bz2";
+ sha256 = "19kpcxbhqzpmhi94mp48nalgmsh6s7rsx1gb4kwkhirp2pbjcyl7";
+ };
+ # Duden_Rechtschreibung = builtins.fetchTarball {
+ # url = "http://download.huzheng.org/babylon/german/stardict-Duden_Rechtschreibung-2.4.2.tar.bz2";
+ # sha256 = "0xiprb45s88w62rn8rlbjrsagbiliay9hszsiy20glwabf6zsfji";
+ # };
+ Duden_Synonym = builtins.fetchTarball {
+ url = "http://download.huzheng.org/babylon/german/stardict-Duden_Synonym-2.4.2.tar.bz2";
+ sha256 = "0cx086zvb86bmz7i8vnsch4cj4fb0cp165g4hig4982zakj6f2jd";
+ };
+ # Duden = builtins.fetchTarball {
+ # url = "http://download.huzheng.org/de/stardict-duden-2.4.2.tar.bz2";
+ # sha256 = "049i4ynfqqxykv1nlkyks94mvn14s22qdax5gg7hx1ks5y4xw64j";
+ # };
+ # FreeOnlineDictionaryOfComputing = builtins.fetchTarball {
+ # url = "http://download.huzheng.org/dict.org/stardict-dictd_www.dict.org_foldoc-2.4.2.tar.bz2";
+ # sha256 = "1lw2i8dzxpx929cpgvv0x366dnh4drr10wzqmrhcd0kvwglqawgm";
+ # };
+ };
+
+ sanskritDictionaries = {
+ BoehtlingkRoth = pkgs.fetchzip {
+ url = "https://c.krebsco.de/Bohtlingk-and-Roth-Grosses-Petersburger-Worterbuch.zip";
+ sha256 = "13414a8rgd7hd5ffar6nl68nk3ys60wjkgb7m11hp0ahaasmf6ly";
+ stripRoot = false;
+ };
+ MonierWilliams = pkgs.fetchzip {
+ url = "https://c.krebsco.de/mw-cologne.zip";
+ sha256 = "0p99ybxwxmmd94hf035hvm2hhnfy84av7qq79xf28bh2rbx6s9ng";
+ stripRoot = false;
+ };
+ MonierWilliamsEnglish = pkgs.fetchzip {
+ url = "https://c.krebsco.de/mw-english-sanskrit.zip";
+ sha256 = "09a61hhii4b1m2fkrlh4rm2xnlgwrllh84iypbc6wyj00w9jkl3x";
+ stripRoot = false;
+ };
+ };
+
+ swahiliDictionaries = {
+ vickio = pkgs.fetchzip {
+ url = "http://swahili.vickio.net/files/Swahili-English.zip";
+ sha256 = "0m6wkwc83fcim43ijn17lcsda4clkra587gxaz6m59qd0yfwzakw";
+ stripRoot = false;
+ };
+ };
+
+ makeStardictDataDir = dicts: pkgs.linkFarm "dictionaries" (lib.mapAttrsToList (name: path: { inherit name path; }) dicts);
+
+ sdcvPager = pkgs.writeDash "sdcvPager" ''
+ export PATH=${lib.makeBinPath [pkgs.gnused pkgs.ncurses]}
+ sed "
+ s! style=\"color: #...\"!!g;
+ s!<span class=\"zenoTXSpaced\">\([^<>]*\)</span>!\1!g;
+ s!</\?dictionary[^>]*>!!g;
+ s!<style.*</style>!!g;
+ s!<author>\([^<>]*\)</author>!\1 !g;
+ s!<quote lang=\"\(greek\|la\)\">\([^<>]*\)</quote>!$(tput sitm)\2$(tput sgr0)!g;
+ s!<biblScope>\([^<>]*\)</biblScope>!\1!g;
+ s!<mood>\([^<>]*\)</mood>!$(tput sitm)\1$(tput sgr0)!g;
+ s!<adv>\([^<>]*\)</adv>!$(tput sitm)\1$(tput sgr0)!g;
+ s!<gram[^>]*>\([^<>]*\)</gram>!$(tput sitm)\1$(tput sgr0)!g;
+ s!<bibl_title>\([^<>]*\)</bibl_title>!$(tput sitm)\1$(tput sgr0) !g;
+ s!<hi rend=\"ital\">\([^<>]*\)</hi>!$(tput sitm)\1$(tput sgr0) !g;
+ s!<dict_tr>\([^<>]*\)</dict_tr>!$(tput setaf 3)\1$(tput sgr0)!g;
+ s!<headword>\([^<>]*\)</headword>!$(tput bold)\1$(tput sgr0)\t!g;
+ s!</\?a[^>]*>!!g
+ s!</\?[cp]b[^>]*>!!g
+ s!</\?gramGrp[^>]*>!!g
+ s!</\?lbl[^>]*>!!g
+ s!</\?xr[^>]*>!!g
+ s!</\?pron[^>]*>!!g
+ s!</\?gen[^>]*>!!g
+ s!</\?etym[^>]*>!!g
+ s!<foreign[^>]*>!$(tput sitm)!g
+ s!</foreign[^>]*>!$(tput sgr0)!g
+ s!</\?date[^>]*>!!g
+ s!</\?placeName[^>]*>!!g
+ s!</\?itype[^>]*>!!g
+ s!</\?p>!!g
+ s!<input[^>]*>!!g
+ s!</\?orth[^>]*>!!g
+ s!</\?forename[^>]*>!!g
+ s!</\?persName[^>]*>!!g
+ s!</\?surname[^>]*>!!g
+ s!</\?entryFree[^>]*>!!g
+ s!</\?def[^>]*>!!g
+ s!</\?cit[^>]*>!!g
+ s!</\?pos[^>]*>!!g
+ s!</\?usg[^>]*>!!g
+ s!</\?span>!!g
+ s!<bibl[^>]*>!$(tput setaf 245)!g
+ s!</bibl[^>]*>!$(tput sgr0)!g
+ s/<dt>/$(tput bold)/g;
+ s:</dt>:$(tput sgr0):g;
+ s/<dd>/\n/g;
+ s:</dd>::g;
+ s/<[bB]>/$(tput bold)/g;
+ s:</[bB]>:$(tput sgr0):g;
+ s:<[bB][rR]\s*/\?>:\n:g;
+ s:<[iI]>:$(tput sitm):g;
+ s:</[iI]>:$(tput sgr0):g;
+ s:<[uU]>:$(tput smul):g;
+ s:</[uU]>:$(tput sgr0):g;
+ s:<FONT face=[^>]*>::g;
+ s:</FONT>::g;
+ s!<head>\([^<>]*\)</head>!$(tput bold)\1$(tput sgr0)!g;
+ s!<span lang=\"\(gr\|la\)\">\([^<>]*\)</span>!\2!g
+ s#<div style=\"margin-left:1em\">\(.*\)</div>#\\1#g;
+ s:<font color=\"brown\">\([^<>]*\)</font>:$(tput setaf 3)\\1$(tput sgr0):g;
+ s:<font color=\"blue\">\([^<>]*\)</font>:$(tput setaf 4)\\1$(tput sgr0):g;
+ s:<font color=\"red\">\([^<>]*\)</font>:$(tput setaf 1)\\1$(tput sgr0):g;
+ s:<font color=\"darkviolet\">\([^<>]*\)</font>:$(tput setaf 5)\\1$(tput sgr0):g;
+ s:<font color=\"#a0a\">\([^<>]*\)</font>:$(tput bold)\1$(tput sgr0):g
+ s:<font color=\"#838\">\([^<>]*\)</font>:$(tput setaf 3)\1$(tput sgr0):g
+ s:&#x27;:':g
+ s:&lt;:<:g
+ s:&gt;:>:g
+ s:<font color=\"#007000\">\([^<>]*\)</font>:$(tput setaf 2)\\1$(tput sgr0):g;
+ s:<font color=\"#007000\">\([^<>]*\)</font>:$(tput setaf 2)\\1$(tput sgr0):g;
+ s:<font color=#000099>\([^<>]*\)</font>:$(tput setaf 4)\\1$(tput sgr0):g;
+ s:<font color=0000FF>\([^<>]*\)</font>:$(tput bold)\\1$(tput sgr0):g;
+ s:<IMG src=\"223E9A06.bmp\"[^>]*>:ː:g;
+ s:<IMG src=\"502F5DDA.bmp\"[^>]*>::g;
+ s!</\?TABLE>!!g
+ s!</\?TR[^>]*>!!g
+ s!</\?TD>!!g
+ s!</\?FONT[^>]*>!!g
+ s!</\?A[^>]*>!!g
+ s!<SPAN class=\"bsptext\">\([^<>]*\)</SPAN>!$(tput setaf 245)\1$(tput sgr0)!g
+ s!</\?SPAN[^>]*>!!g
+ s! +! !g;
+ s!<div part=\"[^\"]*\">!\n\n&!g
+ s!<sense n=\"\([^\"]*\)\"!\n$(tput setaf 5)\1.$(tput sgr0) &!g;
+ s!</\?sense[^>]*>!!g
+ s!</\?div[^>]*>!!g
+ s!<span lang=\"gr\">!!g # unbalanced in Frisk
+ s!^\s*[0-9])!$(tput setaf 5)&$(tput sgr0)!g
+ s#^\(-->.*\)\$#$(tput bold)\1$(tput sgr0)#
+ "
+ '';
+
+ mkDictBin = name: dicts:
+ pkgs.writers.writeDashBin name ''
+ set -efu
+ export SDCV_PAGER=${toString sdcvPager}
+ exec ${pkgs.sdcv}/bin/sdcv --data-dir ${makeStardictDataDir dicts} "$@"
+ '';
+in
+
+pkgs.symlinkJoin {
+ name = "stardict";
+ paths = [
+ (mkDictBin "sd-classics" classicsDictionaries)
+ (mkDictBin "sd-sanskrit" sanskritDictionaries)
+ (mkDictBin "sd-swahili" swahiliDictionaries)
+ (mkDictBin "sd" englishGermanDictionaries)
+ ];
+}
diff --git a/pkgs/simple/viljetic-pages/default.nix b/pkgs/simple/viljetic-pages/default.nix
new file mode 100644
index 0000000..ee07c92
--- /dev/null
+++ b/pkgs/simple/viljetic-pages/default.nix
@@ -0,0 +1,17 @@
+{ pkgs, stdenv, ... }:
+
+stdenv.mkDerivation {
+ name = "viljetic-pages-0";
+ phases = [
+ "installPhase"
+ ];
+ buildInputs = with pkgs; [
+ imagemagick
+ ];
+ installPhase = ''
+ mkdir -p $out
+ cp ${./index.html} $out/index.html
+ convert ${./logo.xpm} $out/favicon.ico
+ convert ${./logo.xpm} $out/favicon2.png
+ '';
+}
diff --git a/pkgs/simple/viljetic-pages/index.html b/pkgs/simple/viljetic-pages/index.html
new file mode 100644
index 0000000..c268cb9
--- /dev/null
+++ b/pkgs/simple/viljetic-pages/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<title>blank page</title>
+<link rel="shortcut icon" href="favicon2.png" type="image/png">
+<i>This page intentionally left blank.</i>
+<!--
+ mailto:tomislav@viljetic.de
+ https://github.com/4z3
+ irc://irc.hackint.org/tv,isnick
+ irc://irc.libera.chat/tv,isnick
+ irc://chat.freenode.net/tv,isnick
+-->
diff --git a/pkgs/simple/viljetic-pages/logo.xpm b/pkgs/simple/viljetic-pages/logo.xpm
new file mode 100644
index 0000000..bb263da
--- /dev/null
+++ b/pkgs/simple/viljetic-pages/logo.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static char *meh[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 2 1 ",
+" c black",
+". c None",
+/* pixels */
+"................",
+". ...... .",
+". .. ...... .. .",
+". .. ...... .. .",
+". ...... .",
+"................",
+". . . .",
+". .. . .. . .",
+". .. . .. . .",
+". . . .",
+"................",
+"...... . .",
+"...... . .",
+"...... . .",
+"...... . .",
+"................"
+};
diff --git a/pkgs/simple/weechat-tv.nix b/pkgs/simple/weechat-tv.nix
new file mode 100644
index 0000000..17d2863
--- /dev/null
+++ b/pkgs/simple/weechat-tv.nix
@@ -0,0 +1,9 @@
+{ lib, pkgs }:
+
+pkgs.wrapWeechat pkgs.weechat-unwrapped {
+ configure = { availablePlugins, ... }: {
+ scripts = [
+ pkgs.weechatScripts.weechat-matrix
+ ];
+ };
+}
diff --git a/pkgs/simple/xdpytools/default.nix b/pkgs/simple/xdpytools/default.nix
new file mode 100644
index 0000000..7d1ee07
--- /dev/null
+++ b/pkgs/simple/xdpytools/default.nix
@@ -0,0 +1,31 @@
+{ lib, pkgs }:
+
+let
+ install = name: { path }: /* sh */ ''
+ (
+ mkdir -p $out/bin
+ touch $out/bin/${name}
+ chmod +x $out/bin/${name}
+ exec >$out/bin/${name}
+
+ echo '#! ${pkgs.dash}/bin/dash'
+ echo export PATH=${lib.makeBinPath path}
+ sed 1d ${./src + "/${name}"}
+ )
+ '';
+in
+
+pkgs.runCommand "xdpytools" {}
+ (toString
+ (lib.mapAttrsToList install {
+ xdpychvt.path = [
+ "$out"
+ "/run/wrappers/'$LOGNAME'"
+ "/run/wrappers"
+ ];
+ xdpysel.path = [
+ "$out"
+ pkgs.findutils
+ pkgs.jq
+ ];
+ }))
diff --git a/pkgs/simple/xdpytools/src/xdpychvt b/pkgs/simple/xdpytools/src/xdpychvt
new file mode 100755
index 0000000..84c1907
--- /dev/null
+++ b/pkgs/simple/xdpytools/src/xdpychvt
@@ -0,0 +1,11 @@
+#! /bin/sh
+# usage: xdpychvt {prev,next}
+# Changes to the VT based on the selected X display.
+#
+# This allows switching between X servers when display names and VT numbers
+# correlate. A more sophisticated tool would try to determine the correct VT
+# by e.g. looking at /proc, but this might not possible when e.g. using
+# security.hideProcessInformation.
+#
+
+chvt "$(xdpysel "$1")"
diff --git a/pkgs/simple/xdpytools/src/xdpysel b/pkgs/simple/xdpytools/src/xdpysel
new file mode 100755
index 0000000..e080155
--- /dev/null
+++ b/pkgs/simple/xdpytools/src/xdpysel
@@ -0,0 +1,49 @@
+#! /bin/sh
+# usage: xdpysel {prev,next}
+# Print the number of the selected X display.
+
+find /tmp/.X11-unix -mindepth 1 -maxdepth 1 |
+jq -Rrs --arg command "$1" '
+ (
+ split("\n") |
+ map(
+ select(.!="") |
+ match("^.*/X([0-9]+)$").captures[0].string |
+ tonumber
+ )
+ )
+ as $all_displays |
+
+ (
+ env.DISPLAY |
+ match("^:([0-9]+)(?:[.][0-9]+)?$").captures[0].string |
+ tonumber
+ )
+ as $current_display |
+
+ ($all_displays | length) as $all_displays_count |
+
+ ($all_displays|index($current_display))
+ as $current_index |
+
+ (($current_index + 1) % $all_displays_count)
+ as $next_index |
+
+ (($all_displays_count + $current_index - 1) % $all_displays_count)
+ as $prev_index |
+
+ $all_displays[$prev_index] as $prev_display |
+ $all_displays[$next_index] as $next_display |
+
+ {
+ prev: $prev_display,
+ next: $next_display,
+ }[$command]
+ as $result |
+
+ if $result | type == "number" then
+ $result
+ else
+ "xdpysel: bad argument: \($command)\n" | halt_error(-1)
+ end
+'
diff --git a/pkgs/simple/xkiller.nix b/pkgs/simple/xkiller.nix
new file mode 100644
index 0000000..8d8f016
--- /dev/null
+++ b/pkgs/simple/xkiller.nix
@@ -0,0 +1,25 @@
+{ pkgs }:
+pkgs.writeDash "xkiller" ''
+ set -efu
+ exec >&2
+ ${pkgs.iproute}/bin/ss -lp src unix:/tmp/.X11-unix/X* |
+ ${pkgs.gnused}/bin/sed -n '
+ s|.*/tmp/.X11-unix/X\([0-9]\+\)\>.*("X[^"]*",pid=\([0-9]\+\)\>.*|\1 \2|p
+ ' |
+ while read -r display pid; do
+ {
+ exit_code=$(
+ DISPLAY=:$display ${pkgs.coreutils}/bin/timeout 1 \
+ ${pkgs.xorg.xset}/bin/xset q >/dev/null 2>&1 &&
+ echo 0 || echo $?
+ )
+ if test $exit_code = 124; then
+ echo "X on display :$display is locked up; killing PID $pid..."
+ ${pkgs.coreutils}/bin/kill -SIGKILL "$pid"
+ else
+ echo "X on display :$display is healthy"
+ fi
+ } &
+ done
+ wait
+''
diff --git a/pkgs/simple/xtoggledpms.nix b/pkgs/simple/xtoggledpms.nix
new file mode 100644
index 0000000..d164ad7
--- /dev/null
+++ b/pkgs/simple/xtoggledpms.nix
@@ -0,0 +1,16 @@
+{ pkgs }:
+
+let
+ grep = "${pkgs.gnugrep}/bin/grep";
+ xset = "${pkgs.xorg.xset}/bin/xset";
+in
+
+pkgs.writeDashBin "xtoggledpms" ''
+ # usage: xtoggledpms
+ set -efu
+ if ${xset} q | ${grep} -qF 'DPMS is Disabled'; then
+ ${xset} dpms force off
+ else
+ ${xset} s off -dpms
+ fi
+''
diff --git a/pkgs/vim/default.nix b/pkgs/vim/default.nix
new file mode 100644
index 0000000..20e845a
--- /dev/null
+++ b/pkgs/vim/default.nix
@@ -0,0 +1,15 @@
+self: super: let
+ inherit (super) lib;
+ mylib = import ../../lib/pure.nix {
+ inherit lib;
+ };
+in {
+ tv = super.tv // {
+ vim = {
+ makePlugin = outPath: outPath // { inherit outPath; };
+ makeRuntimePath =
+ lib.concatMapStringsSep "," (builtins.getAttr "outPath");
+ };
+ vimPlugins = mylib.mapNixDir (path: self.callPackage path {}) ./.;
+ };
+}
diff --git a/pkgs/vim/elixir.nix b/pkgs/vim/elixir.nix
new file mode 100644
index 0000000..2ffbbc8
--- /dev/null
+++ b/pkgs/vim/elixir.nix
@@ -0,0 +1,9 @@
+{ pkgs }:
+pkgs.vimUtils.buildVimPlugin {
+ name = "vim-elixir-2018-08-17";
+ src = pkgs.fetchgit {
+ url = https://github.com/elixir-editors/vim-elixir;
+ rev = "0a847f0faed5ba2d94bb3d51f355c50f37ba025b";
+ sha256 = "1jl85wpgywhcvhgw02y8zpvqf0glr4i8522kxpvhsiacb1v1xh04";
+ };
+}
diff --git a/pkgs/vim/file-line.nix b/pkgs/vim/file-line.nix
new file mode 100644
index 0000000..0509cc4
--- /dev/null
+++ b/pkgs/vim/file-line.nix
@@ -0,0 +1,10 @@
+{ pkgs }:
+
+pkgs.vimUtils.buildVimPlugin {
+ name = "file-line-1.0";
+ src = pkgs.fetchgit {
+ url = https://github.com/bogado/file-line;
+ rev = "refs/tags/1.0";
+ sha256 = "0z47zq9rqh06ny0q8lpcdsraf3lyzn9xvb59nywnarf3nxrk6hx0";
+ };
+}
diff --git a/pkgs/vim/fzf.nix b/pkgs/vim/fzf.nix
new file mode 100644
index 0000000..e24bee5
--- /dev/null
+++ b/pkgs/vim/fzf.nix
@@ -0,0 +1,11 @@
+{ pkgs }:
+
+# cannot use pkgs.vimPlugins.fzf-vim as it's missing :Rg
+pkgs.vimUtils.buildVimPlugin {
+ name = "fzf-2023-01-16";
+ src = pkgs.fetchgit {
+ url = https://github.com/junegunn/fzf.vim;
+ rev = "bdf48c282ad2174c25c059b3cdb7956427b07a99";
+ hash = "sha256-eCCk+Q596Ljjdtjd0cYGqR77K3Me5gf+ts5icP22S3Y=";
+ };
+}
diff --git a/pkgs/vim/hack.nix b/pkgs/vim/hack.nix
new file mode 100644
index 0000000..3844627
--- /dev/null
+++ b/pkgs/vim/hack.nix
@@ -0,0 +1,48 @@
+{ pkgs }:
+
+pkgs.tv.vim.makePlugin (pkgs.writeTextFile (let
+ name = "hack";
+in {
+ name = "vim-color-${name}-1.0.2";
+ destination = "/colors/${name}.vim";
+ text = /* vim */ ''
+ set background=dark
+ hi clear
+ if exists("syntax_on")
+ syntax clear
+ endif
+
+ let colors_name = ${builtins.toJSON name}
+
+ hi Normal ctermbg=235
+ hi Comment ctermfg=242
+ hi Constant ctermfg=255
+ hi Identifier ctermfg=253
+ hi Function ctermfg=253
+ hi Statement ctermfg=253
+ hi PreProc ctermfg=251
+ hi Type ctermfg=251
+ hi Delimiter ctermfg=251
+ hi Special ctermfg=255
+
+ hi Garbage ctermbg=088
+ hi TabStop ctermbg=016
+ hi Todo ctermfg=174 ctermbg=NONE
+
+ hi NixCode ctermfg=040
+ hi NixData ctermfg=046
+ hi NixQuote ctermfg=071
+
+ hi diffNewFile ctermfg=207
+ hi diffFile ctermfg=207
+ hi diffLine ctermfg=207
+ hi diffSubname ctermfg=207
+ hi diffAdded ctermfg=010
+ hi diffRemoved ctermfg=009
+
+ hi Search cterm=NONE ctermbg=216
+
+ hi TabLine cterm=underline guifg=#424242 guibg=#232323
+ hi TabLineFill cterm=underline guifg=#424242 guibg=#232323
+ '';
+}))
diff --git a/pkgs/vim/jq.nix b/pkgs/vim/jq.nix
new file mode 100644
index 0000000..523f49f
--- /dev/null
+++ b/pkgs/vim/jq.nix
@@ -0,0 +1,10 @@
+{ pkgs }:
+
+pkgs.vimUtils.buildVimPlugin {
+ name = "vim-syntax-jq";
+ src = pkgs.fetchgit {
+ url = https://github.com/vito-c/jq.vim;
+ rev = "99d55a300047946a82ecdd7617323a751199ad2d";
+ sha256 = "09c94nah47wx0cr556w61h6pfznxld18pfblc3nv51ivbw7cjqyx";
+ };
+}
diff --git a/pkgs/vim/nix.nix b/pkgs/vim/nix.nix
new file mode 100644
index 0000000..26c4f1e
--- /dev/null
+++ b/pkgs/vim/nix.nix
@@ -0,0 +1,224 @@
+{ lib, pkgs }:
+
+pkgs.tv.vim.makePlugin (pkgs.write "vim-syntax-nix-nested" {
+ "/syntax/haskell.vim".text = ''
+ syn region String start=+\[[[:alnum:]]*|+ end=+|]+
+
+ hi link ConId Identifier
+ hi link VarId Identifier
+ hi link hsDelimiter Delimiter
+ '';
+ "/syntax/nix.vim".text = ''
+ "" Quit when a (custom) syntax file was already loaded
+ "if exists("b:current_syntax")
+ " finish
+ "endif
+
+ "setf nix
+
+ " Ref <nix/src/libexpr/lexer.l>
+ syn match NixID /[a-zA-Z\_][a-zA-Z0-9\_\'\-]*/
+ syn match NixINT /\<[0-9]\+\>/
+ syn match NixPATH /[a-zA-Z0-9\.\_\-\+]*\(\/[a-zA-Z0-9\.\_\-\+]\+\)\+/
+ syn match NixHPATH /\~\(\/[a-zA-Z0-9\.\_\-\+]\+\)\+/
+ syn match NixSPATH /<[a-zA-Z0-9\.\_\-\+]\+\(\/[a-zA-Z0-9\.\_\-\+]\+\)*>/
+ syn match NixURI /[a-zA-Z][a-zA-Z0-9\+\-\.]*:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~\*\']\+/
+ syn region NixSTRING
+ \ matchgroup=NixSTRING
+ \ start='"'
+ \ skip='\\"'
+ \ end='"'
+ syn region NixIND_STRING
+ \ matchgroup=NixIND_STRING
+ \ start="'''"
+ \ skip="'''\('\|[$]\|\\[nrt]\)"
+ \ end="'''"
+
+ syn match NixOther /[-!+&<>|():/;=.,?\[\]*@]/
+
+ syn match NixCommentMatch /\(^\|\s\)#.*/
+ syn region NixCommentRegion start="/\*" end="\*/"
+
+ hi link NixCode Statement
+ hi link NixData Constant
+ hi link NixComment Comment
+
+ hi link NixCommentMatch NixComment
+ hi link NixCommentRegion NixComment
+ hi link NixID NixCode
+ hi link NixINT NixData
+ hi link NixPATH NixData
+ hi link NixHPATH NixData
+ hi link NixSPATH NixData
+ hi link NixURI NixData
+ hi link NixSTRING NixData
+ hi link NixIND_STRING NixData
+
+ hi link NixEnter NixCode
+ hi link NixOther NixCode
+ hi link NixQuote NixData
+
+ syn cluster nix_has_dollar_curly contains=@nix_ind_strings,@nix_strings
+ syn cluster nix_ind_strings contains=NixIND_STRING
+ syn cluster nix_strings contains=NixSTRING
+
+ ${lib.concatStringsSep "\n" (let
+ alts = xs: ''\(${lib.concatStringsSep ''\|'' xs}\)'';
+ capitalize = s: let
+ xs = lib.stringToCharacters s;
+ in
+ lib.toUpper (builtins.head xs) + lib.concatStrings (builtins.tail xs);
+ comment = k: ''/\* ${k} \*/'';
+ def = k: ''${k}[ \t\r\n]*='';
+ writer = k: ''write${k}[^ \t\r\n]*[ \t\r\n]*\("[^"]*"\|[a-z]\+\)'';
+ writerExt = k: writerName ''[^"]*\.${k}'';
+ writerName = k:
+ ''${alts [''toFile'' ''write[^ \t\r\n]*'']}*[ \t\r\n]*"${k}"'';
+ in lib.mapAttrsToList (name: {
+ extraStart ? null,
+ lang ? name
+ }:
+ let
+ startAlts = builtins.filter builtins.isString [
+ (comment name)
+ extraStart
+ ];
+ sigil = ''${alts startAlts}[ \t\r\n]*'';
+ in /* vim */ ''
+ syn include @nix_${lang}_syntax syntax/${lang}.vim
+ if exists("b:current_syntax")
+ unlet b:current_syntax
+ endif
+
+ syn match nix_${lang}_sigil
+ \ X${lib.replaceStrings ["X"] ["\\X"] sigil}\ze\('''\|"\)X
+ \ nextgroup=nix_${lang}_region_IND_STRING,nix_${lang}_region_STRING
+ \ transparent
+
+ syn region nix_${lang}_region_STRING
+ \ matchgroup=NixSTRING
+ \ start='"'
+ \ skip='\\"'
+ \ end='"'
+ \ contained
+ \ contains=@nix_${lang}_syntax
+ \ transparent
+
+ syn region nix_${lang}_region_IND_STRING
+ \ matchgroup=NixIND_STRING
+ \ start="'''"
+ \ skip="'''\('\|[$]\|\\[nrt]\)"
+ \ end="'''"
+ \ contained
+ \ contains=@nix_${lang}_syntax
+ \ transparent
+
+ syn cluster nix_ind_strings
+ \ add=nix_${lang}_region_IND_STRING
+
+ syn cluster nix_strings
+ \ add=nix_${lang}_region_STRING
+
+ " This is required because containedin isn't transitive.
+ syn cluster nix_has_dollar_curly
+ \ add=@nix_${lang}_syntax
+ '') {
+ c = {};
+ cabal = {};
+ diff = {};
+ exim = {};
+ haskell = {};
+ jq.extraStart = alts [
+ (writer "Jq")
+ (writerExt "jq")
+ ];
+ javascript.extraStart = comment "js";
+ lua = {};
+ markdown.extraStart = writerExt "md";
+ nftables = {};
+ #nginx = {};
+ python.extraStart = alts [
+ (comment "py")
+ (writerExt "py")
+ ];
+ sed.extraStart = writer "Sed";
+ sh.extraStart = let
+ phases = [
+ "unpack"
+ "patch"
+ "configure"
+ "build"
+ "check"
+ "install"
+ "fixup"
+ "installCheck"
+ "dist"
+ ];
+ shells = [
+ "ash"
+ "bash"
+ "dash"
+ ];
+ in alts [
+ (def "shellHook")
+ (def "${alts phases}Phase")
+ (def "${alts ["pre" "post"]}${alts (map capitalize phases)}")
+ (writer (alts (map capitalize shells)))
+ ];
+ yaml = {};
+ vim.extraStart = alts [
+ (def ''"[^"]*\.vim"\.text'')
+ (writerExt "vim")
+ (writerName ''\([^"]*\.\)\?vimrc'')
+ ];
+ xdefaults = {};
+ xmodmap = {};
+ })}
+
+ " Clear syntax that interferes with nixINSIDE_DOLLAR_CURLY.
+ syn clear shVarAssign
+
+ syn region nixINSIDE_DOLLAR_CURLY
+ \ matchgroup=NixEnter
+ \ start="[$]{"
+ \ end="}"
+ \ contains=TOP
+ \ containedin=@nix_has_dollar_curly
+ \ transparent
+
+ syn region nix_inside_curly
+ \ matchgroup=NixEnter
+ \ start="{"
+ \ end="}"
+ \ contains=TOP
+ \ containedin=nixINSIDE_DOLLAR_CURLY,nix_inside_curly
+ \ transparent
+
+ syn match NixQuote /'''\(''$\|\\.\)/he=s+2
+ \ containedin=@nix_ind_strings
+ \ contained
+
+ syn match NixQuote /'''\('\|\\.\)/he=s+1
+ \ containedin=@nix_ind_strings
+ \ contained
+
+ syn match NixQuote /\\./he=s+1
+ \ containedin=@nix_strings
+ \ contained
+
+ syn sync fromstart
+
+ let b:current_syntax = "nix"
+
+ set isk=@,48-57,_,192-255,-,'
+ '';
+ "/syntax/sed.vim".text = ''
+ syn region sedBranch
+ \ matchgroup=sedFunction start="T"
+ \ matchgroup=sedSemicolon end=";\|$"
+ \ contains=sedWhitespace
+ '';
+ "/syntax/xmodmap.vim".text = ''
+ syn match xmodmapComment /^\s*!.*/
+ '';
+})
diff --git a/pkgs/vim/showsyntax.nix b/pkgs/vim/showsyntax.nix
new file mode 100644
index 0000000..c27dd04
--- /dev/null
+++ b/pkgs/vim/showsyntax.nix
@@ -0,0 +1,26 @@
+{ pkgs }:
+
+pkgs.tv.vim.makePlugin (pkgs.writeTextFile (let
+ name = "showsyntax";
+in {
+ name = "vim-plugin-${name}-1.0.0";
+ destination = "/plugin/${name}.vim";
+ text = /* vim */ ''
+ if exists('g:loaded_showsyntax')
+ finish
+ endif
+ let g:loaded_showsyntax = 0
+
+ fu! ShowSyntax()
+ let id = synID(line("."), col("."), 1)
+ let name = synIDattr(id, "name")
+ let transName = synIDattr(synIDtrans(id),"name")
+ if name != transName
+ let name .= " (" . transName . ")"
+ endif
+ echo "Syntax: " . name
+ endfu
+
+ command! -n=0 -bar ShowSyntax :call ShowSyntax()
+ '';
+}))
diff --git a/pkgs/vim/tv.nix b/pkgs/vim/tv.nix
new file mode 100644
index 0000000..10816ce
--- /dev/null
+++ b/pkgs/vim/tv.nix
@@ -0,0 +1,42 @@
+{ pkgs }:
+
+pkgs.tv.vim.makePlugin (pkgs.write "vim-tv" {
+ #
+ # TODO
+ #
+ "/ftdetect/todo.vim".text = ''
+ au BufRead,BufNewFile TODO set ft=todo
+ '';
+ "/ftplugin/todo.vim".text = ''
+ setlocal foldmethod=syntax
+ '';
+ "/syntax/todo.vim".text = ''
+ syn match todoComment /#.*/
+
+ syn match todoDate /^[1-9]\S*/
+ \ nextgroup=todoSummary
+
+ syn region todoSummary
+ \ contained
+ \ contains=todoTag
+ \ start="." end="$\n"
+ \ nextgroup=todoBlock
+
+ syn match todoTag /\[[A-Za-z]\+\]/hs=s+1,he=e-1
+ \ contained
+
+ syn region todoBlock
+ \ contained
+ \ contains=Comment
+ \ fold
+ \ start="^[^1-9]" end="^[1-9 ]"re=s-1,he=s-1,me=s-1
+
+ syn sync minlines=1000
+
+ hi link todoComment Comment
+ hi todoDate ctermfg=255
+ hi todoSummary ctermfg=229
+ hi todoBlock ctermfg=248
+ hi todoTag ctermfg=217
+ '';
+})
diff --git a/pkgs/vim/vim.nix b/pkgs/vim/vim.nix
new file mode 100644
index 0000000..e026f13
--- /dev/null
+++ b/pkgs/vim/vim.nix
@@ -0,0 +1,21 @@
+{ lib, pkgs }:
+
+let
+ mylib = import ../../lib/pure.nix {
+ inherit lib;
+ };
+in
+
+pkgs.tv.vim.makePlugin (pkgs.writeTextFile (let
+ name = "vim";
+in {
+ name = "vim-syntax-${name}-1.0.0";
+ destination = "/syntax/${name}.vim";
+ text = /* vim */ ''
+ ${lib.concatMapStringsSep "\n" (s: /* vim */ ''
+ syn keyword vimColor${s} ${s}
+ \ containedin=ALLBUT,vimComment,vimLineComment
+ hi vimColor${s} ctermfg=${s}
+ '') (map (i: mylib.lpad 3 "0" (toString i)) (lib.range 0 255))}
+ '';
+}))
[cgit] Unable to lock slot /tmp/cgit/ae200000.lock: No such file or directory (2)