diff options
| author | Quentin Aristote <quentin@aristote.fr> | 2023-02-22 22:39:56 +0100 |
|---|---|---|
| committer | Quentin Aristote <quentin@aristote.fr> | 2023-02-28 17:47:49 +0100 |
| commit | 70d60e5ee6d1092f765807b8483c9c16d2afa678 (patch) | |
| tree | edeb7a91de348d6fc5dd0e43b9ca7bef794b322c /modules | |
| parent | bbb2f5e7cefb970b3e4994ee51bb2c3a18a073c2 (diff) | |
add home-manager modules
Diffstat (limited to 'modules')
33 files changed, 2123 insertions, 10 deletions
diff --git a/modules/home-manager/default.nix b/modules/home-manager/default.nix new file mode 100644 index 0000000..f9cee08 --- /dev/null +++ b/modules/home-manager/default.nix @@ -0,0 +1,5 @@ +{ ... }: + +{ + imports = [ ./dotfiles.nix ./lockscreen.nix ./personal ./wallpaper.nix ]; +} diff --git a/modules/home-manager/dotfiles.nix b/modules/home-manager/dotfiles.nix new file mode 100644 index 0000000..6d28f39 --- /dev/null +++ b/modules/home-manager/dotfiles.nix @@ -0,0 +1,13 @@ +{ lib, ... }: + +{ + options.personal.home.dotfiles = lib.mkOption { + type = with lib.types; attrsOf path; + default = {}; + description = '' + Paths to dotfiles. + ''; + example = + lib.literalExample "{ \"init.el\" = ./dotfiles/init.el; }"; + }; +} diff --git a/modules/home-manager/lockscreen.nix b/modules/home-manager/lockscreen.nix new file mode 100644 index 0000000..e5c36ed --- /dev/null +++ b/modules/home-manager/lockscreen.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +{ + options.personal.home.lockscreen = lib.mkOption { + type = lib.types.str; + default = "${ + pkgs.personal.lockscreen.override { + backgroundImage = config.personal.home.wallpaper; + } + }/bin/lockscreen.sh"; + description = '' + Command to run for locking the screen. + ''; + }; +} diff --git a/modules/home-manager/personal/default.nix b/modules/home-manager/personal/default.nix new file mode 100644 index 0000000..dcd7500 --- /dev/null +++ b/modules/home-manager/personal/default.nix @@ -0,0 +1,15 @@ +{ ... }: + +{ + imports = [ ./dotfiles ./environment.nix ./gui ./profiles.nix ./programs ]; + + # This value determines the Home Manager release that your + # configuration is compatible with. This helps avoid breakage + # when a new Home Manager release introduces backwards + # incompatible changes. + # + # You can update Home Manager without changing this value. See + # the Home Manager release notes for a list of state version + # changes in each release. + home.stateVersion = "23.05"; +} diff --git a/modules/home-manager/personal/dotfiles/background-image b/modules/home-manager/personal/dotfiles/background-image Binary files differnew file mode 100644 index 0000000..4288f3e --- /dev/null +++ b/modules/home-manager/personal/dotfiles/background-image diff --git a/modules/home-manager/personal/dotfiles/default.nix b/modules/home-manager/personal/dotfiles/default.nix new file mode 100644 index 0000000..27610ca --- /dev/null +++ b/modules/home-manager/personal/dotfiles/default.nix @@ -0,0 +1,11 @@ +{ ... }: + +{ + personal.home.dotfiles = { + wallpaper = ./background-image; + latexmkrc = ./latexmkrc; + rofi = ./rofi.rasi; + spacemacs = ./spacemacs.el; + venv-manager = ./venv-manager.nix; + }; +} diff --git a/modules/home-manager/personal/dotfiles/latexmkrc b/modules/home-manager/personal/dotfiles/latexmkrc new file mode 100644 index 0000000..788ceb7 --- /dev/null +++ b/modules/home-manager/personal/dotfiles/latexmkrc @@ -0,0 +1,5 @@ +$clean_ext = 'bbl nav prv_%R.fmt prv_%R.log prv/*/* prv/* prv run.xml snm vrb'; + +$ENV{'TZ'}='Europe/Paris'; + +$pdf_previewer = 'evince %O %S 2>&1 | grep -v Gtk-WARNING | grep . 1>&2';
\ No newline at end of file diff --git a/modules/home-manager/personal/dotfiles/rofi.rasi b/modules/home-manager/personal/dotfiles/rofi.rasi new file mode 100644 index 0000000..375b28b --- /dev/null +++ b/modules/home-manager/personal/dotfiles/rofi.rasi @@ -0,0 +1,201 @@ +/** + * rofi -dump-theme output. + * Rofi version: 1.7.0 + **/ +* { + alternate-urgent-background: var(lightbg); + alternate-active-foreground: var(blue); + selected-active-background: var(actbg); + selected-urgent-foreground: var(background-color); + hide-scrollbar: "true"; + padding: 0; + normal-foreground: var(text-color); + text-color: rgba ( 178, 174, 168, 100 % ); + line-padding: 2; + background: rgba ( 253, 246, 227, 100 % ); + line-margin: 2; + alternate-normal-foreground: var(foreground); + urgent-foreground: var(text-color); + active-background: var(selbg); + selected-normal-background: var(actbg); + blue: rgba ( 38, 139, 210, 100 % ); + selected-urgent-background: var(urgbg); + selected-active-foreground: var(winbg); + separator-style: "none"; + separatorcolor: var(foreground); + urgbg: rgba ( 229, 57, 53, 100 % ); + lightfg: rgba ( 88, 104, 117, 100 % ); + alternate-active-background: var(lightbg); + selbg: rgba ( 57, 73, 163, 100 % ); + spacing: 2; + winbg: rgba ( 179, 190, 255, 100 % ); + actbg: rgba ( 38, 38, 38, 100 % ); + alternate-urgent-foreground: var(red); + margin: 0; + lightbg: rgba ( 238, 232, 213, 100 % ); + red: rgba ( 220, 50, 47, 100 % ); + background-color: rgba ( 0, 0, 0, 0 % ); + normal-background: var(background-color); + border-color: var(foreground); + foreground: rgba ( 0, 43, 54, 100 % ); + alternate-normal-background: var(lightbg); + urgent-background: var(background-color); + selected-normal-foreground: var(winbg); + active-foreground: var(text-color); +} +element { + padding: 10px ; + cursor: pointer; + spacing: 5px ; + border: 0; +} +element normal.normal { + background-color: var(normal-background); + text-color: var(normal-foreground); +} +element normal.urgent { + background-color: var(urgent-background); + text-color: var(urgent-foreground); +} +element normal.active { + background-color: var(active-background); + text-color: var(active-foreground); +} +element selected.normal { + background-color: var(selected-normal-background); + border-color: var(active-background); + text-color: var(selected-normal-foreground); + border: 0px 5px 0px 0px ; +} +element selected.urgent { + background-color: var(selected-urgent-background); + text-color: var(selected-urgent-foreground); +} +element selected.active { + background-color: var(selected-active-background); + text-color: var(selected-active-foreground); +} +element alternate.normal { + background-color: var(normal-background); + text-color: var(normal-foreground); +} +element alternate.urgent { + background-color: var(urgent-background); + text-color: var(urgent-foreground); +} +element alternate.active { + background-color: var(active-background); + text-color: var(active-foreground); +} +element-text { + background-color: rgba ( 0, 0, 0, 0 % ); + cursor: inherit; + highlight: inherit; + text-color: inherit; +} +element-icon { + background-color: rgba ( 0, 0, 0, 0 % ); + size: 1.0000em ; + cursor: inherit; + text-color: inherit; +} +window { + transparency: "real"; + padding: 5; + width: 10.0000em ; + orientation: horizontal; + location: west; + children: [ mainbox ]; + background-color: rgba ( 0, 0, 0, 100 % ); + height: 100.0000% ; + anchor: west; + border: 1; +} +mainbox { + padding: 0; + spacing: 0.8000em ; + border: 0; + children: [ entry,listview ]; +} +message { + padding: 1px ; + border-color: var(separatorcolor); + border: 2px dash 0px 0px ; +} +textbox { + text-color: var(foreground); +} +listview { + fixed-height: 0; + padding: 2px 0px 0px ; + scrollbar: true; + cycle: false; + dynamic: false; + border-color: var(separatorcolor); + border: 2px dash 0px 0px ; + spacing: 0; +} +scrollbar { + width: 4px ; + padding: 0; + handle-width: 8px ; + border: 0; + handle-color: var(normal-foreground); +} +sidebar { + border-color: var(separatorcolor); + border: 2px dash 0px 0px ; +} +button { + padding: 5px 2px ; + cursor: pointer; + spacing: 0; + text-color: var(normal-foreground); +} +button selected { + background-color: var(active-background); + text-color: var(background-color); +} +num-filtered-rows { + expand: false; + text-color: rgba ( 128, 128, 128, 100 % ); +} +num-rows { + expand: false; + text-color: rgba ( 128, 128, 128, 100 % ); +} +textbox-num-sep { + expand: false; + str: "/"; + text-color: rgba ( 128, 128, 128, 100 % ); +} +inputbar { + padding: 5px ; + spacing: 5px ; + text-color: var(normal-foreground); + children: [ prompt,textbox-prompt-colon,entry,num-filtered-rows,textbox-num-sep,num-rows,case-indicator ]; +} +case-indicator { + spacing: 0; + text-color: var(normal-foreground); +} +entry { + text-color: var(normal-foreground); + cursor: text; + padding: 5px ; + placeholder-color: rgba ( 128, 128, 128, 100 % ); + vertical-align: 1; + expand: false; + spacing: 0; + placeholder: "Type to filter"; +} +prompt { + spacing: 0; + text-color: var(normal-foreground); +} +textbox-prompt-colon { + margin: 0px 0.3000em 0.0000em 0.0000em ; + expand: false; + str: ":"; + text-color: inherit; +} diff --git a/modules/home-manager/personal/dotfiles/spacemacs.el b/modules/home-manager/personal/dotfiles/spacemacs.el new file mode 100644 index 0000000..bd80241 --- /dev/null +++ b/modules/home-manager/personal/dotfiles/spacemacs.el @@ -0,0 +1,651 @@ +;; -*- mode: emacs-lisp; lexical-binding: t -*- +;; This file is loaded by Spacemacs at startup. +;; It must be stored in your home directory. + +(defun dotspacemacs/layers () + "Layer configuration: +This function should only modify configuration layer settings." + (setq-default + ;; Base distribution to use. This is a layer contained in the directory + ;; `+distribution'. For now available distributions are `spacemacs-base' + ;; or `spacemacs'. (default 'spacemacs) + dotspacemacs-distribution 'spacemacs + + ;; Lazy installation of layers (i.e. layers are installed only when a file + ;; with a supported type is opened). Possible values are `all', `unused' + ;; and `nil'. `unused' will lazy install only unused layers (i.e. layers + ;; not listed in variable `dotspacemacs-configuration-layers'), `all' will + ;; lazy install any layer that support lazy installation even the layers + ;; listed in `dotspacemacs-configuration-layers'. `nil' disable the lazy + ;; installation feature and you have to explicitly list a layer in the + ;; variable `dotspacemacs-configuration-layers' to install it. + ;; (default 'unused) + dotspacemacs-enable-lazy-installation 'unused + + ;; If non-nil then Spacemacs will ask for confirmation before installing + ;; a layer lazily. (default t) + dotspacemacs-ask-for-lazy-installation t + + ;; List of additional paths where to look for configuration layers. + ;; Paths must have a trailing slash (i.e. `~/.mycontribs/') + dotspacemacs-configuration-layer-path '() + + ;; List of configuration layers to load. + dotspacemacs-configuration-layers + '( + ;; ---------------------------------------------------------------- + ;; Example of useful layers you may want to use right away. + ;; Uncomment some layer names and press `SPC f e R' (Vim style) or + ;; `M-m f e R' (Emacs style) to install them. + ;; ---------------------------------------------------------------- + auto-completion + better-defaults + ;; eww + git + helm + multiple-cursors + ;; (shell :variables + ;; shell-default-height 30 + ;; shell-default-position 'bottom) + ;; spell-checking + ;; syntax-checking + version-control + treemacs + ;; ---------------------------------------------------------------- + ;; Programming (and markup) languages + ;; ---------------------------------------------------------------- + lsp + csv + emacs-lisp spacemacs-misc + go + haskell + html javascript + latex + markdown + nixos + org + ocaml coq + php + python + rust + yaml + ;; ---------------------------------------------------------------- + ;; Private layers + ;; ---------------------------------------------------------------- + direnv + bibli-paris + why3 + ) + + ;; List of additional packages that will be installed without being wrapped + ;; in a layer (generally the packages are installed only and should still be + ;; loaded using load/require/use-package in the user-config section below in + ;; this file). If you need some configuration for these packages, then + ;; consider creating a layer. You can also put the configuration in + ;; `dotspacemacs/user-config'. To use a local version of a package, use the + ;; `:location' property: '(your-package :location "~/path/to/your-package/") + ;; Also include the dependencies as they will not be resolved automatically. + dotspacemacs-additional-packages '(request-deferred parse-csv) + + ;; A list of packages that cannot be updated. + dotspacemacs-frozen-packages '() + + ;; A list of packages that will not be installed and loaded. + dotspacemacs-excluded-packages '() + + ;; Defines the behaviour of Spacemacs when installing packages. + ;; Possible values are `used-only', `used-but-keep-unused' and `all'. + ;; `used-only' installs only explicitly used packages and deletes any unused + ;; packages as well as their unused dependencies. `used-but-keep-unused' + ;; installs only the used packages but won't delete unused ones. `all' + ;; installs *all* packages supported by Spacemacs and never uninstalls them. + ;; (default is `used-only') + dotspacemacs-install-packages 'used-but-keep-unused)) + +(defun dotspacemacs/init () + "Initialization: +This function is called at the very beginning of Spacemacs startup, +before layer configuration. +It should only modify the values of Spacemacs settings." + ;; This setq-default sexp is an exhaustive list of all the supported + ;; spacemacs settings. + (setq-default + ;; If non-nil then enable support for the portable dumper. You'll need to + ;; compile Emacs 27 from source following the instructions in file + ;; EXPERIMENTAL.org at to root of the git repository. + ;; + ;; WARNING: pdumper does not work with Native Compilation, so it's disabled + ;; regardless of the following setting when native compilation is in effect. + ;; + ;; (default nil) + dotspacemacs-enable-emacs-pdumper nil + + ;; Name of executable file pointing to emacs 27+. This executable must be + ;; in your PATH. + ;; (default "emacs") + dotspacemacs-emacs-pdumper-executable-file "emacs" + + ;; Name of the Spacemacs dump file. This is the file will be created by the + ;; portable dumper in the cache directory under dumps sub-directory. + ;; To load it when starting Emacs add the parameter `--dump-file' + ;; when invoking Emacs 27.1 executable on the command line, for instance: + ;; ./emacs --dump-file=$HOME/.emacs.d/.cache/dumps/spacemacs-27.1.pdmp + ;; (default (format "spacemacs-%s.pdmp" emacs-version)) + dotspacemacs-emacs-dumper-dump-file (format "spacemacs-%s.pdmp" emacs-version) + + ;; If non-nil ELPA repositories are contacted via HTTPS whenever it's + ;; possible. Set it to nil if you have no way to use HTTPS in your + ;; environment, otherwise it is strongly recommended to let it set to t. + ;; This variable has no effect if Emacs is launched with the parameter + ;; `--insecure' which forces the value of this variable to nil. + ;; (default t) + dotspacemacs-elpa-https t + + ;; Maximum allowed time in seconds to contact an ELPA repository. + ;; (default 5) + dotspacemacs-elpa-timeout 5 + + ;; Set `gc-cons-threshold' and `gc-cons-percentage' when startup finishes. + ;; This is an advanced option and should not be changed unless you suspect + ;; performance issues due to garbage collection operations. + ;; (default '(100000000 0.1)) + dotspacemacs-gc-cons '(100000000 0.1) + + ;; Set `read-process-output-max' when startup finishes. + ;; This defines how much data is read from a foreign process. + ;; Setting this >= 1 MB should increase performance for lsp servers + ;; in emacs 27. + ;; (default (* 1024 1024)) + dotspacemacs-read-process-output-max (* 1024 1024) + + ;; If non-nil then Spacelpa repository is the primary source to install + ;; a locked version of packages. If nil then Spacemacs will install the + ;; latest version of packages from MELPA. Spacelpa is currently in + ;; experimental state please use only for testing purposes. + ;; (default nil) + dotspacemacs-use-spacelpa nil + + ;; If non-nil then verify the signature for downloaded Spacelpa archives. + ;; (default t) + dotspacemacs-verify-spacelpa-archives t + + ;; If non-nil then spacemacs will check for updates at startup + ;; when the current branch is not `develop'. Note that checking for + ;; new versions works via git commands, thus it calls GitHub services + ;; whenever you start Emacs. (default nil) + dotspacemacs-check-for-update nil + + ;; If non-nil, a form that evaluates to a package directory. For example, to + ;; use different package directories for different Emacs versions, set this + ;; to `emacs-version'. (default 'emacs-version) + dotspacemacs-elpa-subdirectory 'emacs-version + + ;; One of `vim', `emacs' or `hybrid'. + ;; `hybrid' is like `vim' except that `insert state' is replaced by the + ;; `hybrid state' with `emacs' key bindings. The value can also be a list + ;; with `:variables' keyword (similar to layers). Check the editing styles + ;; section of the documentation for details on available variables. + ;; (default 'vim) + dotspacemacs-editing-style 'vim + + ;; If non-nil show the version string in the Spacemacs buffer. It will + ;; appear as (spacemacs version)@(emacs version) + ;; (default t) + dotspacemacs-startup-buffer-show-version t + + ;; Specify the startup banner. Default value is `official', it displays + ;; the official spacemacs logo. An integer value is the index of text + ;; banner, `random' chooses a random text banner in `core/banners' + ;; directory. A string value must be a path to an image format supported + ;; by your Emacs build. + ;; If the value is nil then no banner is displayed. (default 'official) + dotspacemacs-startup-banner 'official + + ;; Scale factor controls the scaling (size) of the startup banner. Default + ;; value is `auto' for scaling the logo automatically to fit all buffer + ;; contents, to a maximum of the full image height and a minimum of 3 line + ;; heights. If set to a number (int or float) it is used as a constant + ;; scaling factor for the default logo size. + dotspacemacs-startup-banner-scale 'auto + + ;; List of items to show in startup buffer or an association list of + ;; the form `(list-type . list-size)`. If nil then it is disabled. + ;; Possible values for list-type are: + ;; `recents' `recents-by-project' `bookmarks' `projects' `agenda' `todos'. + ;; List sizes may be nil, in which case + ;; `spacemacs-buffer-startup-lists-length' takes effect. + ;; The exceptional case is `recents-by-project', where list-type must be a + ;; pair of numbers, e.g. `(recents-by-project . (7 . 5))', where the first + ;; number is the project limit and the second the limit on the recent files + ;; within a project. + dotspacemacs-startup-lists '((recents . 5) + (projects . 7)) + + ;; True if the home buffer should respond to resize events. (default t) + dotspacemacs-startup-buffer-responsive t + + ;; Show numbers before the startup list lines. (default t) + dotspacemacs-show-startup-list-numbers t + + ;; The minimum delay in seconds between number key presses. (default 0.4) + dotspacemacs-startup-buffer-multi-digit-delay 0.4 + + ;; If non-nil, show file icons for entries and headings on Spacemacs home buffer. + ;; This has no effect in terminal or if "all-the-icons" package or the font + ;; is not installed. (default nil) + dotspacemacs-startup-buffer-show-icons nil + + ;; Default major mode for a new empty buffer. Possible values are mode + ;; names such as `text-mode'; and `nil' to use Fundamental mode. + ;; (default `text-mode') + dotspacemacs-new-empty-buffer-major-mode 'text-mode + + ;; Default major mode of the scratch buffer (default `text-mode') + dotspacemacs-scratch-mode 'text-mode + + ;; If non-nil, *scratch* buffer will be persistent. Things you write down in + ;; *scratch* buffer will be saved and restored automatically. + dotspacemacs-scratch-buffer-persistent nil + + ;; If non-nil, `kill-buffer' on *scratch* buffer + ;; will bury it instead of killing. + dotspacemacs-scratch-buffer-unkillable nil + + ;; Initial message in the scratch buffer, such as "Welcome to Spacemacs!" + ;; (default nil) + dotspacemacs-initial-scratch-message nil + + ;; List of themes, the first of the list is loaded when spacemacs starts. + ;; Press `SPC T n' to cycle to the next theme in the list (works great + ;; with 2 themes variants, one dark and one light) + dotspacemacs-themes '(spacemacs-dark + spacemacs-light) + + ;; Set the theme for the Spaceline. Supported themes are `spacemacs', + ;; `all-the-icons', `custom', `doom', `vim-powerline' and `vanilla'. The + ;; first three are spaceline themes. `doom' is the doom-emacs mode-line. + ;; `vanilla' is default Emacs mode-line. `custom' is a user defined themes, + ;; refer to the DOCUMENTATION.org for more info on how to create your own + ;; spaceline theme. Value can be a symbol or list with additional properties. + ;; (default '(spacemacs :separator wave :separator-scale 1.5)) + dotspacemacs-mode-line-theme '(spacemacs :separator wave :separator-scale 1.5) + + ;; If non-nil the cursor color matches the state color in GUI Emacs. + ;; (default t) + dotspacemacs-colorize-cursor-according-to-state t + + ;; Default font or prioritized list of fonts. The `:size' can be specified as + ;; a non-negative integer (pixel size), or a floating-point (point size). + ;; Point size is recommended, because it's device independent. (default 10.0) + dotspacemacs-default-font '("Source Code Pro" + :size 14.0 + :weight normal + :width normal) + + ;; The leader key (default "SPC") + dotspacemacs-leader-key "SPC" + + ;; The key used for Emacs commands `M-x' (after pressing on the leader key). + ;; (default "SPC") + dotspacemacs-emacs-command-key "SPC" + + ;; The key used for Vim Ex commands (default ":") + dotspacemacs-ex-command-key ":" + + ;; The leader key accessible in `emacs state' and `insert state' + ;; (default "M-m") + dotspacemacs-emacs-leader-key "M-m" + + ;; Major mode leader key is a shortcut key which is the equivalent of + ;; pressing `<leader> m`. Set it to `nil` to disable it. (default ",") + dotspacemacs-major-mode-leader-key "," + + ;; Major mode leader key accessible in `emacs state' and `insert state'. + ;; (default "C-M-m" for terminal mode, "<M-return>" for GUI mode). + ;; Thus M-RET should work as leader key in both GUI and terminal modes. + ;; C-M-m also should work in terminal mode, but not in GUI mode. + dotspacemacs-major-mode-emacs-leader-key (if window-system "<M-return>" "C-M-m") + + ;; These variables control whether separate commands are bound in the GUI to + ;; the key pairs `C-i', `TAB' and `C-m', `RET'. + ;; Setting it to a non-nil value, allows for separate commands under `C-i' + ;; and TAB or `C-m' and `RET'. + ;; In the terminal, these pairs are generally indistinguishable, so this only + ;; works in the GUI. (default nil) + dotspacemacs-distinguish-gui-tab nil + + ;; Name of the default layout (default "Default") + dotspacemacs-default-layout-name "Default" + + ;; If non-nil the default layout name is displayed in the mode-line. + ;; (default nil) + dotspacemacs-display-default-layout nil + + ;; If non-nil then the last auto saved layouts are resumed automatically upon + ;; start. (default nil) + dotspacemacs-auto-resume-layouts nil + + ;; If non-nil, auto-generate layout name when creating new layouts. Only has + ;; effect when using the "jump to layout by number" commands. (default nil) + dotspacemacs-auto-generate-layout-names nil + + ;; Size (in MB) above which spacemacs will prompt to open the large file + ;; literally to avoid performance issues. Opening a file literally means that + ;; no major mode or minor modes are active. (default is 1) + dotspacemacs-large-file-size 1 + + ;; Location where to auto-save files. Possible values are `original' to + ;; auto-save the file in-place, `cache' to auto-save the file to another + ;; file stored in the cache directory and `nil' to disable auto-saving. + ;; (default 'cache) + dotspacemacs-auto-save-file-location 'cache + + ;; Maximum number of rollback slots to keep in the cache. (default 5) + dotspacemacs-max-rollback-slots 5 + + ;; If non-nil, the paste transient-state is enabled. While enabled, after you + ;; paste something, pressing `C-j' and `C-k' several times cycles through the + ;; elements in the `kill-ring'. (default nil) + dotspacemacs-enable-paste-transient-state nil + + ;; Which-key delay in seconds. The which-key buffer is the popup listing + ;; the commands bound to the current keystroke sequence. (default 0.4) + dotspacemacs-which-key-delay 0.4 + + ;; Which-key frame position. Possible values are `right', `bottom' and + ;; `right-then-bottom'. right-then-bottom tries to display the frame to the + ;; right; if there is insufficient space it displays it at the bottom. + ;; (default 'bottom) + dotspacemacs-which-key-position 'bottom + + ;; Control where `switch-to-buffer' displays the buffer. If nil, + ;; `switch-to-buffer' displays the buffer in the current window even if + ;; another same-purpose window is available. If non-nil, `switch-to-buffer' + ;; displays the buffer in a same-purpose window even if the buffer can be + ;; displayed in the current window. (default nil) + dotspacemacs-switch-to-buffer-prefers-purpose nil + + ;; If non-nil a progress bar is displayed when spacemacs is loading. This + ;; may increase the boot time on some systems and emacs builds, set it to + ;; nil to boost the loading time. (default t) + dotspacemacs-loading-progress-bar t + + ;; If non-nil the frame is fullscreen when Emacs starts up. (default nil) + ;; (Emacs 24.4+ only) + dotspacemacs-fullscreen-at-startup nil + + ;; If non-nil `spacemacs/toggle-fullscreen' will not use native fullscreen. + ;; Use to disable fullscreen animations in OSX. (default nil) + dotspacemacs-fullscreen-use-non-native nil + + ;; If non-nil the frame is maximized when Emacs starts up. + ;; Takes effect only if `dotspacemacs-fullscreen-at-startup' is nil. + ;; (default nil) (Emacs 24.4+ only) + dotspacemacs-maximized-at-startup nil + + ;; If non-nil the frame is undecorated when Emacs starts up. Combine this + ;; variable with `dotspacemacs-maximized-at-startup' to obtain fullscreen + ;; without external boxes. Also disables the internal border. (default nil) + dotspacemacs-undecorated-at-startup nil + + ;; A value from the range (0..100), in increasing opacity, which describes + ;; the transparency level of a frame when it's active or selected. + ;; Transparency can be toggled through `toggle-transparency'. (default 90) + dotspacemacs-active-transparency 90 + + ;; A value from the range (0..100), in increasing opacity, which describes + ;; the transparency level of a frame when it's inactive or deselected. + ;; Transparency can be toggled through `toggle-transparency'. (default 90) + dotspacemacs-inactive-transparency 90 + + ;; A value from the range (0..100), in increasing opacity, which describes the + ;; transparency level of a frame background when it's active or selected. Transparency + ;; can be toggled through `toggle-background-transparency'. (default 90) + dotspacemacs-background-transparency 90 + + ;; If non-nil show the titles of transient states. (default t) + dotspacemacs-show-transient-state-title t + + ;; If non-nil show the color guide hint for transient state keys. (default t) + dotspacemacs-show-transient-state-color-guide t + + ;; If non-nil unicode symbols are displayed in the mode line. + ;; If you use Emacs as a daemon and wants unicode characters only in GUI set + ;; the value to quoted `display-graphic-p'. (default t) + dotspacemacs-mode-line-unicode-symbols t + + ;; If non-nil smooth scrolling (native-scrolling) is enabled. Smooth + ;; scrolling overrides the default behavior of Emacs which recenters point + ;; when it reaches the top or bottom of the screen. (default t) + dotspacemacs-smooth-scrolling t + + ;; Show the scroll bar while scrolling. The auto hide time can be configured + ;; by setting this variable to a number. (default t) + dotspacemacs-scroll-bar-while-scrolling t + + ;; Control line numbers activation. + ;; If set to `t', `relative' or `visual' then line numbers are enabled in all + ;; `prog-mode' and `text-mode' derivatives. If set to `relative', line + ;; numbers are relative. If set to `visual', line numbers are also relative, + ;; but only visual lines are counted. For example, folded lines will not be + ;; counted and wrapped lines are counted as multiple lines. + ;; This variable can also be set to a property list for finer control: + ;; '(:relative nil + ;; :visual nil + ;; :disabled-for-modes dired-mode + ;; doc-view-mode + ;; markdown-mode + ;; org-mode + ;; pdf-view-mode + ;; text-mode + ;; :size-limit-kb 1000) + ;; When used in a plist, `visual' takes precedence over `relative'. + ;; (default nil) + dotspacemacs-line-numbers nil + + ;; Code folding method. Possible values are `evil', `origami' and `vimish'. + ;; (default 'evil) + dotspacemacs-folding-method 'evil + + ;; If non-nil and `dotspacemacs-activate-smartparens-mode' is also non-nil, + ;; `smartparens-strict-mode' will be enabled in programming modes. + ;; (default nil) + dotspacemacs-smartparens-strict-mode nil + + ;; If non-nil smartparens-mode will be enabled in programming modes. + ;; (default t) + dotspacemacs-activate-smartparens-mode t + + ;; If non-nil pressing the closing parenthesis `)' key in insert mode passes + ;; over any automatically added closing parenthesis, bracket, quote, etc... + ;; This can be temporary disabled by pressing `C-q' before `)'. (default nil) + dotspacemacs-smart-closing-parenthesis nil + + ;; Select a scope to highlight delimiters. Possible values are `any', + ;; `current', `all' or `nil'. Default is `all' (highlight any scope and + ;; emphasis the current one). (default 'all) + dotspacemacs-highlight-delimiters 'all + + ;; If non-nil, start an Emacs server if one is not already running. + ;; (default nil) + dotspacemacs-enable-server nil + + ;; Set the emacs server socket location. + ;; If nil, uses whatever the Emacs default is, otherwise a directory path + ;; like \"~/.emacs.d/server\". It has no effect if + ;; `dotspacemacs-enable-server' is nil. + ;; (default nil) + dotspacemacs-server-socket-dir nil + + ;; If non-nil, advise quit functions to keep server open when quitting. + ;; (default nil) + dotspacemacs-persistent-server nil + + ;; List of search tool executable names. Spacemacs uses the first installed + ;; tool of the list. Supported tools are `rg', `ag', `pt', `ack' and `grep'. + ;; (default '("rg" "ag" "pt" "ack" "grep")) + dotspacemacs-search-tools '("rg" "ag" "pt" "ack" "grep") + + ;; Format specification for setting the frame title. + ;; %a - the `abbreviated-file-name', or `buffer-name' + ;; %t - `projectile-project-name' + ;; %I - `invocation-name' + ;; %S - `system-name' + ;; %U - contents of $USER + ;; %b - buffer name + ;; %f - visited file name + ;; %F - frame name + ;; %s - process status + ;; %p - percent of buffer above top of window, or Top, Bot or All + ;; %P - percent of buffer above bottom of window, perhaps plus Top, or Bot or All + ;; %m - mode name + ;; %n - Narrow if appropriate + ;; %z - mnemonics of buffer, terminal, and keyboard coding systems + ;; %Z - like %z, but including the end-of-line format + ;; If nil then Spacemacs uses default `frame-title-format' to avoid + ;; performance issues, instead of calculating the frame title by + ;; `spacemacs/title-prepare' all the time. + ;; (default "%I@%S") + dotspacemacs-frame-title-format "%I@%S" + + ;; Format specification for setting the icon title format + ;; (default nil - same as frame-title-format) + dotspacemacs-icon-title-format nil + + ;; Color highlight trailing whitespace in all prog-mode and text-mode derived + ;; modes such as c++-mode, python-mode, emacs-lisp, html-mode, rst-mode etc. + ;; (default t) + dotspacemacs-show-trailing-whitespace t + + ;; Delete whitespace while saving buffer. Possible values are `all' + ;; to aggressively delete empty line and long sequences of whitespace, + ;; `trailing' to delete only the whitespace at end of lines, `changed' to + ;; delete only whitespace for changed lines or `nil' to disable cleanup. + ;; (default nil) + dotspacemacs-whitespace-cleanup nil + + ;; If non-nil activate `clean-aindent-mode' which tries to correct + ;; virtual indentation of simple modes. This can interfere with mode specific + ;; indent handling like has been reported for `go-mode'. + ;; If it does deactivate it here. + ;; (default t) + dotspacemacs-use-clean-aindent-mode t + + ;; Accept SPC as y for prompts if non-nil. (default nil) + dotspacemacs-use-SPC-as-y nil + + ;; If non-nil shift your number row to match the entered keyboard layout + ;; (only in insert state). Currently supported keyboard layouts are: + ;; `qwerty-us', `qwertz-de' and `querty-ca-fr'. + ;; New layouts can be added in `spacemacs-editing' layer. + ;; (default nil) + dotspacemacs-swap-number-row nil + + ;; Either nil or a number of seconds. If non-nil zone out after the specified + ;; number of seconds. (default nil) + dotspacemacs-zone-out-when-idle nil + + ;; Run `spacemacs/prettify-org-buffer' when + ;; visiting README.org files of Spacemacs. + ;; (default nil) + dotspacemacs-pretty-docs nil + + ;; If nil the home buffer shows the full path of agenda items + ;; and todos. If non-nil only the file name is shown. + dotspacemacs-home-shorten-agenda-source nil + + ;; If non-nil then byte-compile some of Spacemacs files. + dotspacemacs-byte-compile nil)) + +(defun dotspacemacs/user-env () + "Environment variables setup. +This function defines the environment variables for your Emacs session. By +default it calls `spacemacs/load-spacemacs-env' which loads the environment +variables declared in `~/.spacemacs.env' or `~/.spacemacs.d/.spacemacs.env'. +See the header of this file for more information." + (spacemacs/load-spacemacs-env) +) + +(defun dotspacemacs/user-init () + "Initialization for user code: +This function is called immediately after `dotspacemacs/init', before layer +configuration. +It is mostly for variables that should be set before packages are loaded. +If you are unsure, try setting them in `dotspacemacs/user-config' first." +) + + +(defun dotspacemacs/user-load () + "Library to load while dumping. +This function is called only while dumping Spacemacs configuration. You can +`require' or `load' the libraries of your choice that will be included in the +dump." +) + + +(defun dotspacemacs/user-config () + "Configuration for user code: +This function is called at the very end of Spacemacs startup, after layer +configuration. +Put your configuration code here, except for variables that should be set +before packages are loaded." + ;; Variables customization + (custom-set-variables + '(merlin-command "ocamlmerlin") + + ;; reftex + ;; https://tex.stackexchange.com/a/54825 + '(reftex-bibliography-commands '("bibliography" + "nobibliography" + "addbibresource")) + ;; https://tex.stackexchange.com/a/213909 + '(reftex-use-external-file-finders t) + + ;; don't pop warning buffer on native comp + '(native-comp-async-report-warnings-errors 'silent) + + ;; restrict which warnings are shown + '(warning-minimum-level :emergency) + ) + + ;; auto-completion + (global-company-mode t) + + ;; hooks + (add-hook 'LaTeX-mode-hook 'outline-minor-mode) + + ;; Key bindings + (defun my-ediff-dotfile-and-template () + (interactive) + (ediff-files "~/code/nix/latitude-7490/home/config/dotfiles/spacemacs" + (concat dotspacemacs-template-directory ".spacemacs.template"))) + (spacemacs/set-leader-keys "feD" 'my-ediff-dotfile-and-template) + (defun my-open-dotfile () + (interactive) + (find-file "~/code/nix/latitude-7490/home/config/dotfiles/spacemacs")) + (spacemacs/set-leader-keys "fed" 'my-open-dotfile) + + (spacemacs/set-leader-keys-for-major-mode 'magit-mode "b" 'magit-branch) +) + +;; Do not write anything past this comment. This is where Emacs will +;; auto-generate custom variable definitions. +(defun dotspacemacs/emacs-custom-settings () + "Emacs custom settings. +This is an auto-generated function, do not modify its content directly, use +Emacs customize menu instead. +This function is called at the very end of Spacemacs initialization." +(custom-set-variables + ;; custom-set-variables was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(package-selected-packages + '(yapfify utop tuareg caml sphinx-doc pytest pyenv-mode py-isort poetry pippel pipenv pyvenv pip-requirements ocp-indent ocamlformat merlin-eldoc live-py-mode importmagic epc ctable concurrent deferred helm-pydoc flycheck-ocaml merlin dune cython-mode company-reftex company-math math-symbol-lists company-auctex company-anaconda blacken auctex anaconda-mode pythonic yasnippet-snippets unfill treemacs-magit smeargle orgit-forge orgit org-rich-yank org-projectile org-category-capture org-present org-pomodoro alert log4e gntp org-mime org-download org-cliplink org-brain nix-mode mwim mmm-mode markdown-toc magit-svn magit-section magit-gitflow magit-popup htmlize helm-org-rifle helm-nixos-options helm-gitignore helm-git-grep helm-company helm-c-yasnippet gnuplot gitignore-templates gitignore-mode gitconfig-mode gitattributes-mode git-timemachine git-messenger git-link git-gutter-fringe+ fringe-helper git-gutter+ gh-md fuzzy forge markdown-mode magit ghub closql emacsql-sqlite emacsql treepy git-commit with-editor transient flyspell-correct-helm flyspell-correct flycheck-pos-tip pos-tip evil-org company-nixos-options nixos-options company browse-at-remote auto-yasnippet yasnippet auto-dictionary ac-ispell auto-complete ws-butler writeroom-mode visual-fill-column winum volatile-highlights vi-tilde-fringe uuidgen undo-tree treemacs-projectile treemacs-persp treemacs-icons-dired treemacs-evil treemacs cfrs ht pfuture posframe toc-org symon symbol-overlay string-inflection string-edit spaceline-all-the-icons memoize all-the-icons spaceline powerline restart-emacs request rainbow-delimiters popwin persp-mode password-generator paradox spinner overseer org-superstar open-junk-file nameless multi-line shut-up macrostep lorem-ipsum link-hint indent-guide hungry-delete hl-todo highlight-parentheses highlight-numbers parent-mode highlight-indentation helm-xref helm-themes helm-swoop helm-purpose window-purpose imenu-list helm-projectile helm-org helm-mode-manager helm-make helm-ls-git helm-flx helm-descbinds helm-ag google-translate golden-ratio flycheck-package package-lint flycheck flycheck-elsa flx-ido flx fancy-battery eyebrowse expand-region evil-visualstar evil-visual-mark-mode evil-unimpaired f evil-tutor evil-textobj-line evil-surround evil-numbers evil-nerd-commenter evil-mc evil-matchit evil-lisp-state evil-lion evil-indent-plus evil-iedit-state evil-goggles evil-exchange evil-escape evil-ediff evil-easymotion evil-collection annalist evil-cleverparens smartparens evil-args evil-anzu anzu eval-sexp-fu emr iedit clang-format projectile paredit list-utils pkg-info epl elisp-slime-nav editorconfig dumb-jump s drag-stuff dired-quick-sort devdocs define-word dash column-enforce-mode clean-aindent-mode centered-cursor-mode auto-highlight-symbol auto-compile packed aggressive-indent ace-window ace-link ace-jump-helm-line helm avy helm-core popup which-key use-package pcre2el org-plus-contrib hydra lv hybrid-mode font-lock+ evil goto-chg dotenv-mode diminish bind-map bind-key async))) +(custom-set-faces + ;; custom-set-faces was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + ) +) diff --git a/modules/home-manager/personal/dotfiles/venv-manager.nix b/modules/home-manager/personal/dotfiles/venv-manager.nix new file mode 100644 index 0000000..248cb0c --- /dev/null +++ b/modules/home-manager/personal/dotfiles/venv-manager.nix @@ -0,0 +1,39 @@ +{ config, lib, pkgs, ... }: + +{ + direnv.enable = lib.mkDefault true; + + haskell = { spacemacs.enable = lib.mkDefault true; }; + + latex = { + packages = tl: { + inherit (tl) + scheme-basic # scheme + koma-script ragged2e everysel footmisc # koma + ; + }; + latexmk = { + enable = lib.mkDefault true; + output.pdf.enable = lib.mkDefault true; + rc = + lib.optional (lib.pathExists ~/.config/latexmkrc) ~/.config/latexmkrc; + }; + }; + + nix.enable = lib.mkDefault true; + + ocaml.tuareg.enable = lib.mkDefault true; + + coq.coq = pkgs.coq_8_15; + # pkgs.coq_8_15.override { buildIde = false; }; + + why3 = { + defaultEditor = "emacsclient -c"; + extraConfig = lib.optionalString config.coq.enable '' + [prover] + editor = "" + name = "Coq" + version = "8.15+rc1" + ''; + }; +} diff --git a/modules/home-manager/personal/environment.nix b/modules/home-manager/personal/environment.nix new file mode 100644 index 0000000..3d29db1 --- /dev/null +++ b/modules/home-manager/personal/environment.nix @@ -0,0 +1,20 @@ +{ config, lib, pkgs, ... }: + +{ + home.packages = with pkgs; [ coreutils moreutils ]; + personal.home.wallpaper = lib.mkDefault config.personal.home.dotfiles.wallpaper; + + programs.bash = { + enable = lib.mkDefault true; + }; + + home = { + shellAliases = { + amimullvad = "curl -Ls https://am.i.mullvad.net/connected"; + rm = "rm -f"; + ssh = "TERM=xterm-256color ssh"; + edit = "$EDITOR"; + }; + sessionVariables = { CDPATH = "~"; }; + }; +} diff --git a/modules/home-manager/personal/gui/default.nix b/modules/home-manager/personal/gui/default.nix new file mode 100644 index 0000000..fe50f0c --- /dev/null +++ b/modules/home-manager/personal/gui/default.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }@extraArgs: + +let cfg = config.personal.gui; +in { + imports = [ ./redshift.nix ./x ]; + + options.personal.gui = { + enable = lib.mkEnableOption "GUI" // { + default = extraArgs.osConfig.personal.gui.enable or false; + }; + }; + + config = lib.mkIf cfg.enable { + services.kdeconnect.indicator = lib.mkDefault true; + + home.pointerCursor = lib.mkDefault { + name = "Numix-Cursor-Light"; + package = pkgs.numix-cursor-theme; + }; + + dconf.enable = lib.mkDefault true; + gtk = { + enable = lib.mkDefault true; + theme = lib.mkDefault { + name = "Arc-Dark"; + package = pkgs.arc-theme; + }; + iconTheme = lib.mkDefault { + name = "breeze-dark"; + package = pkgs.breeze-icons; + }; + }; + qt = { + enable = lib.mkDefault true; + platformTheme = lib.mkDefault "gtk"; + }; + + home.packages = lib.optional config.dconf.enable pkgs.dconf + ++ [ pkgs.keepassxc ]; + programs.firefox.enable = true; + }; +} diff --git a/modules/home-manager/personal/gui/redshift.nix b/modules/home-manager/personal/gui/redshift.nix new file mode 100644 index 0000000..2242ad2 --- /dev/null +++ b/modules/home-manager/personal/gui/redshift.nix @@ -0,0 +1,17 @@ +{ config, lib, ... }@extraArgs: + +{ + services.redshift = { + enable = lib.mkDefault config.personal.gui.enable; + tray = lib.mkDefault true; + temperature = { + day = lib.mkDefault 2500; + night = lib.mkDefault 2500; + }; + latitude = + extraArgs.osConfig.location.latitude or (lib.mkDefault "48.856614"); + longitude = + extraArgs.osConfig.location.longitude or (lib.mkDefault "2.3522219"); + settings.redshift.transition = lib.mkDefault 0; + }; +} diff --git a/modules/home-manager/personal/gui/x/default.nix b/modules/home-manager/personal/gui/x/default.nix new file mode 100644 index 0000000..0de1552 --- /dev/null +++ b/modules/home-manager/personal/gui/x/default.nix @@ -0,0 +1,14 @@ +{ config, lib, ... }@extraArgs: + +let cfg = config.personal.x; +in { + imports = [ ./i3 ./idlehook.nix ]; + + options.personal.x = { + enable = lib.mkEnableOption "X" // { + default = extraArgs.osConfig.services.xserver.enable or false; + }; + }; + + config.xsession.enable = lib.mkDefault cfg.enable; +} diff --git a/modules/home-manager/personal/gui/x/i3/bar/default.nix b/modules/home-manager/personal/gui/x/i3/bar/default.nix new file mode 100644 index 0000000..58d4bce --- /dev/null +++ b/modules/home-manager/personal/gui/x/i3/bar/default.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }@extraArgs: + +let + statusPackage = + pkgs.personal.barista.override { i3statusGo = ./i3status.go; }; +in { + xsession.windowManager.i3.config.bars = [{ + statusCommand = "${statusPackage}/bin/i3status"; + fonts = { + names = [ "roboto" ]; + size = 11.0; + }; + colors.background = "#111111"; + }]; + + home.packages = with pkgs; + lib.optionals + (config.xsession.enable && config.xsession.windowManager.i3.enable) [ + material-design-icons + roboto + # source-code-pro + ]; + + # (Miscellaneous) Tray icons + services.blueman-applet.enable = + lib.mkDefault (extraArgs.osConfig.services.blueman.enable); +} diff --git a/modules/home-manager/personal/gui/x/i3/bar/i3status.go b/modules/home-manager/personal/gui/x/i3/bar/i3status.go new file mode 100644 index 0000000..196e6cc --- /dev/null +++ b/modules/home-manager/personal/gui/x/i3/bar/i3status.go @@ -0,0 +1,289 @@ +package main + +import ( + "io" + "net/http" + "os" + "regexp" + "strconv" + "time" + + "barista.run" + "barista.run/bar" + "barista.run/colors" + "barista.run/group" + "barista.run/modules/battery" + "barista.run/modules/clock" + "barista.run/modules/diskspace" + "barista.run/modules/funcs" + "barista.run/modules/netinfo" + "barista.run/modules/systemd" + "barista.run/modules/volume" + "barista.run/modules/volume/pulseaudio" + "barista.run/modules/wlan" + "barista.run/outputs" + "barista.run/pango" + "barista.run/pango/icons/mdi" +) + +func main() { + // Constants + colors.LoadFromMap(map[string]string{ + // Color palette of Cezanne's Vue de la Baie de Marseille + "good": "#C5D294", + "degraded": "#E9CC67", + "bad": "#FFBC88", + }) + mdi.Load() // repo path will be inserted at build time + + // Display status of several services + updateSuccessIcon := pango.Icon("mdi-reload") + updatingIcon := pango.Icon("mdi-update") + updateFailIcon := pango.Icon("mdi-reload-alert") + garbageFullIcon := pango.Icon("mdi-delete") + garbageEmptyingIcon := pango.Icon("mdi-delete-restore") + garbageEmptyIcon := pango.Icon("mdi-delete-outline") + barista.Add(group.Simple(systemd.Service("nixos-upgrade").Output(func(i systemd.ServiceInfo) bar.Output { + state := i.UnitInfo.State + var colorScheme string + var output *pango.Node + switch { + case state == systemd.StateInactive: + colorScheme = "good" + output = updateSuccessIcon + case state == systemd.StateActivating: + colorScheme = "degraded" + output = updatingIcon + default: + colorScheme = "bad" + output = updateFailIcon + } + return outputs.Pango(output).Color(colors.Scheme(colorScheme)) + }), + systemd.Service("nix-gc").Output(func(i systemd.ServiceInfo) bar.Output { + state := i.UnitInfo.State + var colorScheme string + var output *pango.Node + switch { + case state == systemd.StateInactive: + colorScheme = "good" + output = garbageEmptyIcon + case state == systemd.StateActivating: + colorScheme = "degraded" + output = garbageEmptyingIcon + default: + colorScheme = "bad" + output = garbageFullIcon + } + return outputs.Pango(output).Color(colors.Scheme(colorScheme)) + }))) + + // Display space left on / + storageIcon := pango.Icon("mdi-database") + barista.Add(diskspace.New("/").Output(func(i diskspace.Info) bar.Output { + used := i.UsedPct() + var colorScheme string + if used >= 90 { + colorScheme = "bad" + } else if used >= 50 { + colorScheme = "degraded" + } else { + colorScheme = "good" + } + return outputs.Pango(storageIcon, pango.Textf(" %d%%", used)).Color(colors.Scheme(colorScheme)) + })) + + // Check connection to the Mullvad VPN + mullvadIsUpRe := regexp.MustCompile(`^You are connected to Mullvad`) + mullvadServerRe := regexp.MustCompile(`\(server (.*)\)`) + mullvadIpRe := regexp.MustCompile(`Your IP address is (.*)`) + client := &http.Client{Timeout: 3 * time.Second} + incognitoIcon := pango.Icon("mdi-incognito") + incognitoOffIcon := pango.Icon("mdi-incognito-off") + barista.Add(funcs.Every(5*time.Second, func(s bar.Sink) { + icon := incognitoOffIcon + message := pango.Text("") + colorScheme := "bad" + res, err := client.Get("https://am.i.mullvad.net/connected") + if !s.Error(err) { + status, err := io.ReadAll(res.Body) + res.Body.Close() + if !s.Error(err) { + var re *regexp.Regexp + if mullvadIsUpRe.Match(status) { + re = mullvadServerRe + colorScheme = "good" + icon = incognitoIcon + } else { + re = mullvadIpRe + colorScheme = "degraded" + } + result := re.FindSubmatch(status) + if len(result) >= 2 { + message = pango.Textf(" %s", result[1]) + } + } + } + client.CloseIdleConnections() + s.Output(outputs.Pango(icon, message).Color(colors.Scheme(colorScheme))) + })) + + // Display the wifi status + wifiOffIcon := pango.Icon("mdi-wifi-off") + wifiRefreshIcon := pango.Icon("mdi-wifi-refresh") + wifiOnIcon := pango.Icon("mdi-wifi") + barista.Add(wlan.Named("wlp2s0").Output(func(w wlan.Info) bar.Output { + var output *pango.Node + var colorScheme string + switch { + case w.Connected(): + output = pango.New(wifiOnIcon, pango.Textf(" %s", w.SSID)) + colorScheme = "good" + case w.Connecting(): + output = wifiRefreshIcon + colorScheme = "degraded" + default: + output = wifiOffIcon + colorScheme = "bad" + } + return outputs.Pango(output).Color(colors.Scheme(colorScheme)) + })) + + // Display the ethernet status + ethernetCableOnIcon := pango.Icon("mdi-ethernet-cable") + ethernetCableOffIcon := pango.Icon("mdi-ethernet-cable-off") + barista.Add(netinfo.Prefix("e").Output(func(s netinfo.State) bar.Output { + var output *pango.Node + var colorScheme string + switch { + case s.Connected(): + ip := "<no ip>" + if len(s.IPs) > 0 { + ip = s.IPs[0].String() + } + output = pango.New(ethernetCableOnIcon, pango.Textf(" %s", ip)) + colorScheme = "good" + case s.Connecting(): + output = ethernetCableOnIcon + colorScheme = "degraded" + default: + output = ethernetCableOffIcon + colorScheme = "bad" + } + return outputs.Pango(output).Color(colors.Scheme(colorScheme)) + })) + + // Display the battery status + batteryIcons := [11]*pango.Node{pango.Icon("mdi-battery-outline"), + pango.Icon("mdi-battery-10"), + pango.Icon("mdi-battery-20"), + pango.Icon("mdi-battery-30"), + pango.Icon("mdi-battery-40"), + pango.Icon("mdi-battery-50"), + pango.Icon("mdi-battery-60"), + pango.Icon("mdi-battery-70"), + pango.Icon("mdi-battery-80"), + pango.Icon("mdi-battery-90"), + pango.Icon("mdi-battery")} + batteryChargingIcons := [11]*pango.Node{pango.Icon("mdi-battery-charging-outline"), + pango.Icon("mdi-battery-charging-10"), + pango.Icon("mdi-battery-charging-20"), + pango.Icon("mdi-battery-charging-30"), + pango.Icon("mdi-battery-charging-40"), + pango.Icon("mdi-battery-charging-50"), + pango.Icon("mdi-battery-charging-60"), + pango.Icon("mdi-battery-charging-70"), + pango.Icon("mdi-battery-charging-80"), + pango.Icon("mdi-battery-charging-90"), + pango.Icon("mdi-battery-charging-100")} + barista.Add(battery.All().Output(func(b battery.Info) bar.Output { + switch b.Status { + case battery.Disconnected, battery.Unknown: + return nil + default: + var icons [11]*pango.Node + var colorScheme string + if b.Status == battery.Charging { + icons = batteryChargingIcons + colorScheme = "good" + } else { + icons = batteryIcons + if b.RemainingPct() <= 10 { + colorScheme = "bad" + } else if b.RemainingPct() <= 20 { + colorScheme = "degraded" + } else { + colorScheme = "good" + } + } + icon := icons[b.RemainingPct()/10] + return outputs.Pango(icon, pango.Textf(" %d%%", b.RemainingPct())).Color(colors.Scheme(colorScheme)) + } + })) + + // Display brightness + brightnessHighIcon := pango.Icon("mdi-lightbulb-on") + brightnessMidIcon := pango.Icon("mdi-lightbulb-on-outline") + brightnessLowIcon := pango.Icon("mdi-lightbulb-outline") + ReadBrightness := func(name string) (int, error) { + valueStr, err := os.ReadFile("/sys/class/backlight/intel_backlight/" + name) + if err != nil { + return 0, err + } + return strconv.Atoi(string(valueStr[:len(valueStr)-1])) + } + brightnessMax, _ := ReadBrightness("max_brightness") // always non-zero, unless there's an error + barista.Add(funcs.Every(time.Second, func(s bar.Sink) { + brightness, err := ReadBrightness("brightness") + if !s.Error(err) { + value := (brightness * 100) / brightnessMax + var icon *pango.Node + if value <= 30 { + icon = brightnessLowIcon + } else if value < 70 { + icon = brightnessMidIcon + } else { + icon = brightnessHighIcon + } + s.Output(outputs.Pango(icon, pango.Textf(" %d%%", value))) + } + })) + + // Display output volume + volumeOffIcon := pango.Icon("mdi-volume-variant-off") + volumeLowIcon := pango.Icon("mdi-volume-low") + volumeMidIcon := pango.Icon("mdi-volume-medium") + volumeHighIcon := pango.Icon("mdi-volume-high") + barista.Add(volume.New(pulseaudio.DefaultSink()).Output(func(v volume.Volume) bar.Output { + volume := v.Pct() + var icon *pango.Node + if volume == 0 || v.Mute { + icon = volumeOffIcon + } else if volume <= 30 { + icon = volumeLowIcon + } else if volume <= 70 { + icon = volumeMidIcon + } else { + icon = volumeHighIcon + } + return outputs.Pango(icon, pango.Textf(" %d%%", volume)) + })) + + // Display microphone volume + microphoneOffIcon := pango.Icon("mdi-microphone-off") + microphoneIcon := pango.Icon("mdi-microphone") + barista.Add(volume.New(pulseaudio.DefaultSource()).Output(func(v volume.Volume) bar.Output { + volume := v.Pct() // the value returned by pulseaudio may be weird + var icon *pango.Node + if volume == 0 || v.Mute { + icon = microphoneOffIcon + } else { + icon = microphoneIcon + } + return outputs.Pango(icon, pango.Textf(" %d%%", volume)) + })) + + barista.Add(clock.Local().OutputFormat("2006-01-02 15:04:05")) + + panic(barista.Run()) +} diff --git a/modules/home-manager/personal/gui/x/i3/default.nix b/modules/home-manager/personal/gui/x/i3/default.nix new file mode 100644 index 0000000..beae770 --- /dev/null +++ b/modules/home-manager/personal/gui/x/i3/default.nix @@ -0,0 +1,56 @@ +{ config, lib, pkgs, ... }@extraArgs: + +let cfg = config.personal.x.i3; +in { + imports = [ ./bar ./keybindings.nix ./startup.nix ]; + + options.personal.x.i3 = { + enable = lib.mkEnableOption "i3" // { + default = + extraArgs.osConfig.services.xserver.windowManager.i3.enable or false; + }; + }; + + config = lib.mkIf cfg.enable { + xsession.windowManager.i3 = { + enable = cfg.enable; + package = lib.mkDefault pkgs.i3-gaps; + + config = { + assigns = lib.optionalAttrs (config.personal.profiles.multimedia + && (extraArgs.osConfig.programs.steam.enable or true)) { + "8: multimedia" = [ + { class = "^Steam$"; } + { class = "Netflix"; } + { class = "MUBI"; } + { class = "Deezer"; } + ]; + } // lib.optionalAttrs config.personal.profiles.social { + "9: social" = [ + { class = "^Mail$"; } + { class = "^thunderbird$"; } + { class = "^Signal$"; } + ]; + } // { + "10: passwords" = [{ + # matches <some db>.kbdx [Locked] - KeePassXC + title = ".*\\.kbdx \\[Locked\\] - KeePassXC$"; + }]; + }; + + workspaceAutoBackAndForth = lib.mkDefault true; + + window = { + titlebar = lib.mkDefault false; + border = lib.mkDefault 0; + }; + floating.titlebar = lib.mkDefault false; + gaps = { + inner = lib.mkDefault 15; + outer = lib.mkDefault 5; + }; + }; + }; + programs.rofi.enable = lib.mkDefault true; + }; +} diff --git a/modules/home-manager/personal/gui/x/i3/keybindings.nix b/modules/home-manager/personal/gui/x/i3/keybindings.nix new file mode 100644 index 0000000..3781867 --- /dev/null +++ b/modules/home-manager/personal/gui/x/i3/keybindings.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, ... }: + +let + brightnessctl = "${pkgs.brightnessctl}/bin/brightnessctl"; + brightnessctlKbd = "${brightnessctl} --device dell:kbd_backlight"; + volumectl = "${pkgs.pulseaudio}/bin/pactl"; + screenshot = "${pkgs.shutter}/bin/shutter"; + + modifier = "Mod4"; +in { + xsession.windowManager.i3.config = { + inherit modifier; + + keybindings = lib.mkOptionDefault { + # launching apps + "${modifier}+Control+Return" = ''exec "$EDITOR"''; + "${modifier}+Shift+Return" = ''exec "$BROWSER"''; + "${modifier}+d" = lib.mkIf config.programs.rofi.enable + ''exec "rofi -modi drun,filebrowser,run,window -show drun"''; + + # exiting + "${modifier}+Shift+e" = "exec i3-msg exit"; + "${modifier}+l" = + "exec ${config.personal.home.lockscreen}/bin/lockscreen.sh"; + + # media keys + "XF86MonBrightnessUp" = "exec ${brightnessctl} set 5%+"; + "XF86MonBrightnessDown" = "exec ${brightnessctl} set 5%-"; + "XF86AudioRaiseVolume" = + "exec ${volumectl} set-sink-volume @DEFAULT_SINK@ +5%"; + "XF86AudioLowerVolume" = + "exec ${volumectl} set-sink-volume @DEFAULT_SINK@ -5%"; + "XF86AudioMute" = "exec ${volumectl} set-sink-mute @DEFAULT_SINK@ toggle"; + "Shift+XF86AudioRaiseVolume" = + "exec ${volumectl} set-source-volume @DEFAULT_SOURCE@ +5%"; + "Shift+XF86AudioLowerVolume" = + "exec ${volumectl} set-source-volume @DEFAULT_SOURCE@ -5%"; + "XF86AudioMicMute" = + "exec ${volumectl} set-source-mute @DEFAULT_SOURCE@ toggle"; + "XF86KbdBrightnessUp" = '' + exec ${brightnessctlKbd} set \ + $(( $(${brightnessctlKbd} max) - $(${brightnessctlKbd} get) )) + ''; + "Print" = "exec ${screenshot}"; + }; + }; +} diff --git a/modules/home-manager/personal/gui/x/i3/startup.nix b/modules/home-manager/personal/gui/x/i3/startup.nix new file mode 100644 index 0000000..9baf388 --- /dev/null +++ b/modules/home-manager/personal/gui/x/i3/startup.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +{ + xsession.windowManager.i3.config.startup = let + autostart = { command, always ? false, notification ? false }: { + inherit command always notification; + }; + autostartIf = cond: args: lib.optional cond (autostart args); + in [ + (autostart { command = "rfkill block bluetooth"; }) + (autostart { command = "keepassxc"; }) + ] + ++ autostartIf config.programs.thunderbird.enable { command = "thunderbird"; } + ++ autostartIf config.personal.profiles.social { command = "signal-desktop"; } + # ++ autostartIf config.services.redshift.enable { + # command = "systemctl --user start redshift"; + # } + ++ autostartIf (config.personal.home.wallpaper != null) { + command = "${pkgs.feh}/bin/feh --bg-scale ${config.personal.home.wallpaper}"; + } + # ++ autostartIf config.services.xidlehook.enable { + # command = "systemctl --user start xidlehook.service"; + # } + ; +} diff --git a/modules/home-manager/personal/gui/x/idlehook.nix b/modules/home-manager/personal/gui/x/idlehook.nix new file mode 100644 index 0000000..129a9f8 --- /dev/null +++ b/modules/home-manager/personal/gui/x/idlehook.nix @@ -0,0 +1,22 @@ +{ config, lib, pkgs, ... }: + +let + brightnessctl = "${pkgs.brightnessctl}/bin/brightnessctl"; +in { + config.services.xidlehook = { + enable = lib.mkDefault config.personal.x.enable; + not-when-fullscreen = lib.mkDefault true; + not-when-audio = lib.mkDefault true; + timers = [ + { + delay = 120; + command = "${brightnessctl} set 10%-"; + canceller = "${brightnessctl} set +10%"; + } + { + delay = 180; + command = config.personal.home.lockscreen; + } + ]; + }; +} diff --git a/modules/home-manager/personal/profiles.nix b/modules/home-manager/personal/profiles.nix new file mode 100644 index 0000000..25722f5 --- /dev/null +++ b/modules/home-manager/personal/profiles.nix @@ -0,0 +1,157 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.personal.profiles; + mkEnableProfileOption = name: lib.mkEnableOption "${name} profile"; +in { + options.personal.profiles = { + dev = mkEnableProfileOption "development"; + social = mkEnableProfileOption "social"; + syncing = mkEnableProfileOption "syncing"; + multimedia = mkEnableProfileOption "video"; + }; + + config = lib.mkMerge [ + (lib.mkIf cfg.dev { + home.packages = with pkgs; [ gnupg python3 ]; + programs = { + alacritty.enable = lib.mkDefault config.personal.gui.enable; + direnv.enable = lib.mkDefault true; + emacs.enable = lib.mkDefault true; + git.enable = lib.mkDefault true; + }; + + home.shellAliases = { + mkenv = '' + cp ~/.config/venv-manager/shell-template.nix ./shell.nix ; + echo "use_nix" >> .envrc ; + direnv allow ; + $EDITOR shell.nix ; + ''; + }; + + services.gpg-agent = { + enable = true; + enableSshSupport = true; + }; + + home.file = { + ".config/latexmkrc".text = + builtins.readFile config.personal.home.dotfiles.latexmkrc; + ".config/venv-manager/config/default.nix".source = + lib.mkDefault config.personal.home.dotfiles.venv-manager; + }; + }) + + (lib.mkIf cfg.multimedia { + home.packages = with pkgs; [ pavucontrol transmission-gtk vlc ]; + personal = { + gui.enable = lib.mkForce true; + firefox.webapps = [ + { + name = "Netflix"; + genericName = "Streaming service"; + icon = "${pkgs.personal.netflixIcon}"; + comment = "Unlimited movies, TV shows, and more."; + url = "https://www.netflix.com/fr-en/login"; + categories = [ "AudioVideo" "Video" "Player" ]; + } + { + name = "MUBI"; + genericName = "Streaming service"; + icon = "${pkgs.personal.mubiIcon}"; + comment = "Watch hand-picked cinema."; + url = "https://mubi.com"; + categories = [ "AudioVideo" "Video" "Player" ]; + } + { + name = "Deezer"; + genericName = "Streaming service"; + icon = "${pkgs.personal.deezerIcon}"; + comment = "Listen to music online"; + url = "https://deezer.com/login"; + categories = [ "AudioVideo" "Audio" "Player" "Music" ]; + } + ]; + }; + }) + + (lib.mkIf cfg.social { + home.packages = with pkgs; + lib.optionals config.personal.gui.enable [ signal-desktop ]; + programs.thunderbird.enable = lib.mkDefault config.personal.gui.enable; + accounts.email.accounts = let + gpg = { + key = "DFC1660846EEA97C059F18534EF515441E635D36"; + signByDefault = true; + }; + thunderbirdSettings = id: { + "mail.identity.id_${id}.fcc_folder_picker_mode" = 0; + }; + in { + personal = { + inherit gpg; + address = "quentin@aristote.fr"; + userName = "quentin@aristote.fr"; + realName = "Quentin Aristote"; + folders = { + drafts = "Inbox/Brouillons"; + inbox = "Inbox"; + sent = "Inbox/Envoyés"; + trash = "Inbox/Corbeille"; + }; + imap = { + host = "ssl0.ovh.net"; + port = 993; + }; + smtp = { + host = "ssl0.ovh.net"; + port = 465; + }; + thunderbird = { + enable = true; + profiles = [ "all" "personal" ]; + settings = thunderbirdSettings; + }; + }; + work = { + inherit gpg; + address = "quentin.aristote@ens.fr"; + userName = "qaristote"; + realName = "Quentin Aristote"; + aliases = [ + "quentin.aristote@ens.psl.eu" + "qaristote@clipper.ens.fr" + "qaristote@clipper.ens.psl.eu" + ]; + folders = { + drafts = "Drafts"; + inbox = "Inbox"; + sent = "Sent"; + trash = "Trash"; + }; + imap = { + host = "clipper.ens.fr"; + port = 993; + }; + smtp = { + host = "clipper.ens.fr"; + port = 465; + }; + thunderbird = { + enable = true; + profiles = [ "all" "work" ]; + settings = thunderbirdSettings; + }; + }; + }; + }) + + (lib.mkIf cfg.syncing { + services = { + kdeconnect.enable = lib.mkDefault true; + syncthing.enable = lib.mkDefault true; + }; + }) + ]; +} diff --git a/modules/home-manager/personal/programs/alacritty.nix b/modules/home-manager/personal/programs/alacritty.nix new file mode 100644 index 0000000..afecfc9 --- /dev/null +++ b/modules/home-manager/personal/programs/alacritty.nix @@ -0,0 +1,21 @@ +{ config, lib, ... }: + +{ + programs.alacritty.settings = { + window = { + padding = { + x = 10; + y = 10; + }; + dimensions = { + lines = 75; + columns = 100; + }; + }; + + font = { size = 8.0; }; + }; + + xsession.windowManager.i3.config.terminal = lib.mkIf config.programs.alacritty.enable "alacritty"; +} + diff --git a/modules/home-manager/personal/programs/default.nix b/modules/home-manager/personal/programs/default.nix new file mode 100644 index 0000000..8b3ba16 --- /dev/null +++ b/modules/home-manager/personal/programs/default.nix @@ -0,0 +1,13 @@ +{ ... }: + +{ + imports = [ + ./alacritty.nix + ./direnv.nix + ./emacs.nix + ./firefox + ./git.nix + ./rofi.nix + ./thunderbird.nix + ]; +} diff --git a/modules/home-manager/personal/programs/direnv.nix b/modules/home-manager/personal/programs/direnv.nix new file mode 100644 index 0000000..7d87dc2 --- /dev/null +++ b/modules/home-manager/personal/programs/direnv.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +let cfg = config.programs.direnv; +in { + programs.direnv.nix-direnv.enable = true; + + systemd.user = lib.mkIf cfg.enable + (pkgs.personal.lib.homeManager.serviceWithTimer "direnv-clean-update" { + Unit = { + Description = + "Remove old virtual environments and update the current ones"; + After = [ "network-online.target" ]; + }; + Service = { + Type = "oneshot"; + ExecSearchPath = + "${pkgs.coreutils}/bin:${pkgs.findutils}/bin:${pkgs.direnv}/bin:/bin/sh"; + WorkingDirectory = "${config.home.homeDirectory}"; + ExecStart = '' + find -type d -name .direnv \ + -execdir /bin/sh -c "rm -f .direnv/{nix,flake}-profile*" \; \ + -execdir direnv exec . true \; + ''; + }; + Timer = { + Persistent = true; + OnCalendar = "daily"; + }; + Install = { WantedBy = [ "default.target " ]; }; + }); +} diff --git a/modules/home-manager/personal/programs/emacs.nix b/modules/home-manager/personal/programs/emacs.nix new file mode 100644 index 0000000..2189541 --- /dev/null +++ b/modules/home-manager/personal/programs/emacs.nix @@ -0,0 +1,59 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.programs.emacs; + spacemacs-update-script = pkgs.callPackage ({ emacs, git }: + pkgs.writeShellApplication { + name = "spacemacs-update"; + + runtimeInputs = [ emacs git ]; + + text = '' + git checkout develop + git pull + git checkout local + git merge develop + emacs --fg-daemon=update-daemon \ + --eval '(progn + (configuration-layer/update-packages "no-confirmation") + (spacemacs/kill-emacs))' + ''; + }) { emacs = cfg.package; }; +in { + config = lib.mkIf cfg.enable { + services.emacs = { + enable = lib.mkDefault true; + client.enable = lib.mkDefault true; + startWithUserSession = lib.mkDefault true; + }; + home.sessionVariables.EDITOR = "emacsclient --create-frame"; + + # add some packages necessary in spacemacs + programs.emacs.extraPackages = + lib.mkDefault (ep: with ep; [ emacsql-sqlite emacsql-sqlite3 ]); + home.packages = with pkgs; [ gnutar source-code-pro ]; + + # spacemacs dotfile + home.file.".spacemacs.d/init.el".source = + lib.mkDefault config.personal.home.dotfiles.spacemacs; + + # service to update spacemacs + systemd.user = + (pkgs.personal.lib.homeManager.serviceWithTimer "spacemacs-update" { + Unit = { + Description = "Update Spacemacs by pulling the develop branch"; + After = [ "network-online.target" "emacs.service" ]; + }; + Service = { + Type = "oneshot"; + WorkingDirectory = "${config.home.homeDirectory}/.emacs.d/"; + ExecStart = "${spacemacs-update-script}"; + }; + Timer = { + Persistent = true; + OnCalendar = "daily"; + }; + Install = { WantedBy = [ "default.target" ]; }; + }); + }; +} diff --git a/modules/home-manager/personal/programs/firefox/default.nix b/modules/home-manager/personal/programs/firefox/default.nix new file mode 100644 index 0000000..1e97c40 --- /dev/null +++ b/modules/home-manager/personal/programs/firefox/default.nix @@ -0,0 +1,139 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.personal.firefox; + userjs = pkgs.callPackage ./userjs.nix { + inherit (pkgs.personal) arkenfoxUserJS; + inherit (pkgs.lib.personal) toUserJS; + }; + engines = import ./engines.nix; + userchrome-treestyletabs = '' + /* Hide main tabs toolbar */ + #TabsToolbar { + visibility: collapse; + } + /* Sidebar min and max width removal */ + #sidebar { + max-width: none !important; + min-width: 0px !important; + } + /* Hide sidebar header, when using Tree Style Tab. */ + #sidebar-box[sidebarcommand="treestyletab_piro_sakura_ne_jp-sidebar-action"] #sidebar-header { + visibility: collapse; + } + ''; + extensions = with pkgs.personal; [ + canvasblocker + clearurls + darkreader + neat-url + redirector + smart-referer + temporary-containers + tree-style-tab + ublock-origin + unpaywall + url-in-title + ]; + webappsWithIds = (builtins.foldl' ({ counter, value }: + { name, ... }@next: { + counter = counter + 1; + value = value ++ [ + (next // { + id = counter; + profileName = lib.toLower name; + }) + ]; + }) { + counter = 0; + value = [ ]; + } cfg.webapps).value; +in { + options.personal.firefox = { + webapps = lib.mkOption { + type = with lib.types; + listOf (submodule { + options = let mkTypedOption = type: lib.mkOption { inherit type; }; + in { + name = mkTypedOption str; + genericName = mkTypedOption str // { default = ""; }; + url = mkTypedOption str; + comment = mkTypedOption str // { default = ""; }; + extraUserJS = mkTypedOption lines // { default = ""; }; + categories = mkTypedOption (listOf str) // { default = [ ]; }; + icon = mkTypedOption path; + }; + }); + default = [ ]; + }; + }; + + config = lib.mkMerge [ + { + programs.firefox.profiles = builtins.foldl' (prev: + { name, id, profileName, extraUserJS, ... }: + prev // { + "${profileName}" = { + inherit extensions; + id = id + 2; + extraConfig = userjs.streaming + extraUserJS; + }; + }) { + default = { + inherit extensions; + id = 0; # isDefault = true + + extraConfig = userjs.default; + userChrome = userchrome-treestyletabs; + search = { + force = lib.mkDefault true; + engines = { + inherit (engines) Searx; + "Bing".metaData.hidden = true; + "Google".metaData.hidden = true; + "Amazon.fr".metaData.hidden = true; + }; + default = "Searx"; + order = [ "Searx" "Wikipedia" ]; + }; + }; + + videoconferencing = { + inherit extensions; + id = 1; + + extraConfig = userjs.videoconferencing; + userChrome = userchrome-treestyletabs; + }; + } webappsWithIds; + } + + (lib.mkIf config.programs.firefox.enable { + xdg.desktopEntries = let + firefoxProfilesDir = "${config.home.homeDirectory}/.mozilla/firefox"; + firefoxInProfile = profile: + '' + ${config.programs.firefox.package}/bin/firefox --profile "${firefoxProfilesDir}/${profile}"''; + in builtins.foldl' (prev: + { name, profileName, url, genericName, icon, comment, categories, ... }: + prev // { + "${profileName}" = { + inherit name genericName icon comment categories; + exec = "${firefoxInProfile profileName} ${url}"; + }; + }) { + videoconferences = { + name = "Video Conferences"; + genericName = "Video conference"; + comment = "Use video conferencing software in a browser."; + exec = "${firefoxInProfile "videoconferencing"}"; + categories = [ "Network" "VideoConference" ]; + }; + } webappsWithIds; + + home.shellAliases.fftmp = "firefox --profile $(mktemp -d)"; + home.sessionVariables.BROWSER = "firefox"; + }) + ]; +} diff --git a/modules/home-manager/personal/programs/firefox/engines.nix b/modules/home-manager/personal/programs/firefox/engines.nix new file mode 100644 index 0000000..7ea2830 --- /dev/null +++ b/modules/home-manager/personal/programs/firefox/engines.nix @@ -0,0 +1,8 @@ +{ + Searx = { + urls = [{ template = "https://searx.aristote.fr/search?q={searchTerms}"; }]; + iconUpdateURL = + "https://searx.aristote.fr/static/themes/oscar/img/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; # every day + }; +} diff --git a/modules/home-manager/personal/programs/firefox/userjs.nix b/modules/home-manager/personal/programs/firefox/userjs.nix new file mode 100644 index 0000000..ee105b3 --- /dev/null +++ b/modules/home-manager/personal/programs/firefox/userjs.nix @@ -0,0 +1,66 @@ +{ arkenfoxUserJS, toUserJS }: + +rec { + arkenfox = builtins.readFile "${arkenfoxUserJS}"; + default = arkenfox + toUserJS { + "keyword.enabled" = true; # 0801 + "signon.rememberSignons" = false; # 0901 + "security.nocertdb" = true; # 1222 + "media.peerconnection.enabled" = false; # 2001 + "media.peerconnection.ice.no_host" = true; # 2004 + "dom.allow_cut_copy" = true; # 2404 + "dom.battery.enabled" = false; # 2502 + "permissions.default.xr" = 2; # 2521 + "privacy.clearOnShutdown.siteSettings" = true; # 2811 + + # Personal + ## Warnings + "browser.tabs.warnOnClose" = false; + "browser.tabs.warnOnCloseOtherTabs" = false; + ## Updates + "app.update.auto" = false; + "browser.search.update" = false; + ## Appearance + "toolkit.legacyUserProfileCustomizations.stylesheets" = true; + ## Content behavior + "clipboard.autocopy" = false; + ## UX behavior + "browser.quitShortcut.disabled" = true; + "browser.tabs.closeWindowWithLastTab" = false; + ## UX features + "extensions.pocket.enabled" = false; + "identity.fxaccounts.enabled" = false; + }; + + streaming = default + toUserJS { + # Widevine (DRMs) + "media.gmp-widevinecdm.enabled" = true; + "media.eme.enabled" = true; + # Cache + "browser.cache.disk.enable" = true; + "browser.cache.offline.storage" = true; + # Privacy + "privacy.clearOnShutdown.cache" = false; + "privacy.clearOnShutdown.cookies" = false; + "privacy.clearOnShutdown.siteSettings" = false; + "privacy.clearOnShutdown.offlineApps" = false; + "privacy.resistFingerprinting" = false; # Netflix is whining + }; + + videoconferencing = default + toUserJS { + # IMPORTANT: uncheck "Prevent WebRTC from leaking local IP addresses" in uBlock Origin's settings + # NOTE: if using RFP (4501) + # some sites, e.g. Zoom, need a canvas site exception [Right Click>View Page Info>Permissions] + # Discord video does not work: it thinks you are FF78: use a separate profile or spoof the user agent + "media.peerconnection.enabled" = true; + "media.peerconnection.ice.no_host" = false; # may or may not be required + "webgl.disabled" = false; # required for Zoom + "webgl.min_capability_mode" = false; + "media.getusermedia.screensharing.enabled" = true; # optional + "media.autoplay.blocking_policy" = + 0; # optional (otherwise add site exceptions) + "javascript.options.wasm" = + true; # optional (some platforms may require this) + "dom.webaudio.enabled" = true; + }; +} diff --git a/modules/home-manager/personal/programs/git.nix b/modules/home-manager/personal/programs/git.nix new file mode 100644 index 0000000..5d272dc --- /dev/null +++ b/modules/home-manager/personal/programs/git.nix @@ -0,0 +1,21 @@ +{ lib, pkgs, ... }: + +{ + programs.git = { + userName = lib.mkDefault "Quentin Aristote"; + userEmail = lib.mkDefault "quentin@aristote.fr"; + + ignores = builtins.map builtins.readFile + (with pkgs.personal; [ emacsGitignore linuxGitignore direnvGitignore ]) + ++ [ + # Personal rules + '' + # Nix + shell.nix + .nix-gc-roots + .tmp + result + '' + ]; + }; +} diff --git a/modules/home-manager/personal/programs/rofi.nix b/modules/home-manager/personal/programs/rofi.nix new file mode 100644 index 0000000..141339c --- /dev/null +++ b/modules/home-manager/personal/programs/rofi.nix @@ -0,0 +1,8 @@ +{ config, lib, ... }: + +{ + programs.rofi = { + cycle = lib.mkDefault true; + theme = lib.mkDefault config.personal.home.dotfiles.rofi; + }; +} diff --git a/modules/home-manager/personal/programs/thunderbird.nix b/modules/home-manager/personal/programs/thunderbird.nix new file mode 100644 index 0000000..c3450af --- /dev/null +++ b/modules/home-manager/personal/programs/thunderbird.nix @@ -0,0 +1,35 @@ +{ config, lib, pkgs, ... }: + +let + configDefault = builtins.readFile "${pkgs.personal.thunderbirdUserJS}" + + pkgs.lib.personal.toUserJS { + # 0391 + "mail.bii.alert.show_preview" = false; + # 0610 + "browser.send_pings" = false; + # 5004 + "permissions.memory_only" = false; + # 5016 + "browser.download.folderList" = 1; + # 9000 + "app.update.auto" = false; + # 9131 + "extensions.cardbook.useOnlyEmail" = false; + # 9312 + "calendar.timezone.local" = "Europe/Paris"; + }; + profiles = { + all = { }; + personal = { }; + work = { }; + }; +in { + config = lib.mkMerge [ + { programs.thunderbird = { inherit profiles; }; } + (lib.mkIf config.programs.thunderbird.enable { + home.file = lib.concatMapAttrs + (name: _: { ".thunderbird/${name}/user.js".text = configDefault; }) + profiles; + }) + ]; +} diff --git a/modules/home-manager/wallpaper.nix b/modules/home-manager/wallpaper.nix new file mode 100644 index 0000000..cd71aab --- /dev/null +++ b/modules/home-manager/wallpaper.nix @@ -0,0 +1,14 @@ +{ config, lib, ... }: + +let wallpaper = config.personal.home.wallpaper; +in { + options.personal.home.wallpaper = lib.mkOption { + type = with lib.types; nullOr path; + default = null; + description = '' + Path to the desktop wallpaper. + ''; + example = + lib.literalExample "${config.home.homeDirectory}/images/wallpaper.jpg"; + }; +} diff --git a/modules/nixos/personal/user.nix b/modules/nixos/personal/user.nix index 0d1585e..0cb308a 100644 --- a/modules/nixos/personal/user.nix +++ b/modules/nixos/personal/user.nix @@ -1,22 +1,49 @@ -{ config, lib, ... }: +{ config, lib, ... }@extraArgs: -let cfg = config.personal.user; +let + cfg = config.personal.user; + importedHomeManager = extraArgs ? home-manager; in { + imports = lib.optional importedHomeManager + extraArgs.home-manager.nixosModules.home-manager; + options.personal.user = { enable = lib.mkEnableOption "main user"; name = lib.mkOption { type = lib.types.str; default = "qaristote"; }; + homeManager = { enable = lib.mkEnableOption "home-manager"; }; }; - config.users.users."${cfg.name}" = lib.mkIf cfg.enable { - isNormalUser = true; - extraGroups = [ "wheel" ] ++ lib.optional config.sound.enable "sound" - ++ lib.optional config.networking.networkmanager.enable "networkmanager"; - openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK4wGbl3++lqCjLUhoRyABBrVEeNhIXYO4371srkRoyq qaristote@latitude-7490" - ]; + config = lib.mkIf cfg.enable ({ + users.users."${cfg.name}" = { + isNormalUser = true; + extraGroups = [ "wheel" ] ++ lib.optional config.sound.enable "sound" + ++ lib.optional config.networking.networkmanager.enable + "networkmanager"; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK4wGbl3++lqCjLUhoRyABBrVEeNhIXYO4371srkRoyq qaristote@latitude-7490" + ]; + }; - }; + assertions = let + missingArgAssertion = name: { + assertion = lib.hasAttr name extraArgs || !cfg.homeManager.enable; + message = + "attribute ${name} missing: add it in lib.nixosSystem's specialArgs, or set config.personal.user.homeManager.enable to false"; + }; + in [ + (missingArgAssertion "homeModules") + (missingArgAssertion "home-manager") + ]; + } // lib.optionalAttrs (importedHomeManager && extraArgs ? homeModules) { + home-manager = lib.mkIf cfg.homeManager.enable { + users."${cfg.name}".imports = extraArgs.homeModules; + useGlobalPkgs = lib.mkDefault true; + useUserPackages = lib.mkDefault true; + # TODO fix this: only config.personal options seem to be passed (or not ?) + extraSpecialArgs.osConfig = lib.mkDefault config; + }; + }); } |
