Merge remote-tracking branch 'ni/master'

This commit is contained in:
lassulus 2023-01-19 14:11:01 +01:00
commit b51998cfae
33 changed files with 664 additions and 169 deletions

24
kartei/tv/hosts/ru.nix Normal file
View File

@ -0,0 +1,24 @@
{
ci = true;
nets = {
retiolum = {
ip4.addr = "10.243.13.42";
aliases = [
"ru.r"
];
tinc.pubkey = ''
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAr4xgpXPr/OGrLO5vwur35esesbAwREwShGJf9btt65UQXst090tD
GWev8Yfi3Mr241r1TG7zpW3Idh5nth2yhzVvqGc9m6QmK27v2MKpb+ppjOKab7RL
1KfdBAwjdrWdL2xO3XAYOUljxWoIV4VKX8kEBvjJEDOwl/u+g5mB3yLWebtIT7Wk
EneMU6wvCVKhOPeqyXmbqO/+j6+bqxkKP2/5hHcX3a91+15YbR3SvREK2rUm9stx
Rc3kmGUO/DiGK6MmUmt+qieGo/4vheK8hij57dY0uXFIC7U680QzV7jsUmtlKGBL
PoK/Xn6TLLG6nozgmF+q8esYyaYQFrwU2QIDAQAB
-----END RSA PUBLIC KEY-----
'';
tinc.pubkey_ed25519 = "Eg9l+RxFSNrQ9RkTd8tSkoTIG2m7zhQpjUJBWJRft1J";
};
};
secure = true;
ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIcNClgsey79WzdEQs/8qkLMHzc1SCU/MqyMerPcUi8X root@ru";
}

View File

@ -3,8 +3,7 @@
hostNames =
["github.com"]
++
# List generated with (IPv6 addresses are currently ignored):
# curl -sS https://api.github.com/meta | jq -r .git[] | grep -v : | nix-shell -p cidr2glob --run cidr2glob | jq -Rs 'split("\n")|map(select(.!=""))' > known-hosts.json
# update known-hosts.json using ./update
lib.importJSON ./known-hosts.json
;
publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==";

15
krebs/3modules/github/update Executable file
View File

@ -0,0 +1,15 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p cidr2glob curl git jq
# update known-hosts.json
#
# usage: ./update
set -efu
# XXX IPv6 addresses are currently ignored
curl -sS https://api.github.com/meta | jq -r .git[] | grep -v : | cidr2glob | jq -Rs 'split("\n")|map(select(.!=""))' > known-hosts.json
if git diff --exit-code known-hosts.json; then
echo known-hosts.json is up to date: nothing to do >&2
fi

View File

@ -1,12 +1,13 @@
{ openssl, writePython2Bin }:
{ openssl, writePython3Bin }:
writePython2Bin "syncthing-device-id" {
writePython3Bin "syncthing-device-id" {
flakeIgnore = [
"E226"
"E302"
"E305"
"E501"
"F401"
"W504"
];
} /* python */ ''
import base64

View File

@ -11,8 +11,6 @@ with import ./lib;
<stockholm/tv/2configs/xsessions>
];
environment.homeBinInPath = true;
krebs.build.host = config.krebs.hosts.bu;
networking.hostId = lib.mkDefault "00000000";

View File

@ -41,8 +41,6 @@ with import ./lib;
fsType = "btrfs";
};
environment.homeBinInPath = true;
environment.systemPackages = with pkgs; [
(writeDashBin "play" ''
set -euf

View File

@ -39,6 +39,10 @@ with import ./lib;
esac
${pkgs.bash-fzf-history.bind}
if test -n "''${BASH_EXTRA_INIT-}"; then
. "$BASH_EXTRA_INIT"
fi
'';
promptInit = /* sh */ ''
case $UID in

View File

@ -1,8 +1,8 @@
with import ./lib;
{ config, pkgs, ... }: {
{ config, modulesPath, pkgs, ... }: {
imports = [
<nixpkgs/nixos/modules/services/hardware/sane_extra_backends/brscan4.nix>
(modulesPath + "/services/hardware/sane_extra_backends/brscan4.nix")
];
krebs.nixpkgs.allowUnfreePredicate = pkg: any (eq (packageName pkg)) [

View File

@ -16,6 +16,7 @@ with import ./lib;
./nets/hkw.nix
./networkd.nix
./nginx
./nix.nix
./pki
./ssh.nix
./sshd.nix
@ -44,21 +45,12 @@ with import ./lib;
time.timeZone = "Europe/Berlin";
}
{
nix.extraOptions = ''
auto-optimise-store = true
'';
# TODO check if both are required:
nix.settings.extra-sandbox-paths = [
"/etc/protocols"
pkgs.iana-etc.outPath
];
}
{
nixpkgs.config.allowUnfree = false;
}
{
environment.homeBinInPath = true;
environment.profileRelativeEnvVars.PATH = mkForce [ "/bin" ];
environment.systemPackages = with pkgs; [
@ -137,4 +129,11 @@ with import ./lib;
];
}
];
nixpkgs.overlays =
mkAfter (optional config.hardware.video.hidpi.enable (self: super: {
alacritty-tv = super.alacritty-tv.override {
variant = "hidpi";
};
}));
}

View File

@ -4,8 +4,8 @@ with import ./lib;
../smartd.nix
{
nix.buildCores = 2;
nix.maxJobs = 2;
nix.settings.cores = 2;
nix.settings.max-jobs = 2;
}
(if lib.versionAtLeast (lib.versions.majorMinor lib.version) "21.11" then {
nix.daemonCPUSchedPolicy = "batch";

View File

@ -0,0 +1,32 @@
{ pkgs, ... }: {
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usbhid" ];
boot.initrd.kernelModules = [ "amdgpu" ];
boot.kernelModules = [ "kvm-amd" ];
hardware.cpu.amd.updateMicrocode = true;
hardware.enableRedistributableFirmware = true;
hardware.opengl.enable = true;
hardware.opengl.extraPackages = [
pkgs.amdvlk
pkgs.rocm-opencl-icd
pkgs.rocm-opencl-runtime
];
hardware.video.hidpi.enable = true;
networking.wireless.enable = true;
networking.wireless.interfaces = [
"wlp1s0"
];
networking.interfaces.wlp1s0.useDHCP = true;
nixpkgs.hostPlatform = "x86_64-linux";
services.illum.enable = true;
tv.lidControl.enable = true;
tv.hw.screens.primary.width = 2560;
tv.hw.screens.primary.height = 1600;
}

9
tv/2configs/nix.nix Normal file
View File

@ -0,0 +1,9 @@
{ pkgs, ... }: {
nix.settings.auto-optimise-store = true;
# TODO check if both are required:
nix.settings.extra-sandbox-paths = [
"/etc/protocols"
pkgs.iana-etc.outPath
];
}

View File

@ -1,24 +0,0 @@
{ pkgs, ... }:
with builtins;
let
users = [ "tv" ];
urxvt = pkgs.rxvt_unicode;
mkService = user: {
description = "urxvt terminal daemon";
wantedBy = [ "multi-user.target" ];
restartIfChanged = false;
serviceConfig = {
Restart = "always";
User = user;
ExecStart = "${urxvt}/bin/urxvtd";
};
};
in
{
environment.systemPackages = [ urxvt ];
systemd.services = listToAttrs (map (u: { name = "${u}-urxvtd"; value = mkService u; }) users);
}

View File

@ -11,18 +11,31 @@ with import ./lib;
environment.variables.VIMINIT = ":so /etc/vimrc";
};
extra-runtimepath = pkgs.tv.vim.makeRuntimePath [
pkgs.tv.vimPlugins.elixir
base-plugins = [
pkgs.tv.vimPlugins.file-line
pkgs.tv.vimPlugins.fzf
pkgs.tv.vimPlugins.hack
pkgs.vimPlugins.undotree
(pkgs.tv.vim.makePlugin (pkgs.write "vim-tv-base" {
"/ftplugin/haskell.vim".text = ''
if exists("g:vim_tv_ftplugin_haskell_loaded")
finish
endif
let g:vim_tv_ftplugin_haskell_loaded = 1
setlocal iskeyword+='
'';
}))
];
extra-plugins = [
pkgs.tv.vimPlugins.elixir
pkgs.tv.vimPlugins.fzf
pkgs.tv.vimPlugins.jq
pkgs.tv.vimPlugins.nix
pkgs.tv.vimPlugins.showsyntax
pkgs.tv.vimPlugins.tv
pkgs.tv.vimPlugins.vim
pkgs.vimPlugins.fzfWrapper
pkgs.vimPlugins.undotree
pkgs.vimPlugins.vim-nftables
];
@ -58,7 +71,9 @@ with import ./lib;
];
};
vimrc = pkgs.writeText "vimrc" ''
vimrc = pkgs.writeText "vimrc" /* vim */ ''
vim9script
set nocompatible
set autoindent
@ -71,7 +86,7 @@ with import ./lib;
set mouse=a
set noruler
set pastetoggle=<INS>
set runtimepath=${extra-runtimepath},$VIMRUNTIME
set runtimepath=${pkgs.tv.vim.makeRuntimePath base-plugins},$VIMRUNTIME
set shortmess+=I
set showcmd
set showmatch
@ -88,13 +103,15 @@ with import ./lib;
set wildmenu
set wildmode=longest,full
set runtimepath^=${pkgs.tv.vim.makeRuntimePath extra-plugins}
syntax on
set et ts=2 sts=2 sw=2
filetype plugin indent on
set t_Co=256
colorscheme hack
syntax on
au Syntax * syn match Garbage containedin=ALL /\s\+$/
\ | syn match TabStop containedin=ALL /\t\+/
@ -115,30 +132,52 @@ with import ./lib;
nnoremap <f1> :tabp<cr>
nnoremap <f2> :tabn<cr>
inoremap <f1> <esc>:tabp<cr>
inoremap <f2> <esc>:tabn<cr>
imap <f1> <esc><f1>
imap <f2> <esc><f2>
nnoremap <S-f1> :tabm -1<cr>
nnoremap <S-f2> :tabm +1<cr>
imap <S-f1> <esc><S-f1>
imap <S-f2> <esc><S-f2>
noremap <f3> :ShowSyntax<cr>
" <C-{Up,Down,Right,Left>
# <C-{Up,Down,Right,Left}>
noremap <esc>Oa <nop> | noremap! <esc>Oa <nop>
noremap <esc>Ob <nop> | noremap! <esc>Ob <nop>
noremap <esc>Oc <nop> | noremap! <esc>Oc <nop>
noremap <esc>Od <nop> | noremap! <esc>Od <nop>
" <[C]S-{Up,Down,Right,Left>
# <[C]S-{Up,Down,Right,Left}>
noremap <esc>[a <nop> | noremap! <esc>[a <nop>
noremap <esc>[b <nop> | noremap! <esc>[b <nop>
noremap <esc>[c <nop> | noremap! <esc>[c <nop>
noremap <esc>[d <nop> | noremap! <esc>[d <nop>
vnoremap u <nop>
" fzf
# fzf
nnoremap <esc>q :Buffers<cr>
nnoremap <esc>f :Files<cr>
nnoremap <esc>w :Rg<cr>
" edit alternate buffer
" For some reason neither putting <ctrl>6 nor <ctrl>^ works here...
# edit alternate buffer
# For some reason neither putting <ctrl>6 nor <ctrl>^ works here...
nnoremap <esc>a 
if $TOUCHSCREEN == "1"
nnoremap <ScrollWheelUp> <C-y>
nnoremap <ScrollWheelDown> <C-e>
nnoremap <C-ScrollWheelUp> 3<C-y>
nnoremap <C-ScrollWheelDown> 3<C-e>
nnoremap <S-ScrollWheelUp> 3<C-y>
nnoremap <S-ScrollWheelDown> 3<C-e>
nnoremap <C-S-ScrollWheelUp> <PageUp>
nnoremap <C-S-ScrollWheelDown> <PageDown>
endif
# remember last position
autocmd BufReadPost *
\ if line("'\"") > 0 && line("'\"") <= line("$") |
\ exe "normal! g`\"" |
\ endif
'';
}

View File

@ -8,9 +8,12 @@
./hw.nix
./im.nix
./iptables.nix
./lidControl.nix
./org.freedesktop.machine1.host-shell.nix
./systemd.nix
./slock.nix
./x0vncserver.nix
./Xresources.nix
./wwan.nix
];
}

View File

@ -34,6 +34,10 @@ with import ./lib;
type = with types; listOf str;
default = [];
};
filter.Wiregrill = mkOption {
type = with types; listOf str;
default = [];
};
};
};
};
@ -66,6 +70,16 @@ with import ./lib;
default = [];
};
input-wiregrill-accept-tcp = mkOption {
type = with types; listOf (either int str);
default = [];
};
input-wiregrill-accept-udp = mkOption {
type = with types; listOf (either int str);
default = [];
};
extra = mkOption {
default = {};
type = extraTypes.rules;
@ -141,6 +155,7 @@ with import ./lib;
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:Retiolum - [0:0]
:Wiregrill - [0:0]
${concatMapStringsSep "\n" (rule: "-A INPUT ${rule}") ([]
++ [
"-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT"
@ -150,6 +165,7 @@ with import ./lib;
++ map accept-tcp (unique (map toString cfg.input-internet-accept-tcp))
++ map accept-udp (unique (map toString cfg.input-internet-accept-udp))
++ ["-i retiolum -j Retiolum"]
++ ["-i wiregrill -j Wiregrill"]
)}
${formatTable cfg.extra.filter}
${formatTable cfg."extra${toString iptables-version}".filter}
@ -170,6 +186,23 @@ with import ./lib;
];
}."ip${toString iptables-version}tables"
)}
${concatMapStringsSep "\n" (rule: "-A Wiregrill ${rule}") ([]
++ optional (cfg.accept-echo-request == "wiregrill") accept-echo-request
++ map accept-tcp (unique (map toString cfg.input-wiregrill-accept-tcp))
++ map accept-udp (unique (map toString cfg.input-wiregrill-accept-udp))
++ {
ip4tables = [
"-p tcp -j REJECT --reject-with tcp-reset"
"-p udp -j REJECT --reject-with icmp-port-unreachable"
"-j REJECT --reject-with icmp-proto-unreachable"
];
ip6tables = [
"-p tcp -j REJECT --reject-with tcp-reset"
"-p udp -j REJECT --reject-with icmp6-port-unreachable"
"-j REJECT"
];
}."ip${toString iptables-version}tables"
)}
COMMIT
'';
}

View File

@ -0,0 +1,45 @@
with import ./lib;
{ config, pkgs, ... }: {
options = {
tv.lidControl.enable = mkEnableOption "tv.lidControl";
};
config = let
cfg = config.tv.lidControl;
in mkIf cfg.enable {
services.acpid.enable = true;
services.acpid.lidEventCommands = /* sh */ ''
set -- $1
# usage: vt_is_xserver NUMBER
vt_is_xserver() {
${pkgs.iproute}/bin/ss -lp src unix:/tmp/.X11-unix/X* |
${pkgs.gnused}/bin/sed -n 's|.*/tmp/.X11-unix/X\([0-9]\+\)\>.*|\1|p' |
${pkgs.gnugrep}/bin/grep -Fqx "$1"
}
console=$(${pkgs.kbd}/bin/fgconsole)
if vt_is_xserver "$console"; then
# usage: run_on_display COMMAND [ARG...]
run_on_display() {
owner=$(${pkgs.coreutils}/bin/stat -c %u /tmp/.X11-unix/X$console)
${pkgs.systemd}/bin/systemd-run -GPq \
-E DISPLAY=:$console \
--uid=$owner \
"$@"
}
case $3 in
open)
run_on_display ${pkgs.xorg.xset}/bin/xset dpms force on
;;
close)
run_on_display ${pkgs.xorg.xset}/bin/xset dpms force off
;;
esac
fi
'';
services.logind.lidSwitch = "ignore";
services.logind.lidSwitchDocked = "ignore";
services.logind.lidSwitchExternalPower = "ignore";
};
}

47
tv/3modules/systemd.nix Normal file
View File

@ -0,0 +1,47 @@
with import ./lib;
{ config, ... }: let
normalUsers = filterAttrs (_: getAttr "isNormalUser") config.users.users;
in {
options = {
tv.systemd.services = mkOption {
type = types.attrsOf (types.submodule (self: {
options = {
operators = mkOption {
type = with types; listOf (enum (attrNames normalUsers));
default = [];
};
};
}));
default = {};
};
};
config = {
security.polkit.extraConfig = let
access =
mapAttrs'
(name: cfg:
nameValuePair "${name}.service"
(genAttrs cfg.operators (const true))
)
config.tv.systemd.services;
in optionalString (access != {}) /* js */ ''
polkit.addRule(function () {
const access = ${lib.toJSON access};
return function (action, subject) {
if (action.id === "org.freedesktop.systemd1.manage-units") {
const unit = action.lookup("unit");
if (
(access[unit]||{})[subject.user] ||
(
unit.includes("@") &&
(access[unit.replace(/@[^.]+/, "@")]||{})[subject.user]
)
) {
return polkit.Result.YES;
}
}
}
}());
'';
};
}

181
tv/3modules/wwan.nix Normal file
View File

@ -0,0 +1,181 @@
with import ./lib;
{ config, pkgs, ... }: {
options = {
tv.wwan.enable = mkEnableOption "tv.wwan";
tv.wwan.apn = mkOption {
type = with types; filename;
};
tv.wwan.device = mkOption {
type = with types; pathname;
default = "/dev/cdc-wdm0";
};
tv.wwan.interface = mkOption {
type = with types; nullOr filename;
default = null;
};
tv.wwan.operators = mkOption {
type = with types; listOf username;
default = [];
};
tv.wwan.secrets = mkOption {
type = with types; pathname;
default = toString <secrets/wwan.json>;
# format: {"pin1":number}
};
};
config = let
cfg = config.tv.wwan;
in mkIf cfg.enable {
nixpkgs.overlays = singleton (self: super: {
uqmi-wrapper = pkgs.symlinkJoin {
name = "uqmi-wrapper";
paths = [
(pkgs.writeDashBin "uqmi" ''
exec ${pkgs.uqmi}/bin/uqmi --device=${cfg.device} "$@"
'')
(pkgs.writeTextDir "share/bash-completion/completions/uqmi" /* sh */''
_uqmi_complete() {
case ''${#COMP_WORDS[@]} in
2)
COMPREPLY=($(compgen -W "$(
${pkgs.uqmi}/bin/uqmi --help 2>&1 |
${pkgs.coreutils}/bin/tr , \\n |
${pkgs.gnused}/bin/sed -nr 's/^ *(-[a-z-]+).*/\1/p'
)" -- "''${COMP_WORDS[1]}"))
;;
esac
}
complete -F _uqmi_complete uqmi
'')
pkgs.uqmi
];
};
});
systemd.services.wwan = {
environment = {
SECRETS = "%d/secrets";
};
path = [
pkgs.busybox
pkgs.coreutils
pkgs.iproute2
pkgs.jq
pkgs.uqmi-wrapper
(pkgs.writeDashBin "get-interface" (
if cfg.interface != null then /* sh */ ''
echo ${cfg.interface}
'' else /* sh */ ''
exec ${pkgs.libqmi}/bin/qmicli -d ${cfg.device} -p --get-wwan-iface
''
))
];
serviceConfig = {
LoadCredential = [
"secrets:${cfg.secrets}"
];
Type = "oneshot";
RemainAfterExit = true;
SyslogIdentifier = "wwan";
ExecStart = pkgs.writeDash "tv.wwan.start.sh" ''
set -efu
interface=$(get-interface)
pin1_status=$(
uqmi --uim-get-sim-state |
jq -r '"\(.pin1_status)/\(.pin1_verify_tries)"'
)
case $pin1_status in
verified/*)
:
;;
not_verified/3)
pin1=$(jq .pin1 "$SECRETS")
echo "verifying PIN1" >&2
if ! uqmi --uim-verify-pin1 "$pin1"; then
echo "error: failed to verify PIN1" >&2
exit 1
fi
;;
not_verified/*)
echo "error: not trying to verify PIN1: not enough tries left" >&2
echo \
"please check your configuration in ${cfg.secrets}" \
" and verify if manually using:" \
" ${pkgs.uqmi}/bin/uqmi -d $device --uim-veriy-pin1 XXXX" \
>&2
exit 1
esac
raw_ip_path=/sys/class/net/$interface/qmi/raw_ip
raw_ip=$(cat "$raw_ip_path")
if [ "$raw_ip" != Y ]; then
echo "enabling raw-ip" >&2
if ! echo Y > "$raw_ip_path"; then
echo "error: failed to enable raw-ip" >&2
exit 1
fi
fi
operating_mode=$(uqmi --get-device-operating-mode | tr -d \")
case $operating_mode in
online)
:
;;
persistent_low_power|low_power)
echo "settings device operating mode to online" >&2
uqmi --set-device-operating-mode online
operating_mode=$(uqmi --get-device-operating-mode | tr -d \")
if test "$operating_mode" != online; then
echo "error: failed to set device operating mode to online" >&2
exit 1
fi
;;
*)
echo "error: don't know how to change device operating mode to online: $operating_mode" >&2
exit 1
esac
ip link set dev "$interface" up
data_status=$(uqmi --get-data-status | tr -d \")
case $data_status in
connected)
:
;;
disconnected)
echo "starting network (APN=${cfg.apn})" >&2
sleep 1
uqmi \
--start-network \
--autoconnect \
--apn ${cfg.apn} \
--ip-family ipv4
sleep 1
;;
*)
echo "error: unsupported data status: $data_status" >&2
exit 1
esac
udhcpc -q -f -n -i "$interface"
'';
Restart = "on-failure";
ExecStop = pkgs.writeDash "tv.wwan.stop.sh" ''
set -efu
interface=$(get-interface)
ip link set dev "$interface" down
uqmi --stop-network 0xFFFFFFFF --autoconnect
uqmi --sync
uqmi --set-device-operating-mode persistent_low_power
'';
};
};
users.users.root.packages = [
pkgs.uqmi-wrapper
];
tv.systemd.services.wwan.operators = cfg.operators;
};
}

View File

@ -1,24 +0,0 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
module Build where
import XMonad (Dimension)
import THEnv.JSON (getCompileEnvJSONExp)
myFont :: String
myFont =
"-schumacher-*-*-*-*-*-*-*-*-*-*-*-iso10646-*"
myScreenWidth :: Dimension
myScreenWidth =
$(getCompileEnvJSONExp (id @Dimension) "XMONAD_BUILD_SCREEN_WIDTH")
myTermFontWidth :: Dimension
myTermFontWidth =
$(getCompileEnvJSONExp (id @Dimension) "XMONAD_BUILD_TERM_FONT_WIDTH")
myTermPadding :: Dimension
myTermPadding =
2

View File

@ -1,18 +0,0 @@
{-# LANGUAGE ScopedTypeVariables #-}
module THEnv.JSON where
import Data.Aeson (eitherDecode,FromJSON)
import Data.ByteString.Lazy.Char8 (pack)
import Language.Haskell.TH.Syntax (Exp,Lift(lift),Q)
import THEnv (getCompileEnv)
import Control.Monad
getCompileEnvJSON :: (FromJSON a) => String -> Q a
getCompileEnvJSON name =
either error (id :: a -> a) . eitherDecode . pack <$> getCompileEnv name
getCompileEnvJSONExp ::
forall proxy a. (FromJSON a, Lift a) => proxy a -> String -> Q Exp
getCompileEnvJSONExp _ =
(lift :: a -> Q Exp) <=< getCompileEnvJSON

View File

@ -1,12 +1,18 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PatternSynonyms #-}
module Main (main) where
import System.Exit (exitFailure)
import XMonad.Hooks.EwmhDesktops (ewmh)
import XMonad.Hooks.RefocusLast (refocusLastLayoutHook, toggleFocus)
import Control.Exception
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 Text.Read (readEither)
import XMonad
@ -20,11 +26,18 @@ import XMonad.Actions.CycleWS (toggleWS)
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 (SpawnUrgencyHook(..), withUrgencyHook)
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)
@ -32,8 +45,6 @@ import XMonad.Actions.PerWorkspaceKeys (chooseAction)
import Shutdown (shutdown, newShutdownEventHandler)
import Build (myFont, myScreenWidth, myTermFontWidth, myTermPadding)
main :: IO ()
main = getArgs >>= \case
@ -45,21 +56,39 @@ main = getArgs >>= \case
(=??) :: Query a -> (a -> Bool) -> Query Bool
(=??) x p = fmap p x
readEnv :: Data.Aeson.FromJSON b => String -> IO b
readEnv name =
Data.Maybe.fromJust
. Data.Aeson.decodeStrict'
. Data.ByteString.Char8.pack
<$> getEnv name
mainNoArgs :: IO ()
mainNoArgs = do
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
workspaces0 <- getWorkspaces0
handleShutdownEvent <- newShutdownEventHandler
let
config =
id
$ withUrgencyHook (SpawnUrgencyHook "echo emit Urgency ")
ewmh
$ withUrgencyHookC
BorderUrgencyHook
{ urgencyBorderColor = "#ff0000"
}
UrgencyConfig
{ remindWhen = Dont
, suppressWhen = Never
}
$ def
{ terminal = {-pkg:rxvt_unicode-}"urxvtc"
{ terminal = {-pkg:alacritty-tv-}"alacritty"
, modMask = mod4Mask
, keys = myKeys
, keys = myKeys myTermFont
, workspaces = workspaces0
, layoutHook =
refocusLastLayoutHook $
smartBorders $
ResizableTall
1
@ -67,7 +96,7 @@ mainNoArgs = do
(fromIntegral (80 * myTermFontWidth + 2 * (myTermPadding + borderWidth def)) / fromIntegral myScreenWidth)
[]
|||
Full
StateFull
, manageHook =
composeAll
[ appName =? "fzmenu-urxvt" --> doCenterFloat
@ -113,20 +142,20 @@ forkFile path args env =
spawnRootTerm :: X ()
spawnRootTerm =
forkFile
{-pkg:rxvt_unicode-}"urxvtc"
["-name", "root-urxvt", "-e", "/run/wrappers/bin/su", "-"]
{-pkg:alacritty-tv-}"alacritty"
["--profile=root", "-e", "/run/wrappers/bin/su", "-"]
Nothing
myKeys :: XConfig Layout -> Map (KeyMask, KeySym) (X ())
myKeys conf = Map.fromList $
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:rxvt_unicode-}"urxvtc" [] Nothing)
, ((_4 , xK_x ), forkFile {-pkg:alacritty-tv-}"alacritty" ["--singleton"] Nothing)
, ((_4C , xK_x ), spawnRootTerm)
, ((_C , xK_Menu ), toggleWS)
@ -134,6 +163,8 @@ myKeys conf = Map.fromList $
, ((_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)
@ -162,6 +193,7 @@ myKeys conf = Map.fromList $
, ((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)
@ -188,21 +220,20 @@ myKeys conf = Map.fromList $
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 = myFont }
def { XMonad.Prompt.font = font }
xdeny :: X ()
xdeny =
forkFile
{-pkg-}"xterm"
[ "-fn", myFont
, "-geometry", "300x100"
, "-name", "AlertFloat"
, "-bg", "#E4002B"
, "-e", "sleep", "0.05"
]
Nothing
xdeny =
forkFile
{-pkg-}"xterm"
[ "-fn", font
, "-geometry", "300x100"
, "-name", "AlertFloat"
, "-bg", "#E4002B"
, "-e", "sleep", "0.05"
]
Nothing

View File

@ -23,7 +23,6 @@ executable xmonad
xmonad,
xmonad-contrib
other-modules:
Shutdown,
THEnv.JSON
Shutdown
default-language: Haskell2010
ghc-options: -O2 -Wall -threaded

View File

@ -0,0 +1,14 @@
self: super:
super.alacritty.overrideAttrs (old:
assert self.lib.versions.majorMinor old.version == "0.11";
{
version = "${old.version}-tv";
src = self.fetchFromGitHub {
owner = "4z3";
repo = "alacritty";
rev = "touchscreen-support-0.11";
hash = "sha256-oA4earrJ7lPVSBm9vRccWatAQ49hfDKsa7M72B5uQpY=";
};
}
)

View File

@ -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=";
};
})

View File

@ -1,4 +1,6 @@
{ pkgs }:
{ pkgs
, variant ? "x220"
}:
let
lib = import ./lib;
@ -6,7 +8,7 @@ let
program = "${pkgs.font-size-alacritty}/bin/font-size-alacritty";
args = [arg];
};
config = {
configs.default = lib.recursiveUpdate variants.${variant} {
bell.animation = "EaseOut";
bell.duration = 50;
bell.color = "#ff00ff";
@ -30,10 +32,6 @@ let
colors.bright.cyan = "#72fbfb";
colors.bright.white = "#fbfbfb";
draw_bold_text_with_bright_colors = true;
font.normal.family = "Clean";
font.bold.family = "Clean";
font.bold.style = "Regular";
font.size = 10;
hints.enabled = [
{
regex = "(ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)[^\\u0000-\\u001F\\u007F-\\u009F<>\"\\s{-}\\^`]+";
@ -42,15 +40,73 @@ let
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-1";
font.bold.family = "iosevka-tv-1";
font.italic.family = "iosevka-tv-1";
font.bold_italic.family = "iosevka-tv-1";
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"; }
];
scrolling.multiplier = 8;
};
config-file = pkgs.writeJSON "alacritty-tv.json" config;
writeProfile = name: config: let
config-file =
assert lib.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/cp ${config-file} "$HOME"/.alacritty.yml
fi
'';
in
pkgs.symlinkJoin {
@ -58,31 +114,35 @@ pkgs.symlinkJoin {
paths = [
(pkgs.writeDashBin "alacritty" ''
# usage:
# alacritty [--singleton] [ARGS...]
# alacritty [--profile=PROFILE] [--singleton] [ARGS...]
# where
# PROFILE one of ${lib.toJSON (lib.attrNames configs)}
set -efu
# Use home so Alacritty can find the configuration without arguments.
# HOME will be reset once in Alacritty.
HOME=$TMPDIR/Alacritty
export HOME
case ''${1-} in
${lib.concatMapStringsSep "\n" (name: /* sh */ ''
--${lib.shell.escape name}|--profile=${lib.shell.escape name})
shift
profile=${writeProfile name configs.${name}}
;;
'') (lib.attrNames configs)}
*)
profile=${writeProfile "default" configs.default}
;;
esac
# Install stored configuration if it has changed.
# This allows for both declarative updates and runtime modifications.
${pkgs.coreutils}/bin/mkdir -p "$HOME"
if test "$(${pkgs.coreutils}/bin/cat "$HOME"/ref)" != ${config-file}; then
echo ${config-file} > "$HOME"/ref
${pkgs.coreutils}/bin/cp ${config-file} "$HOME"/.alacritty.yml
fi
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

View File

@ -6,7 +6,7 @@ set -efu
case ${FZMENU_PHASE-0} in
0)
export FZMENU_PHASE=1
exec setsid -f urxvt -name fzmenu-urxvt -e dash "$0"
exec setsid -f terminal dash "$0"
;;
1)
if result=$(

View File

@ -6,7 +6,7 @@ set -efu
case ${FZMENU_PHASE-0} in
0)
export FZMENU_PHASE=1
exec setsid -f urxvt -name fzmenu-urxvt -e dash "$0"
exec setsid -f terminal dash "$0"
;;
1)
if result=$(

View File

@ -1,5 +1,15 @@
{ 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
@ -16,9 +26,9 @@ pkgs.runCommand "fzmenu" {
(pkgs.pass.withExtensions (ext: [
ext.pass-otp
]))
pkgs.rxvt_unicode
pkgs.utillinux
pkgs.xdotool
terminal
]}
substituteInPlace $out/bin/passmenu \
@ -31,8 +41,8 @@ pkgs.runCommand "fzmenu" {
(pkgs.pass.withExtensions (ext: [
ext.pass-otp
]))
pkgs.rxvt_unicode
pkgs.utillinux
pkgs.xdotool
terminal
]}
''

View File

@ -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 = "iosevka-tv-1";
}

View File

@ -2,10 +2,10 @@
# cannot use pkgs.vimPlugins.fzf-vim as it's missing :Rg
pkgs.vimUtils.buildVimPlugin {
name = "fzf-2018-11-14";
name = "fzf-2023-01-16";
src = pkgs.fetchgit {
url = https://github.com/junegunn/fzf.vim;
rev = "ad1833ecbc9153b6e34a4292dc089a58c4bcb8dc";
sha256 = "1z2q71q6l9hq9fqfqpj1svhyk4yk1bzw1ljhksx4bnpz8gkfbx2m";
rev = "bdf48c282ad2174c25c059b3cdb7956427b07a99";
hash = "sha256-eCCk+Q596Ljjdtjd0cYGqR77K3Me5gf+ts5icP22S3Y=";
};
}

View File

@ -42,5 +42,8 @@ in {
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
'';
}))

View File

@ -1,17 +1,6 @@
{ pkgs }:
pkgs.tv.vim.makePlugin (pkgs.write "vim-tv" {
#
# Haskell
#
"/ftplugin/haskell.vim".text = ''
if exists("g:vim_tv_ftplugin_haskell_loaded")
finish
endif
let g:vim_tv_ftplugin_haskell_loaded = 1
setlocal iskeyword+='
'';
#
# TODO
#