]> gitweb.ps.run Git - flake_thinkpad/blob - home-ps.nix
update
[flake_thinkpad] / home-ps.nix
1 { config, pkgs, lib, wallpaper, ... }:
2
3 let
4   theme = pkgs.qogir-theme.override { tweaks = [ "square" ]; };
5   markdownStyleHeader = pkgs.writeText "style.html" ''
6     <style type="text/css">
7     html{
8       margin:40px auto;
9       max-width:650px;
10       line-height:1.6;
11       font-size:18px;
12       color:#444;
13       background-color:#EEE;
14       padding:0 10px
15     }
16     @media (prefers-color-scheme: dark) {
17     html{
18       color:#CCC;
19       background-color:#333;
20     }
21     }
22     h1,h2,h3{line-height:1.2}
23     </style>
24   '';
25   markdownCaddyfile = pkgs.writeText "Caddyfile" ''
26     :8123
27
28     encode zstd gzip
29     templates
30     file_server browse {
31             root "/"
32             hide ".*"
33     }
34
35     @md <<CEL
36       {file}.endsWith(".md")
37       || {file}.endsWith(".MD")
38       CEL
39
40     header @md Content-Type "text/html; charset=UTF-8"
41     respond @md <<HTML
42             <!DOCTYPE html>
43             <html>
44                     <head>
45                             <title>{{ "{file.base}" }}</title>
46                             <link rel="stylesheet" href="https://sindresorhus.com/github-markdown-css/github-markdown.css">
47                             <style>
48                             .markdown-body {
49                                         box-sizing: border-box;
50                                         min-width: 200px;
51                                         max-width: 980px;
52                                         margin: 0 auto;
53                                         padding: 45px;
54                                 }
55                             </style>
56                     </head>
57                     <body class="markdown-body">
58                     {{
59                     markdown (include "{path}")
60                     }}
61                     </body>
62             </html>
63             HTML 200
64   '';
65 in
66 {
67   # Home Manager needs a bit of information about you and the paths it should
68   # manage.
69   home.username = "ps";
70   home.homeDirectory = "/home/ps";
71
72   services.xcape = {
73     enable = true;
74     mapExpression = {
75       Caps_Lock = "Escape";
76     };
77   };
78
79   xfconf.settings = {
80     xfce4-desktop = {
81       "backdrop/screen0/monitor0/image-path" = "${wallpaper}";
82       "backdrop/screen0/monitor0/image-show" = true;
83       "backdrop/screen0/monitor0/image-style" = 5;
84     };
85   };
86
87   systemd.user.services.markdownCaddy = {
88     Unit = {
89       Description = "Run a web server serving Markdown files.";
90       Wants = [ "network-online.target" ];
91       After = [ "network-online.target" ];
92     };
93     Install = {
94       WantedBy = [ "default.target" ];
95     };
96     Service = {
97       WorkingDirectory = "/";
98       ExecStart = "${pkgs.writeShellScript "markdown-caddy" ''
99         ${pkgs.caddy}/bin/caddy run --config ${markdownCaddyfile} --adapter caddyfile
100       ''}";
101     };
102   };
103   
104   xsession.windowManager.i3 = {
105     enable = true;
106     config = {
107       bars = [];
108       modifier = "Mod4";
109       terminal = "${pkgs.kitty}/bin/kitty";
110       gaps = { inner = 0; outer = 0; };
111       keybindings =
112         let
113           mod = config.xsession.windowManager.i3.config.modifier;
114           i3-next = pkgs.writers.writePython3 "i3-next" {} ''
115             import json
116             from subprocess import check_output
117
118             workspaces = json.loads(check_output(
119               ["${pkgs.i3}/bin/i3-msg",
120                "-t", "get_workspaces"]))
121
122             outputs = {}
123             activeOutput = ""
124             activeWorkspace = -1
125
126             for w in workspaces:
127                 output = w["output"]
128                 workspace = int(w["num"])
129                 if output not in outputs:
130                     outputs[output] = set()
131                 outputs[output].add(workspace)
132                 if w["focused"]:
133                     activeOutput = output
134                     activeWorkspace = workspace
135
136             workspacesSorted = sorted(outputs[activeOutput])
137             activeWorkspaceIndex = workspacesSorted.index(activeWorkspace)
138
139             if activeWorkspaceIndex < len(workspacesSorted) - 1:
140                 print(workspacesSorted[activeWorkspaceIndex + 1])
141             else:
142                 allWorkspaces = set()
143                 for o in outputs.values():
144                     allWorkspaces = allWorkspaces.union(o)
145                 allWorkspacesSorted = sorted(allWorkspaces)
146                 print(allWorkspacesSorted[-1]+1)
147           '';
148   
149           i3-empty = pkgs.writers.writePython3 "i3-empty" {} ''
150             import json
151             from subprocess import check_output
152
153             workspaces = json.loads(check_output(
154               ["${pkgs.i3}/bin/i3-msg",
155                "-t", "get_workspaces"]))
156
157             nextWorkspace = 1
158       
159             for w in workspaces:
160                 wNum = int(w["num"])
161                 if wNum >= nextWorkspace:
162                     nextWorkspace = wNum + 1
163
164             print(nextWorkspace)
165           '';
166           
167           i3-max = pkgs.writers.writePython3 "i3-max" {} ''
168             import json
169             from subprocess import check_output
170
171             workspaces = json.loads(check_output(
172               ["${pkgs.i3}/bin/i3-msg",
173                "-t", "get_workspaces"]))
174
175             result = "MAX"
176       
177             for w in workspaces:
178                 wName = w["name"]
179                 wFocused = w["focused"]
180                 if wName == "MAX" and wFocused:
181                     result = "back_and_forth"
182                     break
183
184             print(f"move window to workspace {result}; workspace {result}")
185           '';
186           i3-move-max = pkgs.writers.writePython3 "i3-move-max" {} ''
187             import json
188             from subprocess import check_output
189
190             workspaces = json.loads(check_output(
191               ["${pkgs.i3}/bin/i3-msg",
192                "-t", "get_workspaces"]))
193
194             result = "MAX"
195       
196             for w in workspaces:
197                 wName = w["name"]
198                 wFocused = w["focused"]
199                 if wName == "MAX" and wFocused:
200                     result = "back_and_forth"
201                     break
202
203             print(f"workspace {result}")
204           '';
205         in lib.mkOptionDefault
206           {
207             # "${mod}+d" = "exec --no-startup-id krunner";
208             # "${mod}+Shift+p" = "exec --no-startup-id set-wallpaper";
209             "${mod}+Shift+Return" = "exec --no-startup-id ${pkgs.kitty}/bin/kitty -d $(${pkgs.xcwd}/bin/xcwd)";
210             "${mod}+BackSpace" = "kill";
211             "${mod}+Prior" = "workspace prev_on_output";
212             "${mod}+Next" = "exec --no-startup-id i3-msg workspace number $(${i3-next})";
213             "${mod}+End" = "exec --no-startup-id i3-msg workspace $(${i3-empty})";
214             "${mod}+Shift+Prior" = "move container to workspace prev_on_output";
215             "${mod}+Shift+Next" = "exec --no-startup-id i3-msg move container to workspace number $(${i3-next})";
216             "${mod}+Shift+End" = "exec --no-startup-id i3-msg move container to workspace $(${i3-empty})";
217             "${mod}+Ctrl+Left" = "move workspace to output left";
218             "${mod}+Ctrl+Right" = "move workspace to output right";
219             "${mod}+y" = "exec --no-startup-id mirror-phone";
220             "${mod}+n" = "exec ${pkgs.kitty}/bin/kitty -d ~/sync/txt nvim -c 'autocmd VimEnter * ++once Telescope find_files'";
221             "${mod}+m" = "exec --no-startup-id i3-msg $(${i3-max})";
222             "${mod}+b" = "split toggle; layout tabbed";
223             "${mod}+Shift+m" = "exec --no-startup-id i3-msg $(${i3-move-max})";
224             "${mod}+Shift+p" = "exec --no-startup-id ${pkgs.autorandr}/bin/autorandr --match-edid -c -f";
225           };
226     };
227     extraConfig = ''
228       for_window [window_role="pop-up"] floating enable
229       for_window [window_role="task_dialog"] floating enable
230       for_window [workspace="9"] floating enable
231
232       for_window [class="kitty-popup"] floating enable
233       for_window [class="Xfce4-appfinder"] floating enable
234       for_window [class="yakuake"] floating enable
235       for_window [class="systemsettings"] floating enable
236       for_window [title="win7"] floating enable; border none
237       for_window [title="Arbeitsfläche.*"] kill, floating enable, border none
238
239       # class                 border  backgr. text    indicator child_border
240       client.focused          #000000bf #000000bf #e6ebef #000000bf   #000000bf
241       client.focused_inactive #00000080 #00000080 #e6ebef #00000080   #00000080
242       client.unfocused        #00000040 #00000040 #e6ebef #00000040   #00000040
243       client.urgent           #2f343a #900000 #e6ebef #900000   #2f343a
244       client.placeholder      #000000 #0c0c0c #e6ebef #000000   #0c0c0c
245
246       focus_follows_mouse no
247       mouse_warping none
248       popup_during_fullscreen all
249     '';
250   };
251
252   services.picom = {
253     enable = true;
254     vSync = true;
255     opacityRules = [
256       "0:_NET_WM_STATE@[*]:a = '_NET_WM_STATE_HIDDEN'"
257     ];
258   };
259
260   programs.git = {
261     userName = "patrick-scho";
262     userEmail = "patrick.schoenberger@posteo.de";
263     includes = [{ contents = {
264         user = {
265           email = "patrick.schoenberger@posteo.de";
266           name = "psch";
267         };
268     };}];
269   };
270
271   programs.bash = {
272     enable = true;
273     historySize = -1;
274     historyFileSize = -1;
275     shellAliases = {  
276       snrs = "sudo nixos-rebuild switch --flake /etc/nixos#default";
277       snrt = "sudo nixos-rebuild test --flake /etc/nixos#default";
278       snrb = "sudo nixos-rebuild boot --flake /etc/nixos#default";
279       senc = "sudo $EDITOR /etc/nixos/configuration.nix";
280       senh = "sudo $EDITOR /etc/nixos/home-ps.nix";
281       senhc = "sudo $EDITOR /etc/nixos/home-common.nix";
282       senf = "sudo $EDITOR /etc/nixos/flake.nix";
283       flakerun = "nix run --override-input nixpkgs nixpkgs";
284       n = "nvim";
285     };
286   };
287
288   programs.fzf = {
289     enable = true;
290     enableBashIntegration = true;
291   };
292
293   programs.readline = {
294     enable = true;
295     bindings = {
296       "\\e[A" = "history-search-backward";
297       "\\e[B" = "history-search-forward";
298     };
299   };
300
301   programs.kitty = {
302     enable = true;
303     themeFile = "Adapta_Nokto_Maia";
304     settings = {
305       # hide_window_decorations = "yes";
306       background_opacity = "0.98";
307       background_blur = "1";
308       confirm_os_window_close = "0";
309       enable_audio_bell = "no";
310       scrollback_pager_history_size = "1024";
311     };
312   };
313
314   home.file.".config/zls.json".text = ''
315     {
316       "enable_build_on_save": true,
317       "build_on_save_step": "check"
318     }
319   '';
320   
321   home.file.".config/vis/plugins/vis-lspc" = {
322     source = builtins.fetchGit {
323       url = "https://gitlab.com/muhq/vis-lspc.git";
324       rev = "e184eb6c971abfcd0dc7f836f402aae6c33a8d13";
325     };
326     recursive = true;
327   };
328   home.file.".config/vis/plugins/vis-commentary" = {
329     source = builtins.fetchGit {
330       url = "https://github.com/lutobler/vis-commentary.git";
331       rev = "0e06ed8212c12c6651cb078b822390094b396f08";
332     };
333     recursive = true;
334   };
335   home.file.".config/vis/visrc.lua".text = ''
336       require('vis')
337       require('plugins/vis-commentary')
338       lspc = require('plugins/vis-lspc')
339
340       lspc.menu_cmd = 'vis-menu'
341       lspc.fallback_dirname_as_root = true
342       lspc.ls_map.zig = {name='zls',cmd='zls',roots={'build.zig'}}
343     
344       vis.events.subscribe(vis.events.INIT, function()
345         -- Your global configuration options
346       end)
347
348       vis.events.subscribe(vis.events.WIN_OPEN, function(win) -- luacheck: no unused args
349         -- Your per window configuration options e.g.
350         vis:command('set number on')
351         vis:command('set autoindent')
352         vis:command('set tabwidth 4')
353         vis:command('set expandtab on')
354       end)
355     '';
356
357   programs.emacs = {
358     enable = true;
359     extraConfig = ''
360       (menu-bar-mode 1)
361       (tool-bar-mode 0)
362       (scroll-bar-mode 0)
363       (global-display-line-numbers-mode)
364       (setq-default
365         display-line-numbers-type 'relative
366         make-backup-files nil
367         inhibit-startup-screen t)
368       (load-theme 'tango-dark t)
369     '';
370     extraPackages = epkgs: [
371       epkgs.zig-mode
372       epkgs.lsp-mode
373     ];
374   };
375
376   programs.tmux = {
377     enable = true;
378     escapeTime = 0;
379     extraConfig = ''
380       set-option -g default-terminal screen-256color
381       set -g history-limit 10000
382       set -g base-index 1
383       set-option -g renumber-windows on
384       bind-key -n M-n new-window -c "#{pane_current_path}"
385       bind-key -n M-1 select-window -t :1
386       bind-key -n M-2 select-window -t :2
387       bind-key -n M-3 select-window -t :3
388       bind-key -n M-4 select-window -t :4
389       bind-key -n M-5 select-window -t :5
390       bind-key -n M-6 select-window -t :6
391       bind-key -n M-7 select-window -t :7
392       bind-key -n M-8 select-window -t :8
393       bind-key -n M-9 select-window -t :9
394       bind-key -n M-0 select-window -t :0
395       bind-key -n M-. select-window -n
396       bind-key -n M-, select-window -p
397       bind-key -n M-S-. swap-window -t +1
398       bind-key -n M-S-, swap-window -t -1
399       bind-key -n M-X confirm-before "kill-window"
400       bind-key -n M-v split-window -h -c "#{pane_current_path}"
401       bind-key -n M-b split-window -v -c "#{pane_current_path}"
402       bind-key -n M-R command-prompt -I "" "rename-window '%%'"
403       bind-key -n M-f resize-pane -Z
404       bind-key -n M-h select-pane -L
405       bind-key -n M-l select-pane -R
406       bind-key -n M-k select-pane -U
407       bind-key -n M-j select-pane -D
408       bind-key -n M-Left select-pane -L
409       bind-key -n M-Right select-pane -R
410       bind-key -n M-Up select-pane -U
411       bind-key -n M-Down select-pane -D
412       bind-key -n "M-H" run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -L; tmux swap-pane -t $old'
413       bind-key -n "M-J" run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -D; tmux swap-pane -t $old'
414       bind-key -n "M-K" run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -U; tmux swap-pane -t $old'
415       bind-key -n "M-L" run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -R; tmux swap-pane -t $old'
416       bind-key -n "M-S-Left" run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -L; tmux swap-pane -t $old'
417       bind-key -n "M-S-Down" run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -D; tmux swap-pane -t $old'
418       bind-key -n "M-S-Up" run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -U; tmux swap-pane -t $old'
419       bind-key -n "M-S-Right" run-shell 'old=`tmux display -p "#{pane_index}"`; tmux select-pane -R; tmux swap-pane -t $old'
420       bind-key -n M-x confirm-before "kill-pane"
421       bind-key -n M-/ copy-mode
422
423       # Linux system clipboard
424       bind -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "xclip -in -selection clipboard"
425       bind-key -T copy-mode-vi MouseDragEnd1Pane send -X copy-pipe-and-cancel "xclip -in -selection clipboard"
426
427       set -g mouse on
428       # set-option -g status-keys vi
429       # set-option -g set-titles on
430       # set-option -g set-titles-string 'tmux - #W'
431       # set -g bell-action any
432       # set-option -g visual-bell off
433       # set-option -g set-clipboard off
434       # setw -g mode-keys vi
435       # setw -g monitor-activity on
436       # set -g visual-activity on
437       # set -g status-style fg=colour15
438       # set -g status-justify centre
439       # set -g status-left ""
440       # set -g status-right ""
441       # set -g status-interval 1
442       # set -g message-style fg=colour0,bg=colour3
443       # setw -g window-status-bell-style fg=colour1
444       # setw -g window-status-current-style fg=yellow,bold
445       # setw -g window-status-style fg=colour250
446       # setw -g window-status-current-format ' #{?#{==:#W,#{b:SHELL}},#{b:pane_current_path},#W} '
447       # setw -g window-status-format ' #{?#{==:#W,#{b:SHELL}},#{b:pane_current_path},#W} '
448       # # For older tmux:
449       # #setw -g window-status-format ' #W '
450       # #setw -g window-status-current-format ' #W '
451     '';
452   };
453
454   programs.nushell = {
455     enable = true;
456     # for editing directly to config.nu 
457     extraConfig = ''
458       $env.config = {
459         show_banner: false,
460         completions: {
461           case_sensitive: false # case-sensitive completions
462           quick: true           # set to false to prevent auto-selecting completions
463           partial: true         # set to false to prevent partial filling of the prompt
464           algorithm: "fuzzy"    # prefix or fuzzy
465         }
466         hooks: {
467           command_not_found: { |cmd| (command-not-found $cmd | str trim)  }
468         }
469       } 
470     '';
471     #  shellAliases = {
472     #  vi = "hx";
473     #  vim = "hx";
474     #  nano = "hx";
475     # };
476   };  
477   # programs.carapace = {
478   #   enable = true;
479   #   enableNushellIntegration = true;
480   # };
481
482   # programs.starship = {
483   #   enable = true;
484   #   settings = {
485   #     add_newline = false;
486   #     character = { 
487   #       success_symbol = "[➜](bold green)";
488   #       error_symbol = "[➜](bold red)";
489   #     };
490   #   };
491   # };
492
493   programs.firefox = {
494     enable = true;
495     profiles = {
496       default = {
497         settings = {
498           "toolkit.legacyUserProfileCustomizations.stylesheets" = true;
499           "browser.fullscreen.autohide" = false;
500           "browser.toolbars.bookmarks.visibility" = "never";
501           "browser.tabs.inTitlebar" = 0;
502           "browser.compactmode.show" = true;
503           "browser.uidensity" = 1;
504         };
505         userChrome = ''
506         #TabsToolbar {
507           visibility: collapse !important;
508         }
509         '';
510       };
511       appmode = {
512         id = 1;
513         settings = {
514           "toolkit.legacyUserProfileCustomizations.stylesheets" = true;
515           "browser.fullscreen.autohide" = false;
516           "browser.toolbars.bookmarks.visibility" = "never";
517           "browser.tabs.inTitlebar" = 0;
518           "browser.compactmode.show" = true;
519           "browser.uidensity" = 1;
520         };
521         userChrome = ''
522         #TabsToolbar {
523           visibility: collapse !important;
524         }
525         #nav-bar {
526           visibility: collapse !important;
527         }
528         #navigator-toolbox {
529           border-bottom: none !important;
530         }
531         '';        
532       };
533     };
534   };
535
536   xdg.desktopEntries = {
537     whatsapp = {
538       name = "WhatsApp";
539       genericName = "Messenger";
540       exec = "app web.whatsapp.com";
541       terminal = false;
542       categories = [ "Application" ];
543       icon = pkgs.fetchurl {
544         url = "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/2062095_application_chat_communication_logo_whatsapp_icon.svg/1024px-2062095_application_chat_communication_logo_whatsapp_icon.svg.png";
545         sha256 = "sha256-0eE3EEGnWFlpObfraTXMIqJz0Uya/h0hDsUA528qKCY=";
546       };
547     };
548     md = {
549       name = "Markdown";
550       genericName = "Documents";
551       exec = "md-app";
552       terminal = false;
553       categories = [ "Application" ];
554       icon = pkgs.fetchurl {
555         url = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Markdown-mark.svg/1024px-Markdown-mark.svg.png";
556         sha256 = "0v161jvmcfxp9lwd86y789430w1vpvxnnm5n2hzgr1kfh03psvb2";
557       };
558     };
559   };
560
561   gtk.enable = true;
562   gtk.theme = {
563     package = theme;
564     name = "Qogir-Dark";
565   };
566   # programs.gnome-shell.theme = {
567   #   package = theme;
568   #   name = "Qogir-Dark";
569   # };
570   # gtk.iconTheme = {
571   #   package = pkgs.vimix-icon-theme;
572   #   name = "vimix-doder-dark";
573   # };
574   home.pointerCursor = {
575     gtk.enable = true;
576     x11.enable = true;
577
578     name = "volantes_light_cursors";
579     size = 24;
580     package = pkgs.volantes-cursors;
581   };
582
583   # This value determines the Home Manager release that your configuration is
584   # compatible with. This helps avoid breakage when a new Home Manager release
585   # introduces backwards incompatible changes.
586   #
587   # You should not change this value, even if you update Home Manager. If you do
588   # want to update the value, then make sure to first check the Home Manager
589   # release notes.
590   home.stateVersion = "24.05"; # Please read the comment before changing.
591
592   # The home.packages option allows you to install Nix packages into your
593   # environment.
594   home.packages = with pkgs; [
595     nixos-icons
596     spotify-player
597     prismlauncher
598     pandoc
599     ghidra
600     gnome-firmware
601     fzf bat delta silver-searcher ripgrep perl universal-ctags
602     rofi
603     # bintools
604     htop
605     unzip
606     rr wrk
607     clang-tools bear
608     linuxPackages_latest.perf
609     texliveFull
610     asciidoctor-with-extensions
611     emscripten
612     caddy
613     python3
614     qogir-icon-theme
615     volantes-cursors
616     xorg.xkill
617     lf nnn yazi
618     feh
619     xarchiver
620     tig lazygit gitui
621     thunderbird
622     aerc
623     libreoffice
624     gimp
625     guvcview
626     arandr
627     vial
628     ncdu
629     gnumake gcc
630     linux-wifi-hotspot
631     esptool picocom
632     wireshark
633     nil
634     bc
635     ffmpeg-full
636     sc-im visidata
637     localsend
638     vis
639     wineWowPackages.unstableFull winetricks
640     signal-desktop
641
642     # # It is sometimes useful to fine-tune packages, for example, by applying
643     # # overrides. You can do that directly here, just don't forget the
644     # # parentheses. Maybe you want to install Nerd Fonts with a limited number of
645     # # fonts?
646     # (pkgs.nerdfonts.override { fonts = [ "FantasqueSansMono" ]; })
647
648     # # You can also create simple shell scripts directly inside your
649     # # configuration. For example, this adds a command 'my-hello' to your
650     # # environment:
651     # (pkgs.writeShellScriptBin "my-hello" ''
652     #   echo "Hello, ${config.home.username}!"
653     # '')
654     # $@ - Liste aller Parameter
655     # $* - String aller Parameter
656     # $# - Anzahl aller Parameter
657     # &> - stdout und stderr pipen
658     # '' - Literal
659     # "" - Expanded
660     # 
661     (pkgs.writeShellScriptBin "app" ''
662       ${pkgs.firefox}/bin/firefox -p appmode --new-window "$@"
663     '')
664     (pkgs.writeShellScriptBin "md" ''
665       file=$(mktemp --suffix=.html) && \
666       echo $file && \
667       ${pkgs.pandoc}/bin/pandoc -o $file $1 -s -H ${markdownStyleHeader} && \
668       app $file && \
669       rm $file
670     '')
671     (pkgs.writeShellScriptBin "run" ''
672       (nohup "$@" &>/dev/null &); sleep 0
673     '')
674     (pkgs.writeShellScriptBin "popup" ''
675       ${pkgs.kitty}/bin/kitty -o hide_window_decorations=yes -o background_opacity=0.5 \
676         --class kitty-popup -o remember_window_size=no \
677         -o initial_window_width=120c -o initial_window_height=40c \
678         "$@"
679     '')
680     (pkgs.writeShellScriptBin "fzfdir" ''
681       find "$1" -name "$2" | ${pkgs.fzf}/bin/fzf --layout=reverse
682     '')
683     (pkgs.writeShellScriptBin "file-app" ''
684       app localhost:8123
685     '')
686     (pkgs.writeShellScriptBin "run-popup" ''
687       popup bash -c 'file=$(compgen -c | grep -v fzf | sort -u | fzf --layout=reverse --print-query | tail -n 1) && run $file'
688     '')
689     (pkgs.writeShellScriptBin "set-wallpaper" ''
690       ${pkgs.feh}/bin/feh --bg-fill --no-fehbg ${wallpaper}
691     '')
692     (pkgs.writeShellScriptBin "mirror-phone" "IP=$(select-ip) && sudo scrcpy --tcpip=$IP --no-audio -K --kill-adb-on-close")
693     (pkgs.writeShellScriptBin "select-ip" ''
694       FILE=$HOME/.cache/select-ip.txt
695       IP=$( ${pkgs.rofi}/bin/rofi -dmenu -input $FILE -p IP ) || exit 1
696       echo $IP >> $FILE
697       gawk -i inplace 'FNR==1{delete a} !a[$0]++' $FILE
698       echo $IP
699     '')
700     (pkgs.writeShellScriptBin "create-repo" ''
701       ssh psch.dev sudo -u git git init --bare /srv/git/$1
702     '')
703   ];
704
705   # Home Manager is pretty good at managing dotfiles. The primary way to manage
706   # plain files is through 'home.file'.
707   home.file = {
708     # # Building this configuration will create a copy of 'dotfiles/screenrc' in
709     # # the Nix store. Activating the configuration will then make '~/.screenrc' a
710     # # symlink to the Nix store copy.
711     # ".screenrc".source = dotfiles/screenrc;
712
713     # # You can also set the file content immediately.
714     # ".gradle/gradle.properties".text = ''
715     #   org.gradle.console=verbose
716     #   org.gradle.daemon.idletimeout=3600000
717     # '';
718     ".background-image".source = wallpaper;
719   };
720
721   # Home Manager can also manage your environment variables through
722   # 'home.sessionVariables'. These will be explicitly sourced when using a
723   # shell provided by Home Manager. If you don't want to manage your shell
724   # through Home Manager then you have to manually source 'hm-session-vars.sh'
725   # located at either
726   #
727   #  ~/.nix-profile/etc/profile.d/hm-session-vars.sh
728   #
729   # or
730   #
731   #  ~/.local/state/nix/profiles/profile/etc/profile.d/hm-session-vars.sh
732   #
733   # or
734   #
735   #  /etc/profiles/per-user/ps/etc/profile.d/hm-session-vars.sh
736   #
737   home.sessionVariables = {
738     # EDITOR = "emacs";
739   };
740
741   # Let Home Manager install and manage itself.
742   programs.home-manager.enable = true;
743 }