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; + contrastOpaci