From 0c4f3acb281be6290c55a6e96bc29fab5b5c7a11 Mon Sep 17 00:00:00 2001 From: tv Date: Mon, 11 Sep 2023 18:24:28 +0200 Subject: stockholm -> hrm --- pkgs/compat/default.nix | 1 + pkgs/default.nix | 24 +++ pkgs/haskell/default.nix | 31 +++ pkgs/haskell/th-env/default.nix | 10 + pkgs/haskell/th-env/src/THEnv.hs | 49 +++++ pkgs/haskell/th-env/th-env.cabal | 20 ++ pkgs/haskell/xmonad-tv/default.nix | 16 ++ pkgs/haskell/xmonad-tv/shell.nix | 83 ++++++++ pkgs/haskell/xmonad-tv/src/Shutdown.hs | 113 ++++++++++ pkgs/haskell/xmonad-tv/src/XMonad/Extra.hs | 14 ++ .../src/XMonad/Hooks/EwmhDesktops/Extra.hs | 117 ++++++++++ pkgs/haskell/xmonad-tv/src/main.hs | 227 ++++++++++++++++++++ pkgs/haskell/xmonad-tv/src/xmonad-tv.cabal | 29 +++ pkgs/override/alacritty.nix | 16 ++ pkgs/override/anbox.nix | 72 +++++++ pkgs/override/default.nix | 11 + pkgs/override/fzf/complete1.patch | 77 +++++++ pkgs/override/fzf/default.nix | 7 + pkgs/override/gitAndTools.nix | 5 + pkgs/override/input-fonts.nix | 13 ++ pkgs/override/iosevka-tv-1.nix | 20 ++ pkgs/override/iosevka-tv-2.nix | 20 ++ pkgs/override/jc.nix | 21 ++ pkgs/override/uqmi.nix | 10 + .../433Utils/RPi_utils.codesend.codestring.patch | 24 +++ pkgs/rpi/433Utils/default.nix | 42 ++++ pkgs/rpi/433Utils/rc-switch.protocols.patch | 10 + pkgs/rpi/433Utils/src.json | 7 + pkgs/rpi/WiringPi/default.nix | 61 ++++++ pkgs/rpi/WiringPi/src.json | 6 + pkgs/rpi/default.nix | 11 + pkgs/simple/alacritty-tv.nix | 155 ++++++++++++++ pkgs/simple/bash-fzf-history.nix | 107 ++++++++++ pkgs/simple/cr.nix | 16 ++ pkgs/simple/default.nix | 22 ++ pkgs/simple/diff-so-fancy.nix | 50 +++++ pkgs/simple/disko.nix | 13 ++ pkgs/simple/editor-input.nix | 18 ++ pkgs/simple/ff.nix | 8 + pkgs/simple/field.nix | 6 + pkgs/simple/flameshot-once-tv.nix | 48 +++++ pkgs/simple/font-size-alacritty.nix | 67 ++++++ pkgs/simple/fzmenu/bin/otpmenu | 44 ++++ pkgs/simple/fzmenu/bin/passmenu | 45 ++++ pkgs/simple/fzmenu/default.nix | 50 +++++ pkgs/simple/hc.nix | 39 ++++ pkgs/simple/iosevka-tv-1.nix | 18 ++ pkgs/simple/iosevka-tv-2.nix | 20 ++ pkgs/simple/libinput-tv.nix | 11 + pkgs/simple/mpvterm/default.nix | 8 + pkgs/simple/mpvterm/mpvterm.patch | 146 +++++++++++++ pkgs/simple/pinentry-urxvt/default.nix | 127 +++++++++++ pkgs/simple/q/default.nix | 176 +++++++++++++++ pkgs/simple/rox-filer.nix | 95 +++++++++ .../rxvt-unicode-256color-terminfo/default.nix | 16 ++ .../rxvt-unicode-256color.terminfo | Bin 0 -> 2239 bytes pkgs/simple/stardict/default.nix | 235 +++++++++++++++++++++ pkgs/simple/viljetic-pages/default.nix | 17 ++ pkgs/simple/viljetic-pages/index.html | 11 + pkgs/simple/viljetic-pages/logo.xpm | 24 +++ pkgs/simple/weechat-tv.nix | 9 + pkgs/simple/xdpytools/default.nix | 31 +++ pkgs/simple/xdpytools/src/xdpychvt | 11 + pkgs/simple/xdpytools/src/xdpysel | 49 +++++ pkgs/simple/xkiller.nix | 25 +++ pkgs/simple/xtoggledpms.nix | 16 ++ pkgs/vim/default.nix | 15 ++ pkgs/vim/elixir.nix | 9 + pkgs/vim/file-line.nix | 10 + pkgs/vim/fzf.nix | 11 + pkgs/vim/hack.nix | 48 +++++ pkgs/vim/jq.nix | 10 + pkgs/vim/nix.nix | 224 ++++++++++++++++++++ pkgs/vim/showsyntax.nix | 26 +++ pkgs/vim/tv.nix | 42 ++++ pkgs/vim/vim.nix | 21 ++ 76 files changed, 3316 insertions(+) create mode 100644 pkgs/compat/default.nix create mode 100644 pkgs/default.nix create mode 100644 pkgs/haskell/default.nix create mode 100644 pkgs/haskell/th-env/default.nix create mode 100644 pkgs/haskell/th-env/src/THEnv.hs create mode 100644 pkgs/haskell/th-env/th-env.cabal create mode 100644 pkgs/haskell/xmonad-tv/default.nix create mode 100644 pkgs/haskell/xmonad-tv/shell.nix create mode 100644 pkgs/haskell/xmonad-tv/src/Shutdown.hs create mode 100644 pkgs/haskell/xmonad-tv/src/XMonad/Extra.hs create mode 100644 pkgs/haskell/xmonad-tv/src/XMonad/Hooks/EwmhDesktops/Extra.hs create mode 100644 pkgs/haskell/xmonad-tv/src/main.hs create mode 100644 pkgs/haskell/xmonad-tv/src/xmonad-tv.cabal create mode 100644 pkgs/override/alacritty.nix create mode 100644 pkgs/override/anbox.nix create mode 100644 pkgs/override/default.nix create mode 100644 pkgs/override/fzf/complete1.patch create mode 100644 pkgs/override/fzf/default.nix create mode 100644 pkgs/override/gitAndTools.nix create mode 100644 pkgs/override/input-fonts.nix create mode 100644 pkgs/override/iosevka-tv-1.nix create mode 100644 pkgs/override/iosevka-tv-2.nix create mode 100644 pkgs/override/jc.nix create mode 100644 pkgs/override/uqmi.nix create mode 100644 pkgs/rpi/433Utils/RPi_utils.codesend.codestring.patch create mode 100644 pkgs/rpi/433Utils/default.nix create mode 100644 pkgs/rpi/433Utils/rc-switch.protocols.patch create mode 100644 pkgs/rpi/433Utils/src.json create mode 100644 pkgs/rpi/WiringPi/default.nix create mode 100644 pkgs/rpi/WiringPi/src.json create mode 100644 pkgs/rpi/default.nix create mode 100644 pkgs/simple/alacritty-tv.nix create mode 100644 pkgs/simple/bash-fzf-history.nix create mode 100644 pkgs/simple/cr.nix create mode 100644 pkgs/simple/default.nix create mode 100644 pkgs/simple/diff-so-fancy.nix create mode 100644 pkgs/simple/disko.nix create mode 100644 pkgs/simple/editor-input.nix create mode 100644 pkgs/simple/ff.nix create mode 100644 pkgs/simple/field.nix create mode 100644 pkgs/simple/flameshot-once-tv.nix create mode 100644 pkgs/simple/font-size-alacritty.nix create mode 100755 pkgs/simple/fzmenu/bin/otpmenu create mode 100755 pkgs/simple/fzmenu/bin/passmenu create mode 100644 pkgs/simple/fzmenu/default.nix create mode 100644 pkgs/simple/hc.nix create mode 100644 pkgs/simple/iosevka-tv-1.nix create mode 100644 pkgs/simple/iosevka-tv-2.nix create mode 100644 pkgs/simple/libinput-tv.nix create mode 100644 pkgs/simple/mpvterm/default.nix create mode 100644 pkgs/simple/mpvterm/mpvterm.patch create mode 100644 pkgs/simple/pinentry-urxvt/default.nix create mode 100644 pkgs/simple/q/default.nix create mode 100644 pkgs/simple/rox-filer.nix create mode 100644 pkgs/simple/rxvt-unicode-256color-terminfo/default.nix create mode 100644 pkgs/simple/rxvt-unicode-256color-terminfo/rxvt-unicode-256color.terminfo create mode 100644 pkgs/simple/stardict/default.nix create mode 100644 pkgs/simple/viljetic-pages/default.nix create mode 100644 pkgs/simple/viljetic-pages/index.html create mode 100644 pkgs/simple/viljetic-pages/logo.xpm create mode 100644 pkgs/simple/weechat-tv.nix create mode 100644 pkgs/simple/xdpytools/default.nix create mode 100755 pkgs/simple/xdpytools/src/xdpychvt create mode 100755 pkgs/simple/xdpytools/src/xdpysel create mode 100644 pkgs/simple/xkiller.nix create mode 100644 pkgs/simple/xtoggledpms.nix create mode 100644 pkgs/vim/default.nix create mode 100644 pkgs/vim/elixir.nix create mode 100644 pkgs/vim/file-line.nix create mode 100644 pkgs/vim/fzf.nix create mode 100644 pkgs/vim/hack.nix create mode 100644 pkgs/vim/jq.nix create mode 100644 pkgs/vim/nix.nix create mode 100644 pkgs/vim/showsyntax.nix create mode 100644 pkgs/vim/tv.nix create mode 100644 pkgs/vim/vim.nix (limited to 'pkgs') 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 +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 ; + + 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 +maintainer: tv +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 + # 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 +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 +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 + #include + ++#include ++#include ++#include ++ + #include + #include + #include +@@ -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 + &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 Binary files /dev/null and b/pkgs/simple/rxvt-unicode-256color-terminfo/rxvt-unicode-256color.terminfo 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!\([^<>]*\)!\1!g; + s!]*>!!g; + s!!!g; + s!\([^<>]*\)!\1 !g; + s!\([^<>]*\)!$(tput sitm)\2$(tput sgr0)!g; + s!\([^<>]*\)!\1!g; + s!\([^<>]*\)!$(tput sitm)\1$(tput sgr0)!g; + s!\([^<>]*\)!$(tput sitm)\1$(tput sgr0)!g; + s!]*>\([^<>]*\)!$(tput sitm)\1$(tput sgr0)!g; + s!\([^<>]*\)!$(tput sitm)\1$(tput sgr0) !g; + s!\([^<>]*\)!$(tput sitm)\1$(tput sgr0) !g; + s!\([^<>]*\)!$(tput setaf 3)\1$(tput sgr0)!g; + s!\([^<>]*\)!$(tput bold)\1$(tput sgr0)\t!g; + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!$(tput sitm)!g + s!]*>!$(tput sgr0)!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!]*>!!g + s!!!g + s!]*>!$(tput setaf 245)!g + s!]*>!$(tput sgr0)!g + s/
/$(tput bold)/g; + s:
:$(tput sgr0):g; + s/
/\n/g; + s:
::g; + s/<[bB]>/$(tput bold)/g; + s::$(tput sgr0):g; + s:<[bB][rR]\s*/\?>:\n:g; + s:<[iI]>:$(tput sitm):g; + s::$(tput sgr0):g; + s:<[uU]>:$(tput smul):g; + s::$(tput sgr0):g; + s:]*>::g; + s:::g; + s!\([^<>]*\)!$(tput bold)\1$(tput sgr0)!g; + s!\([^<>]*\)!\2!g + s#
\(.*\)
#\\1#g; + s:\([^<>]*\):$(tput setaf 3)\\1$(tput sgr0):g; + s:\([^<>]*\):$(tput setaf 4)\\1$(tput sgr0):g; + s:\([^<>]*\):$(tput setaf 1)\\1$(tput sgr0):g; + s:\([^<>]*\):$(tput setaf 5)\\1$(tput sgr0):g; + s:\([^<>]*\):$(tput bold)\1$(tput sgr0):g + s:\([^<>]*\):$(tput setaf 3)\1$(tput sgr0):g + s:':':g + s:<:<:g + s:>:>:g + s:\([^<>]*\):$(tput setaf 2)\\1$(tput sgr0):g; + s:\([^<>]*\):$(tput setaf 2)\\1$(tput sgr0):g; + s:\([^<>]*\):$(tput setaf 4)\\1$(tput sgr0):g; + s:\([^<>]*\):$(tput bold)\\1$(tput sgr0):g; + s:]*>:ː:g; + s:]*>::g; + s!!!g + s!]*>!!g + s!!!g + s!]*>!!g + s!]*>!!g + s!\([^<>]*\)!$(tput setaf 245)\1$(tput sgr0)!g + s!]*>!!g + s! +! !g; + s!
!\n\n&!g + s!]*>!!g + s!]*>!!g + s!!!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 @@ + +blank page + +This page intentionally left blank. + 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 + 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 v1.3.1 [cgit] Unable to lock slot /tmp/cgit/3b300000.lock: No such file or directory (2)