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 = hostNames =
["github.com"] ["github.com"]
++ ++
# List generated with (IPv6 addresses are currently ignored): # update known-hosts.json using ./update
# 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
lib.importJSON ./known-hosts.json lib.importJSON ./known-hosts.json
; ;
publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ=="; 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 = [ flakeIgnore = [
"E226" "E226"
"E302" "E302"
"E305" "E305"
"E501" "E501"
"F401" "F401"
"W504"
]; ];
} /* python */ '' } /* python */ ''
import base64 import base64

View File

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

View File

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

View File

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

View File

@ -1,8 +1,8 @@
with import ./lib; with import ./lib;
{ config, pkgs, ... }: { { config, modulesPath, pkgs, ... }: {
imports = [ 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)) [ krebs.nixpkgs.allowUnfreePredicate = pkg: any (eq (packageName pkg)) [

View File

@ -16,6 +16,7 @@ with import ./lib;
./nets/hkw.nix ./nets/hkw.nix
./networkd.nix ./networkd.nix
./nginx ./nginx
./nix.nix
./pki ./pki
./ssh.nix ./ssh.nix
./sshd.nix ./sshd.nix
@ -44,21 +45,12 @@ with import ./lib;
time.timeZone = "Europe/Berlin"; 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; nixpkgs.config.allowUnfree = false;
} }
{ {
environment.homeBinInPath = true;
environment.profileRelativeEnvVars.PATH = mkForce [ "/bin" ]; environment.profileRelativeEnvVars.PATH = mkForce [ "/bin" ];
environment.systemPackages = with pkgs; [ 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 ../smartd.nix
{ {
nix.buildCores = 2; nix.settings.cores = 2;
nix.maxJobs = 2; nix.settings.max-jobs = 2;
} }
(if lib.versionAtLeast (lib.versions.majorMinor lib.version) "21.11" then { (if lib.versionAtLeast (lib.versions.majorMinor lib.version) "21.11" then {
nix.daemonCPUSchedPolicy = "batch"; 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"; environment.variables.VIMINIT = ":so /etc/vimrc";
}; };
extra-runtimepath = pkgs.tv.vim.makeRuntimePath [ base-plugins = [
pkgs.tv.vimPlugins.elixir
pkgs.tv.vimPlugins.file-line pkgs.tv.vimPlugins.file-line
pkgs.tv.vimPlugins.fzf
pkgs.tv.vimPlugins.hack 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.jq
pkgs.tv.vimPlugins.nix pkgs.tv.vimPlugins.nix
pkgs.tv.vimPlugins.showsyntax pkgs.tv.vimPlugins.showsyntax
pkgs.tv.vimPlugins.tv pkgs.tv.vimPlugins.tv
pkgs.tv.vimPlugins.vim pkgs.tv.vimPlugins.vim
pkgs.vimPlugins.fzfWrapper pkgs.vimPlugins.fzfWrapper
pkgs.vimPlugins.undotree
pkgs.vimPlugins.vim-nftables pkgs.vimPlugins.vim-nftables
]; ];
@ -58,7 +71,9 @@ with import ./lib;
]; ];
}; };
vimrc = pkgs.writeText "vimrc" '' vimrc = pkgs.writeText "vimrc" /* vim */ ''
vim9script
set nocompatible set nocompatible
set autoindent set autoindent
@ -71,7 +86,7 @@ with import ./lib;
set mouse=a set mouse=a
set noruler set noruler
set pastetoggle=<INS> set pastetoggle=<INS>
set runtimepath=${extra-runtimepath},$VIMRUNTIME set runtimepath=${pkgs.tv.vim.makeRuntimePath base-plugins},$VIMRUNTIME
set shortmess+=I set shortmess+=I
set showcmd set showcmd
set showmatch set showmatch
@ -88,13 +103,15 @@ with import ./lib;
set wildmenu set wildmenu
set wildmode=longest,full set wildmode=longest,full
set runtimepath^=${pkgs.tv.vim.makeRuntimePath extra-plugins}
syntax on
set et ts=2 sts=2 sw=2 set et ts=2 sts=2 sw=2
filetype plugin indent on filetype plugin indent on
set t_Co=256 set t_Co=256
colorscheme hack colorscheme hack
syntax on
au Syntax * syn match Garbage containedin=ALL /\s\+$/ au Syntax * syn match Garbage containedin=ALL /\s\+$/
\ | syn match TabStop containedin=ALL /\t\+/ \ | syn match TabStop containedin=ALL /\t\+/
@ -115,30 +132,52 @@ with import ./lib;
nnoremap <f1> :tabp<cr> nnoremap <f1> :tabp<cr>
nnoremap <f2> :tabn<cr> nnoremap <f2> :tabn<cr>
inoremap <f1> <esc>:tabp<cr> imap <f1> <esc><f1>
inoremap <f2> <esc>:tabn<cr> 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> noremap <f3> :ShowSyntax<cr>
" <C-{Up,Down,Right,Left> # <C-{Up,Down,Right,Left}>
noremap <esc>Oa <nop> | noremap! <esc>Oa <nop> noremap <esc>Oa <nop> | noremap! <esc>Oa <nop>
noremap <esc>Ob <nop> | noremap! <esc>Ob <nop> noremap <esc>Ob <nop> | noremap! <esc>Ob <nop>
noremap <esc>Oc <nop> | noremap! <esc>Oc <nop> noremap <esc>Oc <nop> | noremap! <esc>Oc <nop>
noremap <esc>Od <nop> | noremap! <esc>Od <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>[a <nop> | noremap! <esc>[a <nop>
noremap <esc>[b <nop> | noremap! <esc>[b <nop> noremap <esc>[b <nop> | noremap! <esc>[b <nop>
noremap <esc>[c <nop> | noremap! <esc>[c <nop> noremap <esc>[c <nop> | noremap! <esc>[c <nop>
noremap <esc>[d <nop> | noremap! <esc>[d <nop> noremap <esc>[d <nop> | noremap! <esc>[d <nop>
vnoremap u <nop> vnoremap u <nop>
" fzf # fzf
nnoremap <esc>q :Buffers<cr> nnoremap <esc>q :Buffers<cr>
nnoremap <esc>f :Files<cr> nnoremap <esc>f :Files<cr>
nnoremap <esc>w :Rg<cr> nnoremap <esc>w :Rg<cr>
" edit alternate buffer # edit alternate buffer
" For some reason neither putting <ctrl>6 nor <ctrl>^ works here... # For some reason neither putting <ctrl>6 nor <ctrl>^ works here...
nnoremap <esc>a  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 ./hw.nix
./im.nix ./im.nix
./iptables.nix ./iptables.nix
./lidControl.nix
./org.freedesktop.machine1.host-shell.nix ./org.freedesktop.machine1.host-shell.nix
./systemd.nix
./slock.nix ./slock.nix
./x0vncserver.nix ./x0vncserver.nix
./Xresources.nix ./Xresources.nix
./wwan.nix
]; ];
} }

View File

@ -34,6 +34,10 @@ with import ./lib;
type = with types; listOf str; type = with types; listOf str;
default = []; default = [];
}; };
filter.Wiregrill = mkOption {
type = with types; listOf str;
default = [];
};
}; };
}; };
}; };
@ -66,6 +70,16 @@ with import ./lib;
default = []; 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 { extra = mkOption {
default = {}; default = {};
type = extraTypes.rules; type = extraTypes.rules;
@ -141,6 +155,7 @@ with import ./lib;
:FORWARD DROP [0:0] :FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0]
:Retiolum - [0:0] :Retiolum - [0:0]
:Wiregrill - [0:0]
${concatMapStringsSep "\n" (rule: "-A INPUT ${rule}") ([] ${concatMapStringsSep "\n" (rule: "-A INPUT ${rule}") ([]
++ [ ++ [
"-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT" "-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-tcp (unique (map toString cfg.input-internet-accept-tcp))
++ map accept-udp (unique (map toString cfg.input-internet-accept-udp)) ++ map accept-udp (unique (map toString cfg.input-internet-accept-udp))
++ ["-i retiolum -j Retiolum"] ++ ["-i retiolum -j Retiolum"]
++ ["-i wiregrill -j Wiregrill"]
)} )}
${formatTable cfg.extra.filter} ${formatTable cfg.extra.filter}
${formatTable cfg."extra${toString iptables-version}".filter} ${formatTable cfg."extra${toString iptables-version}".filter}
@ -170,6 +186,23 @@ with import ./lib;
]; ];
}."ip${toString iptables-version}tables" }."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 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 LambdaCase #-}
{-# LANGUAGE PatternSynonyms #-}
module Main (main) where module Main (main) where
import System.Exit (exitFailure) import System.Exit (exitFailure)
import XMonad.Hooks.EwmhDesktops (ewmh)
import XMonad.Hooks.RefocusLast (refocusLastLayoutHook, toggleFocus)
import Control.Exception import Control.Exception
import Control.Monad.Extra (whenJustM) import Control.Monad.Extra (whenJustM)
import qualified Data.Aeson
import qualified Data.ByteString.Char8
import qualified Data.List import qualified Data.List
import qualified Data.Maybe
import Graphics.X11.ExtraTypes.XF86 import Graphics.X11.ExtraTypes.XF86
import Text.Read (readEither) import Text.Read (readEither)
import XMonad import XMonad
@ -20,11 +26,18 @@ import XMonad.Actions.CycleWS (toggleWS)
import XMonad.Layout.NoBorders ( smartBorders ) import XMonad.Layout.NoBorders ( smartBorders )
import XMonad.Layout.ResizableTile (ResizableTall(ResizableTall)) import XMonad.Layout.ResizableTile (ResizableTall(ResizableTall))
import XMonad.Layout.ResizableTile (MirrorResize(MirrorExpand,MirrorShrink)) import XMonad.Layout.ResizableTile (MirrorResize(MirrorExpand,MirrorShrink))
import XMonad.Layout.StateFull (pattern StateFull)
import qualified XMonad.Prompt import qualified XMonad.Prompt
import qualified XMonad.StackSet as W import qualified XMonad.StackSet as W
import Data.Map (Map) import Data.Map (Map)
import qualified Data.Map as 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 XMonad.Hooks.ManageHelpers (doCenterFloat,doRectFloat)
import Data.Ratio import Data.Ratio
import XMonad.Hooks.Place (placeHook, smart) import XMonad.Hooks.Place (placeHook, smart)
@ -32,8 +45,6 @@ import XMonad.Actions.PerWorkspaceKeys (chooseAction)
import Shutdown (shutdown, newShutdownEventHandler) import Shutdown (shutdown, newShutdownEventHandler)
import Build (myFont, myScreenWidth, myTermFontWidth, myTermPadding)
main :: IO () main :: IO ()
main = getArgs >>= \case main = getArgs >>= \case
@ -45,21 +56,39 @@ main = getArgs >>= \case
(=??) :: Query a -> (a -> Bool) -> Query Bool (=??) :: Query a -> (a -> Bool) -> Query Bool
(=??) x p = fmap p x (=??) 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 :: IO ()
mainNoArgs = do 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 workspaces0 <- getWorkspaces0
handleShutdownEvent <- newShutdownEventHandler handleShutdownEvent <- newShutdownEventHandler
let let
config = config =
id ewmh
$ withUrgencyHook (SpawnUrgencyHook "echo emit Urgency ") $ withUrgencyHookC
BorderUrgencyHook
{ urgencyBorderColor = "#ff0000"
}
UrgencyConfig
{ remindWhen = Dont
, suppressWhen = Never
}
$ def $ def
{ terminal = {-pkg:rxvt_unicode-}"urxvtc" { terminal = {-pkg:alacritty-tv-}"alacritty"
, modMask = mod4Mask , modMask = mod4Mask
, keys = myKeys , keys = myKeys myTermFont
, workspaces = workspaces0 , workspaces = workspaces0
, layoutHook = , layoutHook =
refocusLastLayoutHook $
smartBorders $ smartBorders $
ResizableTall ResizableTall
1 1
@ -67,7 +96,7 @@ mainNoArgs = do
(fromIntegral (80 * myTermFontWidth + 2 * (myTermPadding + borderWidth def)) / fromIntegral myScreenWidth) (fromIntegral (80 * myTermFontWidth + 2 * (myTermPadding + borderWidth def)) / fromIntegral myScreenWidth)
[] []
||| |||
Full StateFull
, manageHook = , manageHook =
composeAll composeAll
[ appName =? "fzmenu-urxvt" --> doCenterFloat [ appName =? "fzmenu-urxvt" --> doCenterFloat
@ -113,20 +142,20 @@ forkFile path args env =
spawnRootTerm :: X () spawnRootTerm :: X ()
spawnRootTerm = spawnRootTerm =
forkFile forkFile
{-pkg:rxvt_unicode-}"urxvtc" {-pkg:alacritty-tv-}"alacritty"
["-name", "root-urxvt", "-e", "/run/wrappers/bin/su", "-"] ["--profile=root", "-e", "/run/wrappers/bin/su", "-"]
Nothing Nothing
myKeys :: XConfig Layout -> Map (KeyMask, KeySym) (X ()) myKeys :: String -> XConfig Layout -> Map (KeyMask, KeySym) (X ())
myKeys conf = Map.fromList $ myKeys font conf = Map.fromList $
[ ((_4 , xK_Escape ), forkFile {-pkg-}"slock" [] Nothing) [ ((_4 , xK_Escape ), forkFile {-pkg-}"slock" [] Nothing)
, ((_4S , xK_c ), kill) , ((_4S , xK_c ), kill)
, ((_4 , xK_o ), forkFile {-pkg:fzmenu-}"otpmenu" [] Nothing) , ((_4 , xK_o ), forkFile {-pkg:fzmenu-}"otpmenu" [] Nothing)
, ((_4 , xK_p ), forkFile {-pkg:fzmenu-}"passmenu" [] 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) , ((_4C , xK_x ), spawnRootTerm)
, ((_C , xK_Menu ), toggleWS) , ((_C , xK_Menu ), toggleWS)
@ -134,6 +163,8 @@ myKeys conf = Map.fromList $
, ((_4 , xK_space ), withFocused $ \w -> ifM (isFloatingX w) xdeny $ sendMessage NextLayout) , ((_4 , xK_space ), withFocused $ \w -> ifM (isFloatingX w) xdeny $ sendMessage NextLayout)
, ((_4M , xK_space ), withFocused $ \w -> ifM (isFloatingX w) xdeny $ resetLayout) , ((_4M , xK_space ), withFocused $ \w -> ifM (isFloatingX w) xdeny $ resetLayout)
, ((_4 , xK_l ), toggleFocus)
, ((_4 , xK_m ), windows W.focusMaster) , ((_4 , xK_m ), windows W.focusMaster)
, ((_4 , xK_j ), windows W.focusDown) , ((_4 , xK_j ), windows W.focusDown)
, ((_4 , xK_k ), windows W.focusUp) , ((_4 , xK_k ), windows W.focusUp)
@ -162,6 +193,7 @@ myKeys conf = Map.fromList $
, ((0, xF86XK_AudioLowerVolume), audioLowerVolume) , ((0, xF86XK_AudioLowerVolume), audioLowerVolume)
, ((0, xF86XK_AudioRaiseVolume), audioRaiseVolume) , ((0, xF86XK_AudioRaiseVolume), audioRaiseVolume)
, ((0, xF86XK_AudioMute), audioMute) , ((0, xF86XK_AudioMute), audioMute)
, ((0, xF86XK_AudioMicMute), audioMicMute)
, ((_4, xF86XK_AudioMute), pavucontrol []) , ((_4, xF86XK_AudioMute), pavucontrol [])
, ((_4, xK_Prior), forkFile {-pkg-}"xcalib" ["-invert", "-alter"] Nothing) , ((_4, xK_Prior), forkFile {-pkg-}"xcalib" ["-invert", "-alter"] Nothing)
@ -188,21 +220,20 @@ myKeys conf = Map.fromList $
audioLowerVolume = amixer ["-q", "sset", "Master", "5%-"] audioLowerVolume = amixer ["-q", "sset", "Master", "5%-"]
audioRaiseVolume = amixer ["-q", "sset", "Master", "5%+"] audioRaiseVolume = amixer ["-q", "sset", "Master", "5%+"]
audioMute = amixer ["-q", "sset", "Master", "toggle"] audioMute = amixer ["-q", "sset", "Master", "toggle"]
audioMicMute = amixer ["-q", "sset", "Capture", "toggle"]
resetLayout = setLayout $ XMonad.layoutHook conf resetLayout = setLayout $ XMonad.layoutHook conf
promptXPConfig = promptXPConfig =
def { XMonad.Prompt.font = myFont } def { XMonad.Prompt.font = font }
xdeny =
xdeny :: X () forkFile
xdeny = {-pkg-}"xterm"
forkFile [ "-fn", font
{-pkg-}"xterm" , "-geometry", "300x100"
[ "-fn", myFont , "-name", "AlertFloat"
, "-geometry", "300x100" , "-bg", "#E4002B"
, "-name", "AlertFloat" , "-e", "sleep", "0.05"
, "-bg", "#E4002B" ]
, "-e", "sleep", "0.05" Nothing
]
Nothing

View File

@ -23,7 +23,6 @@ executable xmonad
xmonad, xmonad,
xmonad-contrib xmonad-contrib
other-modules: other-modules:
Shutdown, Shutdown
THEnv.JSON
default-language: Haskell2010 default-language: Haskell2010
ghc-options: -O2 -Wall -threaded 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 let
lib = import ./lib; lib = import ./lib;
@ -6,7 +8,7 @@ let
program = "${pkgs.font-size-alacritty}/bin/font-size-alacritty"; program = "${pkgs.font-size-alacritty}/bin/font-size-alacritty";
args = [arg]; args = [arg];
}; };
config = { configs.default = lib.recursiveUpdate variants.${variant} {
bell.animation = "EaseOut"; bell.animation = "EaseOut";
bell.duration = 50; bell.duration = 50;
bell.color = "#ff00ff"; bell.color = "#ff00ff";
@ -30,10 +32,6 @@ let
colors.bright.cyan = "#72fbfb"; colors.bright.cyan = "#72fbfb";
colors.bright.white = "#fbfbfb"; colors.bright.white = "#fbfbfb";
draw_bold_text_with_bright_colors = true; draw_bold_text_with_bright_colors = true;
font.normal.family = "Clean";
font.bold.family = "Clean";
font.bold.style = "Regular";
font.size = 10;
hints.enabled = [ hints.enabled = [
{ {
regex = "(ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)[^\\u0000-\\u001F\\u007F-\\u009F<>\"\\s{-}\\^`]+"; 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"; 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_bindings = [
{ key = "Up"; mods = "Shift|Control"; command = font-size "=14"; } { key = "Up"; mods = "Shift|Control"; command = font-size "=14"; }
{ key = "Up"; mods = "Control"; command = font-size "+1"; } { key = "Up"; mods = "Control"; command = font-size "+1"; }
{ key = "Down"; mods = "Control"; command = font-size "-1"; } { key = "Down"; mods = "Control"; command = font-size "-1"; }
{ key = "Down"; mods = "Shift|Control"; command = font-size "=0"; } { 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 in
pkgs.symlinkJoin { pkgs.symlinkJoin {
@ -58,31 +114,35 @@ pkgs.symlinkJoin {
paths = [ paths = [
(pkgs.writeDashBin "alacritty" '' (pkgs.writeDashBin "alacritty" ''
# usage: # usage:
# alacritty [--singleton] [ARGS...] # alacritty [--profile=PROFILE] [--singleton] [ARGS...]
# where
# PROFILE one of ${lib.toJSON (lib.attrNames configs)}
set -efu set -efu
# Use home so Alacritty can find the configuration without arguments. case ''${1-} in
# HOME will be reset once in Alacritty. ${lib.concatMapStringsSep "\n" (name: /* sh */ ''
HOME=$TMPDIR/Alacritty --${lib.shell.escape name}|--profile=${lib.shell.escape name})
export HOME 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 case ''${1-} in
--singleton) --singleton)
shift shift
if ! ${pkgs.alacritty}/bin/alacritty msg create-window "$@"; then if ! ${pkgs.alacritty}/bin/alacritty msg create-window "$@"; then
. "$profile"
${pkgs.alacritty}/bin/alacritty "$@" & ${pkgs.alacritty}/bin/alacritty "$@" &
fi fi
;; ;;
*) *)
. "$profile"
exec ${pkgs.alacritty}/bin/alacritty "$@" exec ${pkgs.alacritty}/bin/alacritty "$@"
;; ;;
esac esac

View File

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

View File

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

View File

@ -1,5 +1,15 @@
{ lib, pkgs, stdenv }: { 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" { pkgs.runCommand "fzmenu" {
} /* sh */ '' } /* sh */ ''
mkdir $out mkdir $out
@ -16,9 +26,9 @@ pkgs.runCommand "fzmenu" {
(pkgs.pass.withExtensions (ext: [ (pkgs.pass.withExtensions (ext: [
ext.pass-otp ext.pass-otp
])) ]))
pkgs.rxvt_unicode
pkgs.utillinux pkgs.utillinux
pkgs.xdotool pkgs.xdotool
terminal
]} ]}
substituteInPlace $out/bin/passmenu \ substituteInPlace $out/bin/passmenu \
@ -31,8 +41,8 @@ pkgs.runCommand "fzmenu" {
(pkgs.pass.withExtensions (ext: [ (pkgs.pass.withExtensions (ext: [
ext.pass-otp ext.pass-otp
])) ]))
pkgs.rxvt_unicode
pkgs.utillinux pkgs.utillinux
pkgs.xdotool 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 # cannot use pkgs.vimPlugins.fzf-vim as it's missing :Rg
pkgs.vimUtils.buildVimPlugin { pkgs.vimUtils.buildVimPlugin {
name = "fzf-2018-11-14"; name = "fzf-2023-01-16";
src = pkgs.fetchgit { src = pkgs.fetchgit {
url = https://github.com/junegunn/fzf.vim; url = https://github.com/junegunn/fzf.vim;
rev = "ad1833ecbc9153b6e34a4292dc089a58c4bcb8dc"; rev = "bdf48c282ad2174c25c059b3cdb7956427b07a99";
sha256 = "1z2q71q6l9hq9fqfqpj1svhyk4yk1bzw1ljhksx4bnpz8gkfbx2m"; hash = "sha256-eCCk+Q596Ljjdtjd0cYGqR77K3Me5gf+ts5icP22S3Y=";
}; };
} }

View File

@ -42,5 +42,8 @@ in {
hi diffRemoved ctermfg=009 hi diffRemoved ctermfg=009
hi Search cterm=NONE ctermbg=216 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 }:
pkgs.tv.vim.makePlugin (pkgs.write "vim-tv" { 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 # TODO
# #