diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e6e6c9f..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "themes/researcher"] - path = themes/researcher - url = git@github.com:ojroques/hugo-researcher.git diff --git a/config.toml b/config.toml index 5b338dc..1de8dbe 100644 --- a/config.toml +++ b/config.toml @@ -11,6 +11,7 @@ staticDir = ["static"] # logo = "logo.svg" [params.footer] text = "Pavel Korytov, 2021" + mainSections = ['posts'] [permalinks] "/" = "/:filename" diff --git a/content/configs/Console.md b/content/configs/Console.md new file mode 100644 index 0000000..2915e56 --- /dev/null +++ b/content/configs/Console.md @@ -0,0 +1,1099 @@ ++++ +title = "Console" +author = ["Pavel"] +draft = false ++++ + +\#+TOC headlines 6 + + +## `.profile` {#dot-profile} + + +### Environment {#environment} + +```sh +# export EDITOR=/usr/bin/vim +# export BROWSER=/usr/bin/firefox +export QT_QPA_PLATFORMTHEME="qt5ct" +export QT_AUTO_SCREEN_SCALE_FACTOR=0 +# export GTK2_RC_FILES="$HOME/.gtkrc-2.0" +``` + + +### My paths {#my-paths} + +My script folders + +```sh +if [ -d "$HOME/bin" ] ; then + export PATH="$HOME/bin:$PATH" + export PATH="$HOME/bin/scripts:$PATH" +fi +``` + + +### Guix settings {#guix-settings} + +Enable extra profiles + +```sh +if [ -z "$IS_ANDROID" ]; then + GUIX_EXTRA_PROFILES=$HOME/.guix-extra-profiles + for i in $GUIX_EXTRA_PROFILES/*; do + profile=$i/$(basename "$i") + if [ -f "$profile"/etc/profile ]; then + GUIX_PROFILE="$profile" + . "$GUIX_PROFILE"/etc/profile + fi + export XDG_DATA_DIRS="$XDG_DATA_DIRS:$profile/share" + unset profile + done +fi +``` + +Set Jupyter config PATH. It defaults to readonly directory somewhere in Guix profile. + +```sh +export JUPYTER_CONFIG_DIR=$HOME/.config/jupyter +``` + +Set a folder for my packages. + +```sh +export GUIX_PACKAGE_PATH=~/guix-packages +``` + + +### Other package managers {#other-package-managers} + +Using other package managers with Guix requires some extra work. + +Cask + +```sh +if [ -d "$HOME/.cask" ]; then + export PATH="/home/pavel/.cask/bin:$PATH" +fi +``` + +Make flatpak apps visible to launchers: + +```sh +if [ -d "$HOME/.local/share/flatpak" ]; then + export XDG_DATA_DIRS="$XDG_DATA_DIRS:$HOME/.local/share/flatpak/exports/share" +fi +``` + +Enable Nix + +```sh +if [ -f /run/current-system/profile/etc/profile.d/nix.sh ]; then + . /run/current-system/profile/etc/profile.d/nix.sh +fi +``` + +Use Guix fontconfig. Necessary for nix apps + +```sh +if [ -d "$HOME/.guix-extra-profiles/desktop" ]; then + export FONTCONFIG_PATH="$HOME/.guix-extra-profiles/desktop/desktop/etc/fonts" +fi +``` + +Make nix apps visible to launchers: + +```sh +if [ -d "$HOME/.nix-profile" ]; then + export XDG_DATA_DIRS="$XDG_DATA_DIRS:$HOME/.nix-profile/share/applications" +fi +``` + + +#### npm {#npm} + +npm is especially cumbersome, for instance because by default it tries to install packages to `/gnu/store/`. + +In principle, one can set a prefix like this: + +```conf +prefix=/home/pavel/.npm-packages +``` + +But I also want to use node from conda occasionally, where prefix is already set correctly. So instead of tangling the above to the `~/.npmrc` directly, I set an environment variable in the profile: + +```sh +export NPM_CONFIG_USERCONFIG=$HOME/._npmrc +``` + +The variable is unset in a script in [Guix.org]({{< relref "Guix" >}}). + +Set PATH & MANPATH + +```sh +NPM_PACKAGES="${HOME}/.npm-packages" + +export PATH="$PATH:$NPM_PACKAGES/bin" +export MANPATH="${MANPATH-$(manpath)}:$NPM_PACKAGES/share/man" +``` + + +### XResources {#xresources} + +| Guix dependency | +|-----------------| +| xrdb | + +```sh +if [ -z "$IS_ANDROID" ]; then + xrdb ~/.Xresources +fi +``` + + +### OFF (OFF) Package manager paths {#off--package-manager-paths} + +Turned off for now, because probably it won't be necessary in Guix. + +LaTeX + +```sh +if [ -d "/usr/local/texlive/2020" ]; then + export MANPATH="/usr/local/texlive/2020/texmf-dist/doc/man:$MANPATH" + export INFOPATH="/usr/local/texlive/2020/texmf-dist/doc/info:$INFOPATH" + export PATH="/usr/local/texlive/2020/bin/x86_64-linux:$PATH" +fi +``` + +Cargo (Rust) + +```sh +if [ -d "$HOME/.cargo" ] ; then + export PATH="$HOME/.cargo/bin:$PATH" +fi +``` + +RVM (Ruby) + +```sh +if [ -d "$HOME/.rvm" ] ; then + export PATH="$PATH:$HOME/.rvm/bin" +fi +# if [ -d "$HOME/.gem" ]; then +# export PATH="$HOME/.gem/ruby/2.7.0/bin:$PATH" +# fi +``` + +Go + +```sh +if [ -d "$HOME/go" ] ; then + export PATH="$HOME/go/bin:$PATH" +fi +``` + +ghcup (Haskell) + +```sh +[ -f "/home/pavel/.ghcup/env" ] && source "/home/pavel/.ghcup/env" # ghcup-env +``` + +Perl + +```sh +if [ -d "$HOME/perl5" ] ; then + PATH="/home/pavel/perl5/bin${PATH:+:${PATH}}" + PERL5LIB="/home/pavel/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB; + PERL_LOCAL_LIB_ROOT="/home/pavel/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT; + PERL_MB_OPT="--install_base \"/home/pavel/perl5\""; export PERL_MB_OPT; + PERL_MM_OPT="INSTALL_BASE=/home/pavel/perl5"; export PERL_MM_OPT; +fi +``` + + +## Bash {#bash} + + +### `.bash_profile` {#dot-bash-profile} + +```bash +[[ -f ~/.profile ]] && . ~/.profile + +[[ -f ~/.bashrc ]] && . ~/.bashrc +``` + + +### `.bashrc` {#dot-bashrc} + +My `.bashrc`, which has pieces from the default ones in Guix & Manjaro, as well some mine settings. + + +#### Startup & environment {#startup-and-environment} + +Export 'SHELL' to child processes. Programs such as 'screen' honor it and otherwise use /bin/sh. + +```bash +export SHELL +``` + +We are being invoked from a non-interactive shell. If this is an SSH session (as in "ssh host command"), source /etc/profile so we get PATH and other essential variables. + +```bash +if [[ $- != *i* ]] +then + [[ -n "$SSH_CLIENT" && -f "/etc/bashrc" ]] && source /etc/profile + return +fi +``` + +Source the system-wide file + +```bash +if [[ -f "/etc/bashrc" ]]; then + source /etc/bashrc +fi +``` + +| Guix dependency | +|-----------------| +| xhost | + +Allow other users to access X server. Necessary for stuff like aw-watcher-window. + +```bash +xhost +local:root > /dev/null 2>&1 +``` + +Set manpager to bat + +```bash +export MANPAGER="sh -c 'sed -e s/.\\\\x08//g | bat -l man -p'" +``` + + +#### Launch fish {#launch-fish} + +Launch fish shell unless bash itself is launched from fish. + +```bash +use_fish=true + +if [[ $(ps --no-header --pid=$PPID --format=cmd) != "fish" && ${use_fish} && $(command -v fish) ]] +then + exec fish +fi +``` + +The rest of `.bashrc` is not executed if fish was launched. + + +#### Colors {#colors} + +Setting for colors, packed in the default `.bashrc` in Manjaro + +```bash +use_color=true + +# Set colorful PS1 only on colorful terminals. +# dircolors --print-database uses its own built-in database +# instead of using /etc/DIR_COLORS. Try to use the external file +# first to take advantage of user additions. Use internal bash +# globbing instead of external grep binary. +safe_term=${TERM//[^[:alnum:]]/?} # sanitize TERM +match_lhs="" +[[ -f ~/.dir_colors ]] && match_lhs="${match_lhs}$(<~/.dir_colors)" +[[ -f /etc/DIR_COLORS ]] && match_lhs="${match_lhs}$(/dev/null \ + && match_lhs=$(dircolors --print-database) +[[ $'\n'${match_lhs} == *$'\n'"TERM "${safe_term}* ]] && use_color=true + +if ${use_color} ; then + # Enable colors for ls, etc. Prefer ~/.dir_colors #64489 + if type -P dircolors >/dev/null ; then + if [[ -f ~/.dir_colors ]] ; then + eval $(dircolors -b ~/.dir_colors) + elif [[ -f /etc/DIR_COLORS ]] ; then + eval $(dircolors -b /etc/DIR_COLORS) + fi + fi + + if [[ ${EUID} == 0 ]] ; then + PS1='\[\033[01;31m\][\h\[\033[01;36m\] \W\[\033[01;31m\]]\$\[\033[00m\] ' + else + PS1='\[\033[01;32m\][\u@\h\[\033[01;37m\] \W\[\033[01;32m\]]\$\[\033[00m\] ' + fi + + alias ls='ls --color=auto' + alias grep='grep --colour=auto' + alias egrep='egrep --colour=auto' + alias fgrep='fgrep --colour=auto' +else + if [[ ${EUID} == 0 ]] ; then + # show root@ when we don't have colors + PS1='\u@\h \W \$ ' + else + PS1='\u@\h \w \$ ' + fi +fi + +unset use_color safe_term match_lhs sh +``` + + +#### Settings {#settings} + +Some general bash settings. + +References: + +- [shopt list](https://www.gnu.org/software/bash/manual/html%5Fnode/The-Shopt-Builtin.html) + + + +```bash +complete -cf sudo # Sudo autocompletion + +shopt -s checkwinsize # Check windows size after each command +shopt -s expand_aliases # Aliases +shopt -s autocd # Cd to directory just by typing its name (without cd) +``` + +History control + +```bash +shopt -s histappend +export HISTCONTROL=ignoredups:erasedups +HISTSIZE= +HISTFILESIZE= +``` + +Autocompletions + +```bash +[ -r /usr/share/bash-completion/bash_completion ] && . /usr/share/bash-completion/bash_completion +if [ -d "/usr/share/fzf" ]; then + source /usr/share/fzf/completion.bash + source /usr/share/fzf/key-bindings.bash +fi +``` + + +#### Aliases {#aliases} + +```bash +alias v="vim" +alias gg="lazygit" +alias ls="exa --icons" +alias ll="exa -lah --icons" +alias q="exit" +alias c="clear" +alias ci="init_conda" +alias ca="conda activate" +alias cii="export INIT_CONDA=true && init_conda" +``` + +```bash +if [[ ! -z "$SIMPLE" ]]; then + unalias ls + alias ll="ls -lah" +fi +``` + + +#### Anaconda {#anaconda} + +> managed by 'conda init' !!! + +Yeah, tell this to yourself + +```bash +init_conda () { + __conda_setup="$('/home/pavel/.guix-extra-profiles/dev/dev/bin/conda' 'shell.bash' 'hook' 2> /dev/null)" + if [ $? -eq 0 ]; then + eval "$__conda_setup" + else + if [ -f "/home/pavel/.guix-extra-profiles/dev/dev/etc/profile.d/conda.sh" ]; then + . "/home/pavel/.guix-extra-profiles/dev/dev/etc/profile.d/conda.sh" + else + # export PATH="/home/pavel/Programs/miniconda3/bin:$PATH" + echo "what" + fi + fi + unset __conda_setup +} + +if [[ ! -z "$INIT_CONDA" ]]; then + init_conda +fi +``` + + +#### Starship prompt {#starship-prompt} + +```bash +if [[ -z "$SIMPLE" ]]; then + eval "$(starship init bash)" +fi +``` + + +## Fish {#fish} + +| Guix dependency | Description | +|-----------------|------------------------------------------| +| fish | An alternative non POSIX-compliant shell | + +[Fish shell](https://fishshell.com/) is a non-POSIX-compliant shell, which offers some fancy UI & UX features. + +Launch starship + +```fish +starship init fish | source +``` + +Enable vi keybindings & aliases. The alias syntax is the same as in bash, so it's just a noweb reference to `.bashrc`. + +```fish +fish_vi_key_bindings + +<> +``` + +| Guix dependency | +|-----------------| +| dt-colorscripts | + +Launch a random [DT's colorscript](https://gitlab.com/dwt1/shell-color-scripts) unless ran inside tmux or Emacs. + +```fish +if ! test -n "$TMUX"; and ! test -n "$IS_EMACS"; + colorscript random +end +``` + +Suppress fish greeting + +```fish +set fish_greeting +``` + + +### Anaconda {#anaconda} + +First, a function to initialize anaconda. + +```fish +function init_conda + eval /home/pavel/.guix-extra-profiles/dev/dev/bin/conda "shell.fish" "hook" $argv | source +end + +if test -n "$INIT_CONDA"; + init_conda +end +``` + +Then, check if launched from Emacs with environment activated. + +```fish +if test -n "$EMACS_CONDA_ENV"; + conda activate $EMACS_CONDA_ENV +end +``` + + +### Colors {#colors} + +Fish seems to have hardcoded colorcodes in some color settings. I set these to base16 colors so they would match Xresources. + +```fish +set fish_color_command cyan +set fish_color_comment green +set fish_color_end white +set fish_color_error red +set fish_color_escape yellow +set fish_color_operator yellow +set fish_color_param magenta +set fish_color_quote brwhite +set fish_color_redirection yellow +``` + + +### Keybindings {#keybindings} + +```fish +bind -M insert \el forward-char +bind -M insert \eh backward-char +bind -M insert \ew forward-word +bind -M insert \eb backward-word +``` + + +## Nushell {#nushell} + +| Guix dependency | +|-----------------| +| nushell-bin | + +A structured shell. I don't use it as of now, but perhaps one day. + +Set starship prompt + +```toml +startup = [ + <>, + "mkdir ~/.cache/starship", + "starship init nu | save ~/.cache/starship/init.nu", + "source ~/.cache/starship/init.nu", +] +prompt = "starship_prompt" +``` + +Skip welcome message + +```toml +skip_welcome_message = true +``` + +Set table mode + +```toml +table_mode = "rounded" +``` + +Aliases + +```toml +"alias ll = ls -l", +"alias c = clear", +"alias q = exit" +``` + +Colors + +```toml +[color_config] +primitive_filesize="ub" +primitive_boolean="yu" +primitive_duration="g" +primitive_path="y" +primitive_date="r" +primitive_int="c" +primitive_decimal="c" +``` + + +## Starship prompt {#starship-prompt} + +| Guix dependency | Description | +|-----------------|---------------------| +| rust-starship | my prompt of choice | + +[Starship](https://starship.rs/) is a nice cross-shell prompt, written in Rust. + +References: + +- [Startship config guide](https://starship.rs/config/) + + + +```toml +[character] +success_symbol = "[➤ ](bold green)" +error_symbol = "[ ](bold red)" +vicmd_symbol = "[ᐊ ](bold green)" + +[aws] +symbol = " " + +# [battery] +# full_symbol = "" +# charging_symbol = "" +# discharging_symbol = "" + +[conda] +symbol = " " + +[cmd_duration] +min_time = 500 +format = " [$duration]($style) " + +[docker_context] +symbol = " " + +[elixir] +symbol = " " + +[elm] +symbol = " " + +[git_branch] +symbol = " " +truncation_length = 20 + +[golang] +symbol = " " + +# [haskell] +# symbol = " " + +[hg_branch] +symbol = " " + +[java] +symbol = " " + +[julia] +symbol = " " + +[memory_usage] +symbol = " " + +[nim] +symbol = " " + +[nix_shell] +symbol = " " + +[nodejs] +symbol = " " + +[package] +symbol = " " +disabled = true + +[php] +symbol = " " + +[python] +symbol = " " + +[ruby] +symbol = " " + +[rust] +symbol = " " +``` + + +## Tmux {#tmux} + +| Guix dependency | +|-----------------| +| tmux | +| python-tmuxp | + +[tmux](https://github.com/tmux/tmux) is my terminal multiplexer of choice. + +It provides pretty sane defaults, so the config is not too large. I rebind the prefix to `C-a` though. + + +### Term settings {#term-settings} + +I have no idea how and why these two work. + +```vim +set -g default-terminal "screen-256color" +set -ga terminal-overrides ",*256col*:Tc" +``` + +History limit. + +```vim +set -g history-limit 20000 +``` + + +### Keybindings {#keybindings} + +Enable vi keys and mouse. + +```vim +set-window-option -g mode-keys vi +set-option -g xterm-keys on +set-option -g mouse on +set -sg escape-time 10 +``` + +Change prefix from `C-b` to `C-a`. + +```vim +unbind C-b +set -g prefix C-a +bind C-a send-prefix +``` + +Vi-like keybindings to manage panes & windows. + +```vim +bind h select-pane -L +bind j select-pane -D +bind k select-pane -U +bind l select-pane -R + +bind s split-window +bind v split-window -h + +bind-key n new-window +bind-key t next-window +bind-key T previous-window +``` + +Reload the config. + +```vim +bind r source-file ~/.tmux.conf +``` + + +### Copy to clipboard {#copy-to-clipboard} + +| Guix dependency | +|-----------------| +| xclip | + +Make tmux copying copy to clipboard as well + +```vim +bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "xclip -selection clipboard -i" +bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "xclip -selection clipboard -i" +``` + + +### UI {#ui} + +I generated the following with [tmuxline.vim](https://github.com/edkolev/tmuxline.vim) plugin and palenight theme for [vim-airline](https://github.com/vim-airline/vim-airline) + +```vim +# This tmux statusbar config was created by tmuxline.vim +# on Wed, 22 Jan 2020 + +set -g status-justify "centre" +set -g status "on" +set -g status-left-style "none" +set -g message-command-style "fg=#bfc7d5,bg=#474b59" +set -g status-right-style "none" +set -g pane-active-border-style "fg=#939ede" +set -g status-style "none,bg=#333747" +set -g message-style "fg=#bfc7d5,bg=#474b59" +set -g pane-border-style "fg=#474b59" +set -g status-right-length "100" +set -g status-left-length "100" +setw -g window-status-activity-style "none,fg=#939ede,bg=#333747" +setw -g window-status-separator "" +setw -g window-status-style "none,fg=#bfc7d5,bg=#333747" +set -g status-left "#[fg=#292D3E,bg=#939ede] #S #[fg=#939ede,bg=#474b59,nobold,nounderscore,noitalics]#[fg=#bfc7d5,bg=#474b59] #W #[fg=#474b59,bg=#333747,nobold,nounderscore,noitalics]" +set -g status-right "#[fg=#333747,bg=#333747,nobold,nounderscore,noitalics]#[fg=#bfc7d5,bg=#333747] %-H:%M #[fg=#474b59,bg=#333747,nobold,nounderscore,noitalics]#[fg=#bfc7d5,bg=#474b59] %a, %b %d #[fg=#939ede,bg=#474b59,nobold,nounderscore,noitalics]#[fg=#292D3E,bg=#939ede] #H " +setw -g window-status-format "#[fg=#333747,bg=#333747,nobold,nounderscore,noitalics]#[default] #I #W #[align=left] #[fg=#333747,bg=#333747,nobold,nounderscore,noitalics]" +setw -g window-status-current-format "#[fg=#333747,bg=#474b59,nobold,nounderscore,noitalics]#[fg=#bfc7d5,bg=#474b59] #I #W #[fg=#474b59,bg=#333747,nobold,nounderscore,noitalics]" +``` + +Source the line config: + +```vim +source ~/.tmux.line.conf +``` + + +## Alacritty {#alacritty} + +| Guix dependency | +|-----------------| +| alacritty | + +[Alacritty](https://github.com/alacritty/alacritty) is a GPU-accelerated terminal emulator. I haven't found it to be an inch faster than st, but configuration the in yml format is way more convinient than patches. + +Once again, we have an application which doesn't support reading Xresources, so here goes noweb. + + +```bash +xrdb -query all | grep "$color:" | cut -f 2 +``` + +```emacs-lisp +(setq-local org-confirm-babel-evaluate nil) +``` + +References: + +- [default config](https://github.com/alacritty/alacritty/blob/master/alacritty.yml) + + + +```yaml +decorations: none + +font: + normal: + family: JetBrainsMono Nerd Font + style: Regular + + size: 10 + +env: + TERM: xterm-256color + +colors: + primary: + background: '<>' + foreground: '<>' + normal: + black: '<>' + red: '<>' + green: '<>' + yellow: '<>' + blue: '<>' + magenta: '<>' + cyan: '<>' + white: '<>' + bright: + Black: '<>' + Red: '<>' + Green: '<>' + Yellow: '<>' + Blue: '<>' + Magenta: '<>' + Cyan: '<>' + White: '<>' + +background_opacity: 0.80 + +window: + padding: + x: 0 + y: 0 + dynamic_padding: true + +key_bindings: + - { key: Paste, action: Paste } + - { key: Copy, action: Copy } + - { key: L, mods: Control, action: ClearLogNotice } + - { key: L, mods: Control, mode: ~Vi|~Search, chars: "\x0c" } + - { key: PageUp, mods: Shift, mode: ~Alt, action: ScrollPageUp, } + - { key: PageDown, mods: Shift, mode: ~Alt, action: ScrollPageDown } + - { key: Home, mods: Shift, mode: ~Alt, action: ScrollToTop, } + - { key: End, mods: Shift, mode: ~Alt, action: ScrollToBottom } + + # Turn off vi mode + - { key: Space, mods: Shift|Control, mode: ~Search, action: ReceiveChar } + + # (Windows, Linux, and BSD only) + - { key: V, mods: Control|Shift, mode: ~Vi, action: Paste } + - { key: C, mods: Control|Shift, action: Copy } + - { key: F, mods: Control|Shift, mode: ~Search, action: ReceiveChar } + - { key: B, mods: Control|Shift, mode: ~Search, action: ReceiveChar } + - { key: Insert, mods: Shift, action: PasteSelection } + - { key: Key0, mods: Control, action: ResetFontSize } + - { key: Equals, mods: Control, action: IncreaseFontSize } + - { key: Plus, mods: Control, action: IncreaseFontSize } + - { key: NumpadAdd, mods: Control, action: IncreaseFontSize } + - { key: Minus, mods: Control, action: DecreaseFontSize } + - { key: NumpadSubtract, mods: Control, action: DecreaseFontSize } +``` + + +## Various console applications {#various-console-applications} + +| Guix dependency | Description | +|-----------------|---------------------------------------------| +| ncurses | Provides stuff like `clear` | +| exa | `ls` replacement, written in Rust | +| bat | `cat` clone with syntax highlighting | +| htop | Interactive process viewer | +| nethogs | A tool to group processed by used bandwidth | +| osync | rsync wrapper | +| neofetch | Fetch system info | +| fzf | fuzzy finder | +| p7zip | archiver | +| password-store | CLI password manager | +| unzip | | +| jmtpfs | A tool to mount MTP devices (e.g. Android) | +| tokei | Count lines of code | + + +## Misc scripts {#misc-scripts} + + +### `nt` - exec command with a finished notification {#nt-exec-command-with-a-finished-notification} + +Usage: + +```text +nt +``` + +```sh +command="$@" +if [ ! -z "$command" ]; then + start_time="$(date -u +%s)" + $command + end_time="$(date -u +%s)" + elapsed="$(($end_time-$start_time))" + notify-send "Terminal" "Command\n$command\nexecuted in $elapsed seconds" +else + notify-send "Terminal" "Command execution complete" +fi +``` + + +### `autocommmit` {#autocommmit} + +A script to autocommit files in a repository. I use it to sync my org directory and password store. I guess it's not how git is intended to be used, but it works for me. + +Usage: + +```text +autocommit [-F] +``` + +Environment: + +| Variable | Description | Default value | +|---------------|-----------------|---------------| +| `TIMEOUT_MIN` | Default timeout | 60 | + +Here's more or less what the script is doing: + +- If there is a merge conflict, notify +- If there are changed files in the last `TIMEOUT_MIN` minutes, commit +- Fetch +- If there are were changes in the last `TTMEOUT_MIN`, merge (usually the merge has to be fast-forward) +- If fetch was successful & merge was successful or delayed because of changes in the last `TIMEOUT_MIN`, push +- Send a notification about the events above +- Send a separate notification if there is a merge conflict + + + +```bash +TIMEOUT_MIN=${TIMEOUT_MIN:-60} + +export DISPLAY=:0 +cd "$1" + +TIMESTAMP=$(date +%s) +LAST_COMMIT_TIMESTAMP=$(git log -1 --format="%at" | xargs -I{} date -d @{} +%s) +RECENTLY_CHANGED_NUM=$(find . -not -path '*/\.*' -mmin -$TIMEOUT_MIN | wc -l) +CHANGED_NUM=$(git status --porcelain | wc -l) +COMMITED="No" +PUSHED="No" +FETCHED="No" +MERGED="No" + +if [[ $(git ls-files -u | wc -l) -gt 0 ]]; then + notify-send -u critical "Autocommit $(pwd)" "Merge conflict!" + exit +fi + +if [[ ($RECENTLY_CHANGED_NUM -eq 0 || $2 = "-F") && $CHANGED_NUM -gt 0 ]]; then + read -r -d '' MESSAGE << EOM +Autocommit $(date -Iminutes) + +Hostname: $(hostname) +EOM + git add -A + git commit -m "$MESSAGE" + COMMITED="Yes" +fi + +NEED_TO_PUSH=$(git log origin/master..HEAD | wc -l) + +git fetch && FETCHED="Yes" || FETCHED="No" +if [[ $RECENTLY_CHANGED_NUM -gt 0 && $2 != '-F' ]]; then + MERGED="Waiting" +fi + +if [[ ($RECENTLY_CHANGED_NUM -eq 0 || $2 = "-F") && $FETCHED = "Yes" ]]; then + MERGE_OUT=$(git merge origin/master) && MERGED="Yes" || MERGED="No" +fi + +if [[ $NEED_TO_PUSH -gt 0 && ($MERGED = "Yes" || $MERGED = "Waiting") ]]; then + git push origin && PUSHED="Yes" || PUSHED="No" +fi + +if [[ $PUSHED = "Yes" || $COMMITED = "Yes" || ($MERGED = "Yes" && $MERGE_OUT != "Already up to date.")]]; then + read -r -d '' NOTIFICATION << EOM +Commited: $COMMITED +Fetched: $FETCHED +Merged: $MERGED +Pushed: $PUSHED +EOM + notify-send "Autocommit $(pwd)" "$NOTIFICATION" +fi + +if [[ $(git ls-files -u | wc -l) -gt 0 ]]; then + notify-send -u critical "Autocommit $(pwd)" "Merge conflict!" +fi +``` + +`mcron` job: + +```scheme +(job "0 * * * *" "autocommit ~/Documents/org-mode") +(job "0,15,30,45 * * * *" "autocommit ~/.password-store") +``` + + +## Guix settings {#guix-settings} + + +```emacs-lisp +(my/format-guix-dependencies) +``` + +```scheme +(specifications->manifest + '( + <>)) +``` + + +## Android notes {#android-notes} + +SSH instructions: + +Don't forget to install the following termux packages: + +| Termux package | +|----------------| +| vim | +| tmux | +| starship | +| fish | +| exa | +| bat | +| git | + +Also: + +- cleanup `$PREFIX/etc/motd` to remove hello message. +- copy the required font at `$HOME/.termux/font.ttf` and run `termux-reload-settings`. + + +### Installation of [DT's colorscripts](https://gitlab.com/dwt1/shell-color-scripts): {#installation-of-dt-s-colorscripts} + +```bash +git clone https://gitlab.com/dwt1/shell-color-scripts.git +cd shell-color-scripts +``` + +Apply a patch: + +```diff +--- a/colorscript.sh ++++ b/colorscript.sh +@@ -2,7 +2,7 @@ + + # Simple CLI for shell-color-scripts + +-DIR_COLORSCRIPTS="/opt/shell-color-scripts/colorscripts" ++DIR_COLORSCRIPTS="$PREFIX/opt/shell-color-scripts/colorscripts" + LS_CMD="$(command -v ls)" + fmt_help=" %-20s\t%-54s\n" + list_colorscripts="$($LS_CMD "${DIR_COLORSCRIPTS}" | cut -d ' ' -f 1 | nl)" +``` + +```bash +sudo mkdir -p $PREFIX/opt/shell-color-scripts/colorscripts || return 1 +sudo cp -rf colorscripts/* $PREFIX/opt/shell-color-scripts/colorscripts +sudo cp colorscript.sh $PREFIX/bin/colorscript +``` \ No newline at end of file diff --git a/content/configs/Console.md~ b/content/configs/Console.md~ new file mode 100644 index 0000000..2915e56 --- /dev/null +++ b/content/configs/Console.md~ @@ -0,0 +1,1099 @@ ++++ +title = "Console" +author = ["Pavel"] +draft = false ++++ + +\#+TOC headlines 6 + + +## `.profile` {#dot-profile} + + +### Environment {#environment} + +```sh +# export EDITOR=/usr/bin/vim +# export BROWSER=/usr/bin/firefox +export QT_QPA_PLATFORMTHEME="qt5ct" +export QT_AUTO_SCREEN_SCALE_FACTOR=0 +# export GTK2_RC_FILES="$HOME/.gtkrc-2.0" +``` + + +### My paths {#my-paths} + +My script folders + +```sh +if [ -d "$HOME/bin" ] ; then + export PATH="$HOME/bin:$PATH" + export PATH="$HOME/bin/scripts:$PATH" +fi +``` + + +### Guix settings {#guix-settings} + +Enable extra profiles + +```sh +if [ -z "$IS_ANDROID" ]; then + GUIX_EXTRA_PROFILES=$HOME/.guix-extra-profiles + for i in $GUIX_EXTRA_PROFILES/*; do + profile=$i/$(basename "$i") + if [ -f "$profile"/etc/profile ]; then + GUIX_PROFILE="$profile" + . "$GUIX_PROFILE"/etc/profile + fi + export XDG_DATA_DIRS="$XDG_DATA_DIRS:$profile/share" + unset profile + done +fi +``` + +Set Jupyter config PATH. It defaults to readonly directory somewhere in Guix profile. + +```sh +export JUPYTER_CONFIG_DIR=$HOME/.config/jupyter +``` + +Set a folder for my packages. + +```sh +export GUIX_PACKAGE_PATH=~/guix-packages +``` + + +### Other package managers {#other-package-managers} + +Using other package managers with Guix requires some extra work. + +Cask + +```sh +if [ -d "$HOME/.cask" ]; then + export PATH="/home/pavel/.cask/bin:$PATH" +fi +``` + +Make flatpak apps visible to launchers: + +```sh +if [ -d "$HOME/.local/share/flatpak" ]; then + export XDG_DATA_DIRS="$XDG_DATA_DIRS:$HOME/.local/share/flatpak/exports/share" +fi +``` + +Enable Nix + +```sh +if [ -f /run/current-system/profile/etc/profile.d/nix.sh ]; then + . /run/current-system/profile/etc/profile.d/nix.sh +fi +``` + +Use Guix fontconfig. Necessary for nix apps + +```sh +if [ -d "$HOME/.guix-extra-profiles/desktop" ]; then + export FONTCONFIG_PATH="$HOME/.guix-extra-profiles/desktop/desktop/etc/fonts" +fi +``` + +Make nix apps visible to launchers: + +```sh +if [ -d "$HOME/.nix-profile" ]; then + export XDG_DATA_DIRS="$XDG_DATA_DIRS:$HOME/.nix-profile/share/applications" +fi +``` + + +#### npm {#npm} + +npm is especially cumbersome, for instance because by default it tries to install packages to `/gnu/store/`. + +In principle, one can set a prefix like this: + +```conf +prefix=/home/pavel/.npm-packages +``` + +But I also want to use node from conda occasionally, where prefix is already set correctly. So instead of tangling the above to the `~/.npmrc` directly, I set an environment variable in the profile: + +```sh +export NPM_CONFIG_USERCONFIG=$HOME/._npmrc +``` + +The variable is unset in a script in [Guix.org]({{< relref "Guix" >}}). + +Set PATH & MANPATH + +```sh +NPM_PACKAGES="${HOME}/.npm-packages" + +export PATH="$PATH:$NPM_PACKAGES/bin" +export MANPATH="${MANPATH-$(manpath)}:$NPM_PACKAGES/share/man" +``` + + +### XResources {#xresources} + +| Guix dependency | +|-----------------| +| xrdb | + +```sh +if [ -z "$IS_ANDROID" ]; then + xrdb ~/.Xresources +fi +``` + + +### OFF (OFF) Package manager paths {#off--package-manager-paths} + +Turned off for now, because probably it won't be necessary in Guix. + +LaTeX + +```sh +if [ -d "/usr/local/texlive/2020" ]; then + export MANPATH="/usr/local/texlive/2020/texmf-dist/doc/man:$MANPATH" + export INFOPATH="/usr/local/texlive/2020/texmf-dist/doc/info:$INFOPATH" + export PATH="/usr/local/texlive/2020/bin/x86_64-linux:$PATH" +fi +``` + +Cargo (Rust) + +```sh +if [ -d "$HOME/.cargo" ] ; then + export PATH="$HOME/.cargo/bin:$PATH" +fi +``` + +RVM (Ruby) + +```sh +if [ -d "$HOME/.rvm" ] ; then + export PATH="$PATH:$HOME/.rvm/bin" +fi +# if [ -d "$HOME/.gem" ]; then +# export PATH="$HOME/.gem/ruby/2.7.0/bin:$PATH" +# fi +``` + +Go + +```sh +if [ -d "$HOME/go" ] ; then + export PATH="$HOME/go/bin:$PATH" +fi +``` + +ghcup (Haskell) + +```sh +[ -f "/home/pavel/.ghcup/env" ] && source "/home/pavel/.ghcup/env" # ghcup-env +``` + +Perl + +```sh +if [ -d "$HOME/perl5" ] ; then + PATH="/home/pavel/perl5/bin${PATH:+:${PATH}}" + PERL5LIB="/home/pavel/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB; + PERL_LOCAL_LIB_ROOT="/home/pavel/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT; + PERL_MB_OPT="--install_base \"/home/pavel/perl5\""; export PERL_MB_OPT; + PERL_MM_OPT="INSTALL_BASE=/home/pavel/perl5"; export PERL_MM_OPT; +fi +``` + + +## Bash {#bash} + + +### `.bash_profile` {#dot-bash-profile} + +```bash +[[ -f ~/.profile ]] && . ~/.profile + +[[ -f ~/.bashrc ]] && . ~/.bashrc +``` + + +### `.bashrc` {#dot-bashrc} + +My `.bashrc`, which has pieces from the default ones in Guix & Manjaro, as well some mine settings. + + +#### Startup & environment {#startup-and-environment} + +Export 'SHELL' to child processes. Programs such as 'screen' honor it and otherwise use /bin/sh. + +```bash +export SHELL +``` + +We are being invoked from a non-interactive shell. If this is an SSH session (as in "ssh host command"), source /etc/profile so we get PATH and other essential variables. + +```bash +if [[ $- != *i* ]] +then + [[ -n "$SSH_CLIENT" && -f "/etc/bashrc" ]] && source /etc/profile + return +fi +``` + +Source the system-wide file + +```bash +if [[ -f "/etc/bashrc" ]]; then + source /etc/bashrc +fi +``` + +| Guix dependency | +|-----------------| +| xhost | + +Allow other users to access X server. Necessary for stuff like aw-watcher-window. + +```bash +xhost +local:root > /dev/null 2>&1 +``` + +Set manpager to bat + +```bash +export MANPAGER="sh -c 'sed -e s/.\\\\x08//g | bat -l man -p'" +``` + + +#### Launch fish {#launch-fish} + +Launch fish shell unless bash itself is launched from fish. + +```bash +use_fish=true + +if [[ $(ps --no-header --pid=$PPID --format=cmd) != "fish" && ${use_fish} && $(command -v fish) ]] +then + exec fish +fi +``` + +The rest of `.bashrc` is not executed if fish was launched. + + +#### Colors {#colors} + +Setting for colors, packed in the default `.bashrc` in Manjaro + +```bash +use_color=true + +# Set colorful PS1 only on colorful terminals. +# dircolors --print-database uses its own built-in database +# instead of using /etc/DIR_COLORS. Try to use the external file +# first to take advantage of user additions. Use internal bash +# globbing instead of external grep binary. +safe_term=${TERM//[^[:alnum:]]/?} # sanitize TERM +match_lhs="" +[[ -f ~/.dir_colors ]] && match_lhs="${match_lhs}$(<~/.dir_colors)" +[[ -f /etc/DIR_COLORS ]] && match_lhs="${match_lhs}$(/dev/null \ + && match_lhs=$(dircolors --print-database) +[[ $'\n'${match_lhs} == *$'\n'"TERM "${safe_term}* ]] && use_color=true + +if ${use_color} ; then + # Enable colors for ls, etc. Prefer ~/.dir_colors #64489 + if type -P dircolors >/dev/null ; then + if [[ -f ~/.dir_colors ]] ; then + eval $(dircolors -b ~/.dir_colors) + elif [[ -f /etc/DIR_COLORS ]] ; then + eval $(dircolors -b /etc/DIR_COLORS) + fi + fi + + if [[ ${EUID} == 0 ]] ; then + PS1='\[\033[01;31m\][\h\[\033[01;36m\] \W\[\033[01;31m\]]\$\[\033[00m\] ' + else + PS1='\[\033[01;32m\][\u@\h\[\033[01;37m\] \W\[\033[01;32m\]]\$\[\033[00m\] ' + fi + + alias ls='ls --color=auto' + alias grep='grep --colour=auto' + alias egrep='egrep --colour=auto' + alias fgrep='fgrep --colour=auto' +else + if [[ ${EUID} == 0 ]] ; then + # show root@ when we don't have colors + PS1='\u@\h \W \$ ' + else + PS1='\u@\h \w \$ ' + fi +fi + +unset use_color safe_term match_lhs sh +``` + + +#### Settings {#settings} + +Some general bash settings. + +References: + +- [shopt list](https://www.gnu.org/software/bash/manual/html%5Fnode/The-Shopt-Builtin.html) + + + +```bash +complete -cf sudo # Sudo autocompletion + +shopt -s checkwinsize # Check windows size after each command +shopt -s expand_aliases # Aliases +shopt -s autocd # Cd to directory just by typing its name (without cd) +``` + +History control + +```bash +shopt -s histappend +export HISTCONTROL=ignoredups:erasedups +HISTSIZE= +HISTFILESIZE= +``` + +Autocompletions + +```bash +[ -r /usr/share/bash-completion/bash_completion ] && . /usr/share/bash-completion/bash_completion +if [ -d "/usr/share/fzf" ]; then + source /usr/share/fzf/completion.bash + source /usr/share/fzf/key-bindings.bash +fi +``` + + +#### Aliases {#aliases} + +```bash +alias v="vim" +alias gg="lazygit" +alias ls="exa --icons" +alias ll="exa -lah --icons" +alias q="exit" +alias c="clear" +alias ci="init_conda" +alias ca="conda activate" +alias cii="export INIT_CONDA=true && init_conda" +``` + +```bash +if [[ ! -z "$SIMPLE" ]]; then + unalias ls + alias ll="ls -lah" +fi +``` + + +#### Anaconda {#anaconda} + +> managed by 'conda init' !!! + +Yeah, tell this to yourself + +```bash +init_conda () { + __conda_setup="$('/home/pavel/.guix-extra-profiles/dev/dev/bin/conda' 'shell.bash' 'hook' 2> /dev/null)" + if [ $? -eq 0 ]; then + eval "$__conda_setup" + else + if [ -f "/home/pavel/.guix-extra-profiles/dev/dev/etc/profile.d/conda.sh" ]; then + . "/home/pavel/.guix-extra-profiles/dev/dev/etc/profile.d/conda.sh" + else + # export PATH="/home/pavel/Programs/miniconda3/bin:$PATH" + echo "what" + fi + fi + unset __conda_setup +} + +if [[ ! -z "$INIT_CONDA" ]]; then + init_conda +fi +``` + + +#### Starship prompt {#starship-prompt} + +```bash +if [[ -z "$SIMPLE" ]]; then + eval "$(starship init bash)" +fi +``` + + +## Fish {#fish} + +| Guix dependency | Description | +|-----------------|------------------------------------------| +| fish | An alternative non POSIX-compliant shell | + +[Fish shell](https://fishshell.com/) is a non-POSIX-compliant shell, which offers some fancy UI & UX features. + +Launch starship + +```fish +starship init fish | source +``` + +Enable vi keybindings & aliases. The alias syntax is the same as in bash, so it's just a noweb reference to `.bashrc`. + +```fish +fish_vi_key_bindings + +<> +``` + +| Guix dependency | +|-----------------| +| dt-colorscripts | + +Launch a random [DT's colorscript](https://gitlab.com/dwt1/shell-color-scripts) unless ran inside tmux or Emacs. + +```fish +if ! test -n "$TMUX"; and ! test -n "$IS_EMACS"; + colorscript random +end +``` + +Suppress fish greeting + +```fish +set fish_greeting +``` + + +### Anaconda {#anaconda} + +First, a function to initialize anaconda. + +```fish +function init_conda + eval /home/pavel/.guix-extra-profiles/dev/dev/bin/conda "shell.fish" "hook" $argv | source +end + +if test -n "$INIT_CONDA"; + init_conda +end +``` + +Then, check if launched from Emacs with environment activated. + +```fish +if test -n "$EMACS_CONDA_ENV"; + conda activate $EMACS_CONDA_ENV +end +``` + + +### Colors {#colors} + +Fish seems to have hardcoded colorcodes in some color settings. I set these to base16 colors so they would match Xresources. + +```fish +set fish_color_command cyan +set fish_color_comment green +set fish_color_end white +set fish_color_error red +set fish_color_escape yellow +set fish_color_operator yellow +set fish_color_param magenta +set fish_color_quote brwhite +set fish_color_redirection yellow +``` + + +### Keybindings {#keybindings} + +```fish +bind -M insert \el forward-char +bind -M insert \eh backward-char +bind -M insert \ew forward-word +bind -M insert \eb backward-word +``` + + +## Nushell {#nushell} + +| Guix dependency | +|-----------------| +| nushell-bin | + +A structured shell. I don't use it as of now, but perhaps one day. + +Set starship prompt + +```toml +startup = [ + <>, + "mkdir ~/.cache/starship", + "starship init nu | save ~/.cache/starship/init.nu", + "source ~/.cache/starship/init.nu", +] +prompt = "starship_prompt" +``` + +Skip welcome message + +```toml +skip_welcome_message = true +``` + +Set table mode + +```toml +table_mode = "rounded" +``` + +Aliases + +```toml +"alias ll = ls -l", +"alias c = clear", +"alias q = exit" +``` + +Colors + +```toml +[color_config] +primitive_filesize="ub" +primitive_boolean="yu" +primitive_duration="g" +primitive_path="y" +primitive_date="r" +primitive_int="c" +primitive_decimal="c" +``` + + +## Starship prompt {#starship-prompt} + +| Guix dependency | Description | +|-----------------|---------------------| +| rust-starship | my prompt of choice | + +[Starship](https://starship.rs/) is a nice cross-shell prompt, written in Rust. + +References: + +- [Startship config guide](https://starship.rs/config/) + + + +```toml +[character] +success_symbol = "[➤ ](bold green)" +error_symbol = "[ ](bold red)" +vicmd_symbol = "[ᐊ ](bold green)" + +[aws] +symbol = " " + +# [battery] +# full_symbol = "" +# charging_symbol = "" +# discharging_symbol = "" + +[conda] +symbol = " " + +[cmd_duration] +min_time = 500 +format = " [$duration]($style) " + +[docker_context] +symbol = " " + +[elixir] +symbol = " " + +[elm] +symbol = " " + +[git_branch] +symbol = " " +truncation_length = 20 + +[golang] +symbol = " " + +# [haskell] +# symbol = " " + +[hg_branch] +symbol = " " + +[java] +symbol = " " + +[julia] +symbol = " " + +[memory_usage] +symbol = " " + +[nim] +symbol = " " + +[nix_shell] +symbol = " " + +[nodejs] +symbol = " " + +[package] +symbol = " " +disabled = true + +[php] +symbol = " " + +[python] +symbol = " " + +[ruby] +symbol = " " + +[rust] +symbol = " " +``` + + +## Tmux {#tmux} + +| Guix dependency | +|-----------------| +| tmux | +| python-tmuxp | + +[tmux](https://github.com/tmux/tmux) is my terminal multiplexer of choice. + +It provides pretty sane defaults, so the config is not too large. I rebind the prefix to `C-a` though. + + +### Term settings {#term-settings} + +I have no idea how and why these two work. + +```vim +set -g default-terminal "screen-256color" +set -ga terminal-overrides ",*256col*:Tc" +``` + +History limit. + +```vim +set -g history-limit 20000 +``` + + +### Keybindings {#keybindings} + +Enable vi keys and mouse. + +```vim +set-window-option -g mode-keys vi +set-option -g xterm-keys on +set-option -g mouse on +set -sg escape-time 10 +``` + +Change prefix from `C-b` to `C-a`. + +```vim +unbind C-b +set -g prefix C-a +bind C-a send-prefix +``` + +Vi-like keybindings to manage panes & windows. + +```vim +bind h select-pane -L +bind j select-pane -D +bind k select-pane -U +bind l select-pane -R + +bind s split-window +bind v split-window -h + +bind-key n new-window +bind-key t next-window +bind-key T previous-window +``` + +Reload the config. + +```vim +bind r source-file ~/.tmux.conf +``` + + +### Copy to clipboard {#copy-to-clipboard} + +| Guix dependency | +|-----------------| +| xclip | + +Make tmux copying copy to clipboard as well + +```vim +bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "xclip -selection clipboard -i" +bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "xclip -selection clipboard -i" +``` + + +### UI {#ui} + +I generated the following with [tmuxline.vim](https://github.com/edkolev/tmuxline.vim) plugin and palenight theme for [vim-airline](https://github.com/vim-airline/vim-airline) + +```vim +# This tmux statusbar config was created by tmuxline.vim +# on Wed, 22 Jan 2020 + +set -g status-justify "centre" +set -g status "on" +set -g status-left-style "none" +set -g message-command-style "fg=#bfc7d5,bg=#474b59" +set -g status-right-style "none" +set -g pane-active-border-style "fg=#939ede" +set -g status-style "none,bg=#333747" +set -g message-style "fg=#bfc7d5,bg=#474b59" +set -g pane-border-style "fg=#474b59" +set -g status-right-length "100" +set -g status-left-length "100" +setw -g window-status-activity-style "none,fg=#939ede,bg=#333747" +setw -g window-status-separator "" +setw -g window-status-style "none,fg=#bfc7d5,bg=#333747" +set -g status-left "#[fg=#292D3E,bg=#939ede] #S #[fg=#939ede,bg=#474b59,nobold,nounderscore,noitalics]#[fg=#bfc7d5,bg=#474b59] #W #[fg=#474b59,bg=#333747,nobold,nounderscore,noitalics]" +set -g status-right "#[fg=#333747,bg=#333747,nobold,nounderscore,noitalics]#[fg=#bfc7d5,bg=#333747] %-H:%M #[fg=#474b59,bg=#333747,nobold,nounderscore,noitalics]#[fg=#bfc7d5,bg=#474b59] %a, %b %d #[fg=#939ede,bg=#474b59,nobold,nounderscore,noitalics]#[fg=#292D3E,bg=#939ede] #H " +setw -g window-status-format "#[fg=#333747,bg=#333747,nobold,nounderscore,noitalics]#[default] #I #W #[align=left] #[fg=#333747,bg=#333747,nobold,nounderscore,noitalics]" +setw -g window-status-current-format "#[fg=#333747,bg=#474b59,nobold,nounderscore,noitalics]#[fg=#bfc7d5,bg=#474b59] #I #W #[fg=#474b59,bg=#333747,nobold,nounderscore,noitalics]" +``` + +Source the line config: + +```vim +source ~/.tmux.line.conf +``` + + +## Alacritty {#alacritty} + +| Guix dependency | +|-----------------| +| alacritty | + +[Alacritty](https://github.com/alacritty/alacritty) is a GPU-accelerated terminal emulator. I haven't found it to be an inch faster than st, but configuration the in yml format is way more convinient than patches. + +Once again, we have an application which doesn't support reading Xresources, so here goes noweb. + + +```bash +xrdb -query all | grep "$color:" | cut -f 2 +``` + +```emacs-lisp +(setq-local org-confirm-babel-evaluate nil) +``` + +References: + +- [default config](https://github.com/alacritty/alacritty/blob/master/alacritty.yml) + + + +```yaml +decorations: none + +font: + normal: + family: JetBrainsMono Nerd Font + style: Regular + + size: 10 + +env: + TERM: xterm-256color + +colors: + primary: + background: '<>' + foreground: '<>' + normal: + black: '<>' + red: '<>' + green: '<>' + yellow: '<>' + blue: '<>' + magenta: '<>' + cyan: '<>' + white: '<>' + bright: + Black: '<>' + Red: '<>' + Green: '<>' + Yellow: '<>' + Blue: '<>' + Magenta: '<>' + Cyan: '<>' + White: '<>' + +background_opacity: 0.80 + +window: + padding: + x: 0 + y: 0 + dynamic_padding: true + +key_bindings: + - { key: Paste, action: Paste } + - { key: Copy, action: Copy } + - { key: L, mods: Control, action: ClearLogNotice } + - { key: L, mods: Control, mode: ~Vi|~Search, chars: "\x0c" } + - { key: PageUp, mods: Shift, mode: ~Alt, action: ScrollPageUp, } + - { key: PageDown, mods: Shift, mode: ~Alt, action: ScrollPageDown } + - { key: Home, mods: Shift, mode: ~Alt, action: ScrollToTop, } + - { key: End, mods: Shift, mode: ~Alt, action: ScrollToBottom } + + # Turn off vi mode + - { key: Space, mods: Shift|Control, mode: ~Search, action: ReceiveChar } + + # (Windows, Linux, and BSD only) + - { key: V, mods: Control|Shift, mode: ~Vi, action: Paste } + - { key: C, mods: Control|Shift, action: Copy } + - { key: F, mods: Control|Shift, mode: ~Search, action: ReceiveChar } + - { key: B, mods: Control|Shift, mode: ~Search, action: ReceiveChar } + - { key: Insert, mods: Shift, action: PasteSelection } + - { key: Key0, mods: Control, action: ResetFontSize } + - { key: Equals, mods: Control, action: IncreaseFontSize } + - { key: Plus, mods: Control, action: IncreaseFontSize } + - { key: NumpadAdd, mods: Control, action: IncreaseFontSize } + - { key: Minus, mods: Control, action: DecreaseFontSize } + - { key: NumpadSubtract, mods: Control, action: DecreaseFontSize } +``` + + +## Various console applications {#various-console-applications} + +| Guix dependency | Description | +|-----------------|---------------------------------------------| +| ncurses | Provides stuff like `clear` | +| exa | `ls` replacement, written in Rust | +| bat | `cat` clone with syntax highlighting | +| htop | Interactive process viewer | +| nethogs | A tool to group processed by used bandwidth | +| osync | rsync wrapper | +| neofetch | Fetch system info | +| fzf | fuzzy finder | +| p7zip | archiver | +| password-store | CLI password manager | +| unzip | | +| jmtpfs | A tool to mount MTP devices (e.g. Android) | +| tokei | Count lines of code | + + +## Misc scripts {#misc-scripts} + + +### `nt` - exec command with a finished notification {#nt-exec-command-with-a-finished-notification} + +Usage: + +```text +nt +``` + +```sh +command="$@" +if [ ! -z "$command" ]; then + start_time="$(date -u +%s)" + $command + end_time="$(date -u +%s)" + elapsed="$(($end_time-$start_time))" + notify-send "Terminal" "Command\n$command\nexecuted in $elapsed seconds" +else + notify-send "Terminal" "Command execution complete" +fi +``` + + +### `autocommmit` {#autocommmit} + +A script to autocommit files in a repository. I use it to sync my org directory and password store. I guess it's not how git is intended to be used, but it works for me. + +Usage: + +```text +autocommit [-F] +``` + +Environment: + +| Variable | Description | Default value | +|---------------|-----------------|---------------| +| `TIMEOUT_MIN` | Default timeout | 60 | + +Here's more or less what the script is doing: + +- If there is a merge conflict, notify +- If there are changed files in the last `TIMEOUT_MIN` minutes, commit +- Fetch +- If there are were changes in the last `TTMEOUT_MIN`, merge (usually the merge has to be fast-forward) +- If fetch was successful & merge was successful or delayed because of changes in the last `TIMEOUT_MIN`, push +- Send a notification about the events above +- Send a separate notification if there is a merge conflict + + + +```bash +TIMEOUT_MIN=${TIMEOUT_MIN:-60} + +export DISPLAY=:0 +cd "$1" + +TIMESTAMP=$(date +%s) +LAST_COMMIT_TIMESTAMP=$(git log -1 --format="%at" | xargs -I{} date -d @{} +%s) +RECENTLY_CHANGED_NUM=$(find . -not -path '*/\.*' -mmin -$TIMEOUT_MIN | wc -l) +CHANGED_NUM=$(git status --porcelain | wc -l) +COMMITED="No" +PUSHED="No" +FETCHED="No" +MERGED="No" + +if [[ $(git ls-files -u | wc -l) -gt 0 ]]; then + notify-send -u critical "Autocommit $(pwd)" "Merge conflict!" + exit +fi + +if [[ ($RECENTLY_CHANGED_NUM -eq 0 || $2 = "-F") && $CHANGED_NUM -gt 0 ]]; then + read -r -d '' MESSAGE << EOM +Autocommit $(date -Iminutes) + +Hostname: $(hostname) +EOM + git add -A + git commit -m "$MESSAGE" + COMMITED="Yes" +fi + +NEED_TO_PUSH=$(git log origin/master..HEAD | wc -l) + +git fetch && FETCHED="Yes" || FETCHED="No" +if [[ $RECENTLY_CHANGED_NUM -gt 0 && $2 != '-F' ]]; then + MERGED="Waiting" +fi + +if [[ ($RECENTLY_CHANGED_NUM -eq 0 || $2 = "-F") && $FETCHED = "Yes" ]]; then + MERGE_OUT=$(git merge origin/master) && MERGED="Yes" || MERGED="No" +fi + +if [[ $NEED_TO_PUSH -gt 0 && ($MERGED = "Yes" || $MERGED = "Waiting") ]]; then + git push origin && PUSHED="Yes" || PUSHED="No" +fi + +if [[ $PUSHED = "Yes" || $COMMITED = "Yes" || ($MERGED = "Yes" && $MERGE_OUT != "Already up to date.")]]; then + read -r -d '' NOTIFICATION << EOM +Commited: $COMMITED +Fetched: $FETCHED +Merged: $MERGED +Pushed: $PUSHED +EOM + notify-send "Autocommit $(pwd)" "$NOTIFICATION" +fi + +if [[ $(git ls-files -u | wc -l) -gt 0 ]]; then + notify-send -u critical "Autocommit $(pwd)" "Merge conflict!" +fi +``` + +`mcron` job: + +```scheme +(job "0 * * * *" "autocommit ~/Documents/org-mode") +(job "0,15,30,45 * * * *" "autocommit ~/.password-store") +``` + + +## Guix settings {#guix-settings} + + +```emacs-lisp +(my/format-guix-dependencies) +``` + +```scheme +(specifications->manifest + '( + <>)) +``` + + +## Android notes {#android-notes} + +SSH instructions: + +Don't forget to install the following termux packages: + +| Termux package | +|----------------| +| vim | +| tmux | +| starship | +| fish | +| exa | +| bat | +| git | + +Also: + +- cleanup `$PREFIX/etc/motd` to remove hello message. +- copy the required font at `$HOME/.termux/font.ttf` and run `termux-reload-settings`. + + +### Installation of [DT's colorscripts](https://gitlab.com/dwt1/shell-color-scripts): {#installation-of-dt-s-colorscripts} + +```bash +git clone https://gitlab.com/dwt1/shell-color-scripts.git +cd shell-color-scripts +``` + +Apply a patch: + +```diff +--- a/colorscript.sh ++++ b/colorscript.sh +@@ -2,7 +2,7 @@ + + # Simple CLI for shell-color-scripts + +-DIR_COLORSCRIPTS="/opt/shell-color-scripts/colorscripts" ++DIR_COLORSCRIPTS="$PREFIX/opt/shell-color-scripts/colorscripts" + LS_CMD="$(command -v ls)" + fmt_help=" %-20s\t%-54s\n" + list_colorscripts="$($LS_CMD "${DIR_COLORSCRIPTS}" | cut -d ' ' -f 1 | nl)" +``` + +```bash +sudo mkdir -p $PREFIX/opt/shell-color-scripts/colorscripts || return 1 +sudo cp -rf colorscripts/* $PREFIX/opt/shell-color-scripts/colorscripts +sudo cp colorscript.sh $PREFIX/bin/colorscript +``` \ No newline at end of file diff --git a/content/configs/Desktop.md b/content/configs/Desktop.md new file mode 100644 index 0000000..d40c128 --- /dev/null +++ b/content/configs/Desktop.md @@ -0,0 +1,2743 @@ ++++ +title = "Desktop" +author = ["Pavel"] +draft = false ++++ + +My general desktop environment configuration. + +Parts prefixed with (OFF) are not used, but kept for historic purposes. For some reason GitHub's org renderer ignores TODO status, hence such a prefix. Round brackets instead of square ones to prevent GitHub's org renderer from screwing up. + +
+
+ +
Table of Contents
+ +- [Global customization](#global-customization) + - [Colors](#colors) + - [Xresources](#xresources) + - [Colors in Xresources](#colors-in-xresources) + - [Fonts](#fonts) + - [Themes](#themes) + - [Device-specific settings](#device-specific-settings) +- [i3wm](#i3wm) + - [General settings](#general-settings) + - [Managing windows](#managing-windows) + - [Workspaces](#workspaces) + - [Rules](#rules) + - [Scratchpad](#scratchpad) + - [Launch script](#launch-script) + - [i3 config](#i3-config) + - [Gaps & borders](#gaps-and-borders) + - [Keybindings](#keybindings) + - [Move & resize windows](#move-and-resize-windows) + - [OFF (OFF) Intergration with dmenu](#off--intergration-with-dmenu) + - [Integration with rofi](#integration-with-rofi) + - [Launching apps & misc keybindings](#launching-apps-and-misc-keybindings) + - [Apps](#apps) + - [Media controls & brightness](#media-controls-and-brightness) + - [Screenshots](#screenshots) + - [Colors](#colors) + - [OFF (OFF) i3blocks](#off--i3blocks) + - [Keyboard Layout](#keyboard-layout) + - [Autostart](#autostart) +- [Polybar](#polybar) + - [Launching](#launching) + - [General settings](#general-settings) + - [Colors](#colors) + - [Bar config](#bar-config) + - [Modules](#modules) + - [ipstack-vpn](#ipstack-vpn) + - [weather](#weather) + - [aw-afk](#aw-afk) + - [sun](#sun) + - [SEP](#sep) + - [TSEP](#tsep) + - [i3](#i3) + - [xkeyboard](#xkeyboard) + - [mpd](#mpd) + - [pulseaudio](#pulseaudio) + - [cpu](#cpu) + - [ram-memory](#ram-memory) + - [swap-memory](#swap-memory) + - [network](#network) + - [date](#date) + - [battery](#battery) +- [Rofi](#rofi) + - [Theme](#theme) + - [Scripts](#scripts) + - [Buku bookmarks](#buku-bookmarks) + - [Man pages](#man-pages) +- [Flameshot](#flameshot) +- [dunst](#dunst) +- [keynav](#keynav) + - [Config](#config) + - [Using with picom](#using-with-picom) +- [Picom](#picom) + - [Shadows](#shadows) + - [Fading](#fading) + - [Opacity](#opacity) + - [General settings](#general-settings) +- [Zathura](#zathura) +- [Various software](#various-software) + - [Browsers](#browsers) + - [Office](#office) + - [LaTeX](#latex) + - [Dev](#dev) + - [Manifests](#manifests) + - [Flatpak](#flatpak) + - [Nix](#nix) +- [Services](#services) + - [Music](#music) + - [GNU Mcron](#gnu-mcron) + - [ActivityWatch](#activitywatch) + - [PulseEffects](#pulseeffects) + - [xsettingsd](#xsettingsd) + - [Discord rich presence](#discord-rich-presence) + - [Polkit Authentication agent](#polkit-authentication-agent) + - [Xmodmap](#xmodmap) + - [VPN](#vpn) + - [Davmail](#davmail) + - [Shepherd config](#shepherd-config) + - [Sync](#sync) +- [Guix settings](#guix-settings) + +
+ + + +## Global customization {#global-customization} + + +### Colors {#colors} + +Most of the colors are from the Palenight theme. Colorcodes are taken from [this repo](https://github.com/JonathanSpeek/palenight-iterm2): + + + +| color | key | value | +|---------------|---------|---------| +| black | color0 | #292d3e | +| red | color1 | #f07178 | +| green | color2 | #c3e88d | +| yellow | color3 | #ffcb6b | +| blue | color4 | #82aaff | +| magenta | color5 | #c792ea | +| cyan | color6 | #89ddff | +| white | color7 | #d0d0d0 | +| light-black | color8 | #434758 | +| light-red | color9 | #ff8b92 | +| light-green | color10 | #ddffa7 | +| light-yellow | color11 | #ffe585 | +| light-blue | color12 | #9cc4ff | +| light-magenta | color13 | #e1acff | +| light-cyan | color14 | #a3f7ff | +| light-white | color15 | #ffffff | + +The table above is the only source of truth for colors in this config. + +The first way to get colors of it is to use the following noweb: + + +```emacs-lisp +(let ((color (seq-some (lambda (e) (and (string= name (car e)) (nth 2 e))) table))) + (if (> quote 0) + (concat "\"" color "\"") + color)) +``` + +Also, run the following to disable configuration for noweb evaluations: + +```emacs-lisp +(setq-local org-confirm-babel-evaluate nil) +``` + +Test: + +```emacs-lisp +<> +``` + + +### Xresources {#xresources} + + +#### Colors in Xresources {#colors-in-xresources} + +However, I'd rather use the `Xresources` file wherever possible. Here is the code to generate an Xresources file from this table: + + +```emacs-lisp +(apply + #'concat + (mapcar + (lambda (elem) + (concat "*" (nth 1 elem) ": " (nth 2 elem) "\n")) + (seq-filter + (lambda (elem) (nth 1 elem)) + table))) +``` + +```vim +<> + +*background: <> +*foreground: <> +``` + + +#### Fonts {#fonts} + +Also, Xresources are used to set `Xft` settings. Unfortunately, the DPI setting has to be unique for each machine, which means I cannot commit `Xresources` to the repo. + + +```emacs-lisp +(let ((hostname (system-name))) + (cond ((string-equal hostname "azure") 120) + ((string-equal hostname "eminence") 120) + ((string-equal hostname "indigo") 120) + (t 96))) +``` + +```vim +Xft.dpi: <> +``` + + +### Themes {#themes} + +A few programs I use to customize the apperance are listed below. + +| Guix dependency | Description | +|--------------------|-------------------------| +| matcha-theme | My preferred GTK theme | +| papirus-icon-theme | My preferred Icon theme | +| xsettingsd | X11 settings daemon | + +[xsettingsd](https://github.com/derat/xsettingsd) is a lightweight daemon which configures X11 applications. It is launched with shepherd in the [Services](#services) section. + +```vim +Net/ThemeName "Matcha-dark-azul" +Net/IconThemeName "Papirus-Dark" +Gtk/DecorationLayout "menu:minimize,maximize,close" +Gtk/FontName "Sans 10" +Gtk/MonospaceFontName "JetBrainsMono Nerd Mono 12" +Gtk/CursorThemeName "Adwaita" +Xft/Antialias 1 +Xft/Hinting 0 +Xft/HintStyle "hintnone" +``` + + +### Device-specific settings {#device-specific-settings} + +| Guix dependency | Description | +|-----------------|--------------------------------------------| +| xrandr | X11 CLI to RandR | +| xgamma | A tool to alter monitor's gamma correction | +| xinput | Configure input devices | + +Set screen layout & other params depending on hostname + +```sh +hostname=$(hostname) +if [ "$hostname" = "indigo" ]; then + xrandr --output DisplayPort-0 --off --output HDMI-A-0 --mode 1920x1080 --pos 0x0 --rotate normal --output DVI-D-0 --mode 1920x1080 --pos 1920x0 --rotate normal +elif [ "$hostname" = "eminence" ]; then + xgamma -gamma 1.25 +fi +``` + + +## i3wm {#i3wm} + +| Guix dependency | Disabled | +|-----------------|----------| +| i3-gaps | | +| i3lock | true | + +`i3lock` is disabled because the global one has to be used. + +[i3wm](https://i3wm.org/) is a manual tiling window manager, which is currently my window manager of choice. I've tried several alternatives, including [xmonad](https://xmonad.org/) & [EXWM](https://github.com/ch11ng/exwm), but i3 seems to fit my workflow best. + +[i3-gaps](https://github.com/Airblader/i3) is an i3 fork with a few features like window gaps. I like to enable inner gaps when there is at least one container in a workspace. + +References: + +- [i3wm docs](https://i3wm.org/docs/) +- [i3-gaps wiki](https://github.com/Airblader/i3/wiki) + + +### General settings {#general-settings} + +```vim +set $mod Mod4 +font pango:monospace 10 + +# Use Mouse+$mod to drag floating windows to their wanted position +floating_modifier $mod + +# Move cursor between monitors +mouse_warping output + +# Apply XFCE Settings +# exec xfsettingsd +# exec xiccd + +# Set screen layout +exec ~/bin/scripts/screen-layout + +# Most needed keybindigs +# reload the configuration file +bindsym $mod+Shift+c reload + +# restart i3 inplace (preserves your layout/session, can be used to upgrade i3) +bindsym $mod+Shift+r restart + +# exit i3 (logs you out of your X session) +bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'" +``` + + +### Managing windows {#managing-windows} + +Some keybindings for managing windows. + +Kill focused windows + +```vim +bindsym $mod+Shift+q kill +``` + +Change focus + +```vim +bindsym $mod+h focus left +bindsym $mod+j focus down +bindsym $mod+k focus up +bindsym $mod+l focus right + +bindsym $mod+Left focus left +bindsym $mod+Down focus down +bindsym $mod+Up focus up +bindsym $mod+Right focus right +``` + +Move windows around + +```vim +bindsym $mod+Shift+h move left +bindsym $mod+Shift+j move down +bindsym $mod+Shift+k move up +bindsym $mod+Shift+l move right + +bindsym $mod+Shift+Left move left +bindsym $mod+Shift+Down move down +bindsym $mod+Shift+Up move up +bindsym $mod+Shift+Right move right +``` + +Split windows + +```vim +bindsym $mod+s split h +bindsym $mod+v split v +``` + +Enter fullscreen mode + +```vim +# enter fullscreen mode for the focused container +bindsym $mod+f fullscreen toggle +``` + +Changing layout + +```vim +bindsym $mod+w layout stacking +bindsym $mod+t layout tabbed +bindsym $mod+e layout toggle split +``` + +Toggle tiling/floating, switch between tiled and floating windows + +```vim +bindsym $mod+Shift+f floating toggle +bindsym $mod+z focus mode_toggle +``` + +Switching outputs + +```vim +bindsym $mod+Tab move workspace to output right +bindsym $mod+q focus output right +``` + +Focus parent and child container + +```vim +bindsym $mod+a focus parent +bindsym $mod+Shift+A focus child +``` + +Toggle sticky + +```vim +bindsym $mod+i sticky toggle +``` + +Set windows as floating and sticky, move to the top right. + +```vim +bindsym $mod+x floating enable; sticky enable; move position 1220 0; resize set width 700 px +``` + + +### Workspaces {#workspaces} + +```vim +set $w1 "1 🚀" +set $w2 "2 🌍" +set $w3 "3 💬" +set $w4 "4 🛠️️" +set $w7 "7 🛰️" +set $w8 "8 📝" +set $w9 "9 🎵" +set $w10 "10 📦" + +bindsym $mod+1 workspace $w1 +bindsym $mod+2 workspace $w2 +bindsym $mod+3 workspace $w3 +bindsym $mod+4 workspace $w4 +bindsym $mod+5 workspace 5 +bindsym $mod+6 workspace 6 +bindsym $mod+7 workspace $w7 +bindsym $mod+8 workspace $w8 +bindsym $mod+9 workspace $w9 +bindsym $mod+0 workspace $w10 + +# move focused container to workspace +bindsym $mod+Shift+1 move container to workspace $w1 +bindsym $mod+Shift+2 move container to workspace $w2 +bindsym $mod+Shift+3 move container to workspace $w3 +bindsym $mod+Shift+4 move container to workspace $w4 +bindsym $mod+Shift+5 move container to workspace 5 +bindsym $mod+Shift+6 move container to workspace 6 +bindsym $mod+Shift+7 move container to workspace $w7 +bindsym $mod+Shift+8 move container to workspace $w8 +bindsym $mod+Shift+9 move container to workspace $w9 +bindsym $mod+Shift+0 move container to workspace $w10 + +# Cycle workspaces +bindsym $mod+comma workspace prev +bindsym $mod+period workspace next +``` + + +### Rules {#rules} + +Rules to automatically assign applications to workspaces and do other stuff, like enable floating. + +Most apps can be distinguished by a WM class (you can get one with [xprop](https://www.x.org/releases/X11R7.5/doc/man/man1/xprop.1.html)), but in some cases it doesn't work, e.g. for terminal applications. In that case rules can be based on a window title, for instance. + +However, watch out for the following: rule such as `for_window [title="ncmpcpp.*"] move to workspace $w9` will move **any** windows with a title, starting with `ncmpcpp` to workspace `$w9`, which, for instance, may move your browser there if you google "ncmpcpp". + +```vim +assign [class="Emacs"] $w1 +assign [class="qutebrowser"] $w2 +assign [class="firefox"] $w2 +assign [class="VK"] $w3 +assign [class="Slack"] $w3 +assign [class="discord"] $w3 +assign [class="TelegramDesktop"] $w3 +assign [class="Postman"] $w4 +assign [class="Chromium-browse"] $w4 +assign [class="chromium"] $w4 +assign [class="google-chrome"] $w4 +assign [title="Vue Developer Tools"] $w4 +assign [class="Google Play Music Desktop Player"] $w9 +assign [class="jetbrains-datagrip"] $w4 +assign [class="zoom"] $w7 +assign [class="skype"] $w7 +assign [class="Mailspring"] $w8 +assign [class="Thunderbird"] $w8 +assign [class="Joplin"] $w8 +assign [class="keepassxc"] $w10 + +for_window [title="VirtScreen"] floating enable + +for_window [title="ncmpcpp.*"] move to workspace $w9 +for_window [title="newsboat.*"] move to workspace $w9 +for_window [title=".*run_wego"] move to workspace $w9 +for_window [class="cinnamon-settings*"] floating enable +for_window [title="Picture-in-Picture"] sticky enable +for_window [window_role="GtkFileChooserDialog"] resize set width 1000 px height 800 px +for_window [window_role="GtkFileChooserDialog"] move position center +``` + + +### Scratchpad {#scratchpad} + +Scratch terminal, inspired by [this Luke Smith's video](https://www.youtube.com/watch?v=q-l7DnDbiiU). + + +#### Launch script {#launch-script} + +First of all, we have to distinguish a scratchpad terminal from a normal one. To do that, one can create st with a required classname. + +Then, it would be cool not to duplicate scratchpads, so the following script first looks for a window with a created classname. If it exists, the script just toggles the scratchpad visibility. Otherwise, a new instance of a window is created. + +```bash +CLASSNAME="dropdown_tmux" +COMMAND="alacritty --class $CLASSNAME -e tmux new-session -s $CLASSNAME" +pid=$(xdotool search --classname "dropdown_tmux") +if [[ ! -z $pid ]]; then + i3-msg scratchpad show +else + setsid -f ${COMMAND} +fi +``` + + +#### i3 config {#i3-config} + +```vim +# Scratchpad +for_window [instance="dropdown_*"] floating enable +for_window [instance="dropdown_*"] move scratchpad +for_window [instance="dropdown_*"] sticky enable +for_window [instance="dropdown_*"] scratchpad show +for_window [instance="dropdown_*"] move position center + +bindsym $mod+u exec ~/bin/scripts/dropdown +``` + + +### Gaps & borders {#gaps-and-borders} + +The main reason to use i3-gaps + +```vim +# Borders +# for_window [class=".*"] border pixel 0 +default_border pixel 3 +hide_edge_borders both + +# Gaps +set $default_inner 10 +set $default_outer 0 + +gaps inner $default_inner +gaps outer $default_outer + +smart_gaps on +``` + + +#### Keybindings {#keybindings} + +```vim +mode "inner gaps" { + bindsym plus gaps inner current plus 5 + bindsym minus gaps inner current minus 5 + bindsym Shift+plus gaps inner all plus 5 + bindsym Shift+minus gaps inner all minus 5 + bindsym 0 gaps inner current set 0 + bindsym Shift+0 gaps inner all set 0 + + bindsym r gaps inner current set $default_inner + bindsym Shift+r gaps inner all set $default_inner + + bindsym Return mode "default" + bindsym Escape mode "default" +} + +mode "outer gaps" { + bindsym plus gaps outer current plus 5 + bindsym minus gaps outer current minus 5 + bindsym Shift+plus gaps outer all plus 5 + bindsym Shift+minus gaps outer all minus 5 + bindsym 0 gaps outer current set 0 + bindsym Shift+0 gaps outer all set 0 + + bindsym r gaps outer current set $default_outer + bindsym Shift+r gaps outer all set $default_outer + + bindsym Return mode "default" + bindsym Escape mode "default" +} + +bindsym $mod+g mode "inner gaps" +bindsym $mod+Shift+g mode "outer gaps" +``` + + +### Move & resize windows {#move-and-resize-windows} + +A more or less standard set of keybindings to move & resize floating windows. + +Just be careful to always make a way to return from these new modes, otherwise, you'd end up in a rather precarious position. + +```vim +# resize window (you can also use the mouse for that) +mode "resize" { + # These bindings trigger as soon as you enter the resize mode + + bindsym h resize shrink width 10 px or 10 ppt + bindsym j resize grow height 10 px or 10 ppt + bindsym k resize shrink height 10 px or 10 ppt + bindsym l resize grow width 10 px or 10 ppt + + bindsym Shift+h resize shrink width 100 px or 100 ppt + bindsym Shift+j resize grow height 100 px or 100 ppt + bindsym Shift+k resize shrink height 100 px or 100 ppt + bindsym Shift+l resize grow width 100 px or 100 ppt + + # same bindings, but for the arrow keys + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Down resize grow height 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt + bindsym Right resize grow width 10 px or 10 ppt + + bindsym Shift+Left resize shrink width 100 px or 100 ppt + bindsym Shift+Down resize grow height 100 px or 100 ppt + bindsym Shift+Up resize shrink height 100 px or 100 ppt + bindsym Shift+Right resize grow width 100 px or 100 ppt + + # back to normal: Enter or Escape + bindsym Return mode "default" + bindsym Escape mode "default" +} + +bindsym $mod+r mode "resize" + +mode "move" { + bindsym $mod+Tab focus right + + bindsym Left move left + bindsym Down move down + bindsym Up move up + bindsym Right move right + + bindsym h move left + bindsym j move down + bindsym k move up + bindsym l move right + + # back to normal: Enter or Escape + bindsym Return mode "default" + bindsym Escape mode "default" +} + +bindsym $mod+m mode "move" focus floating +``` + + +### OFF (OFF) Intergration with dmenu {#off--intergration-with-dmenu} + +[dmenu](https://tools.suckless.org/dmenu/) is a dynamic menu program for X. I've opted out of using it in favour of rofi, but here is a relevant bit of config. + +Scripts are located in the `bin/scripts` folder. + +```vim +# dmenu +bindsym $mod+d exec i3-dmenu-desktop --dmenu="dmenu -l 10" +bindsym $mod+apostrophe mode "dmenu" + +mode "dmenu" { + bindsym d exec i3-dmenu-desktop --dmenu="dmenu -l 10"; mode default + bindsym p exec dmenu_run -l 10; mode default + bindsym m exec dmenu-man; mode default + bindsym b exec dmenu-buku; mode default + bindsym f exec dmenu-explore; mode default + bindsym t exec dmenu-tmuxp; mode default + bindsym Escape mode "default" +} + +bindsym $mod+b exec --no-startup-id dmenu-buku +``` + + +### Integration with rofi {#integration-with-rofi} + +Keybindings to launch [rofi](https://github.com/davatorium/rofi). For more detail, look the [Rofi](#rofi) section. + +```vim +bindsym $mod+d exec "rofi -modi 'drun,run' -show drun" +bindsym $mod+b exec --no-startup-id rofi-buku-mine + +bindsym $mod+apostrophe mode "rofi" + +mode "rofi" { + bindsym d exec "rofi -modi 'drun,run' -show drun" + bindsym m exec rofi-man; mode default + bindsym b exec rofi-buku-mine; mode default + bindsym k exec rofi-keepassxc -d ~/MEGAsync/Passwords.kdbx; mode default + bindsym Escape mode "default" +} +``` + + +### Launching apps & misc keybindings {#launching-apps-and-misc-keybindings} + +I prefer to use a separate mode to launch most of my apps, with some exceptions. + + +#### Apps {#apps} + +```vim +# Launch apps +# start a terminal at workspace 1 +bindsym $mod+Return exec "i3-msg 'workspace 1 🚀; exec alacritty'" + +bindsym $mod+p exec "copyq menu" +bindsym $mod+Shift+x exec "i3lock -f -i /home/pavel/Pictures/lock-wallpaper.png" + +bindsym $mod+semicolon mode "apps" + +mode "apps" { + bindsym Escape mode "default" + bindsym b exec firefox; mode default + bindsym v exec vk; mode default + bindsym s exec slack-wrapper; mode default; + bindsym d exec "flatpak run com.discordapp.Discord"; mode default; + bindsym m exec "alacritty -e ncmpcpp"; mode default + bindsym c exec "copyq toggle"; mode default + bindsym k exec "keepassxc"; mode default + # bindsym e exec mailspring; mode default + bindsym a exec emacs; mode default + bindsym n exec "alacritty -e newsboat"; mode default + bindsym w exec "alacritty /home/pavel/bin/scripts/run_wego"; mode default + # bindsym a exec emacsclient -c; mode default + # bindsym Shift+a exec emacs; mode default +} +``` + + +#### Media controls & brightness {#media-controls-and-brightness} + +```vim +# Pulse Audio controls +bindsym XF86AudioRaiseVolume exec --no-startup-id "ponymix increase 5 --max-volume 150" +bindsym XF86AudioLowerVolume exec --no-startup-id "ponymix decrease 5 --max-volume 150" +bindsym XF86AudioMute exec --no-startup-id "ponymix toggle" + +exec --no-startup-id xmodmap -e 'keycode 135 = Super_R' && xset -r 135 +bindsym $mod+F2 exec --no-startup-id "ponymix increase 5" +bindsym $mod+F3 exec --no-startup-id "ponymix decrease 5" + +# Media player controls +bindsym XF86AudioPlay exec mpc toggle +bindsym XF86AudioPause exec mpc pause +bindsym XF86AudioNext exec mpc next +bindsym XF86AudioPrev exec mpc prev + +# Screen brightness +bindsym XF86MonBrightnessUp exec light -A 5 +bindsym XF86MonBrightnessDown exec light -U 5 +``` + + +#### Screenshots {#screenshots} + +```vim +# Screenshots +bindsym --release Print exec "flameshot gui" +bindsym --release Shift+Print exec "xfce4-screenshooter" +``` + + +### Colors {#colors} + +Application of the XResources theme to the WM. + +```vim +exec xrdb -merge $HOME/.Xresources + +# Colors +set_from_resource $bg-color background +set_from_resource $active-color color4 +set_from_resource $inactive-bg-color color8 +set_from_resource $text-color foreground +set_from_resource $inactive-text-color color7 +set_from_resource $urgent-bg-color color1 +set_from_resource $urgent-text-color color0 + +# window colors +# border background text indicator child border +client.focused $active-color $bg-color $text-color $bg-color $active-color +client.unfocused $bg-color $inactive-bg-color $inactive-text-color $bg-color $bg-color +client.focused_inactive $active-color $inactive-bg-color $inactive-text-color $bg-color $bg-color +client.urgent $urgent-bg-color $urgent-bg-color $urgent-text-color $bg-color $urgent-bg-color +``` + + +### OFF (OFF) i3blocks {#off--i3blocks} + +I've opted out of i3bar & [i3blocks](https://github.com/vivien/i3blocks) for [polybar](https://github.com/polybar/polybar) + +```vim +bar { + status_command i3blocks -c ~/.config/i3/i3blocks.conf + i3bar_command i3bar + font pango:monospace 12 + output HDMI-A-0 + tray_output none + colors { + background $bg-color + separator #757575 + # border background text + focused_workspace $bg-color $bg-color $text-color + inactive_workspace $inactive-bg-color $inactive-bg-color $inactive-text-color + urgent_workspace $urgent-bg-color $urgent-bg-color $urgent-text-color + } +} + +bar { + status_command i3blocks -c ~/.config/i3/i3blocks.conf + i3bar_command i3bar + font pango:monospace 10 + output DVI-D-0 + colors { + background $bg-color + separator #757575 + # border background text + focused_workspace $bg-color $bg-color $text-color + inactive_workspace $inactive-bg-color $inactive-bg-color $inactive-text-color + urgent_workspace $urgent-bg-color $urgent-bg-color $urgent-text-color + } +} +``` + + +### Keyboard Layout {#keyboard-layout} + +A script to set Russian-English keyboard layout: + +```bash +setxkbmap -layout us,ru +setxkbmap -model pc105 -option 'grp:win_space_toggle' -option 'grp:alt_shift_toggle' +``` + +A script to toggle the layout + +```bash +if setxkbmap -query | grep -q us,ru; then + setxkbmap -layout us + setxkbmap -option +else + setxkbmap -layout us,ru + setxkbmap -model pc105 -option 'grp:win_space_toggle' -option 'grp:alt_shift_toggle' +fi +``` + +And the relevant i3 settings: + +```vim +# Layout +exec_always --no-startup-id set_layout +bindsym $mod+slash exec toggle_layout +``` + + +### Autostart {#autostart} + +```vim +# Polybar +exec_always --no-startup-id "bash /home/pavel/bin/polybar.sh" + +# Wallpaper +exec_always "feh --bg-fill ~/Pictures/wallpaper.jpg" + +# Picom +exec picom + +# Keynav +exec keynav + +# Applets +exec --no-startup-id nm-applet +# exec --no-startup-id /usr/bin/blueman-applet + +exec shepherd +exec dunst +exec copyq +exec "xmodmap ~/.Xmodmap" +# exec "xrdb -merge ~/.Xresources" +# exec "bash ~/bin/autostart.sh" +``` + + +## Polybar {#polybar} + +| Guix dependency | Description | +|-----------------|-------------| +| polybar | statusbar | + +[Polybar](https://github.com/polybar/polybar) is a nice-looking, WM-agnostic statusbar program. + +I switched to polybar because I wanted to try out some WMs other than i3, but decided to stick with i3 for now. + +Don't forget to install the Google Noto Color Emoji font. Guix package with all Noto fonts is way too large. + +References: + +- [polybar docs](https://github.com/polybar/polybar/wiki) + + +### Launching {#launching} + +The script below allows me to: + +- have different blocks on my two different-sized monitors and my laptop; +- have different settings on my desktop PC and laptop; + + + +```bash +hostname=$(hostname) +# Settings varying on the hostname +export WLAN_INTERFACE=$(nmcli -f DEVICE con show | grep -Ev "(.*docker.*|DEVICE|br.*|tun.*|--)" | xargs) +if [ "$hostname" = "azure" ]; then + TRAY_MONITOR="eDP-1" + # export WLAN_INTERFACE="wlp3s0" +elif [ "$hostname" = "eminence" ]; then + TRAY_MONITOR="eDP" + # export WLAN_INTERFACE="wlo1" +else + TRAY_MONITOR="HDMI-A-0" + # export WLAN_INTERFACE="wlp35s0f3u2" +fi + +# Setting varying on the monitor +declare -A FONT_SIZES=( + ["eDP"]="13" + ["eDP-1"]="13" + ["DVI-D-0"]="13" + ["HDMI-A-0"]="13" +) +declare -A EMOJI_SCALE=( + ["eDP"]="9" + ["eDP-1"]="9" + ["DVI-D-0"]="10" + ["HDMI-A-0"]="10" +) +declare -A BAR_HEIGHT=( + ["eDP"]="29" + ["eDP-1"]="29" + ["DVI-D-0"]="29" + ["HDMI-A-0"]="29" +) +declare -A BLOCKS=( + ["eDP"]="pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP battery SEP sun aw-afk date TSEP" + ["eDP-1"]="pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP battery SEP sun aw-afk date TSEP" + ["DVI-D-0"]="pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP weather SEP sun aw-afk date TSEP" + ["HDMI-A-0"]="pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP weather SEP sun aw-afk date TSEP" +) + +# Geolocation for some modules +export LOC="SPB" + +export IPSTACK_API_KEY=$(pass show My_Online/APIs/ipstack | head -n 1) + +pkill polybar +for m in $(xrandr --query | grep " connected" | cut -d" " -f1); do + export MONITOR=$m + if [ "$MONITOR" = "$TRAY_MONITOR" ]; then + export TRAY="right" + else + export TRAY="none" + fi + SIZE=${FONT_SIZES[$MONITOR]} + SCALE=${EMOJI_SCALE[$MONITOR]} + if [[ -z "$SCALE" ]]; then + continue + fi + export FONT0="pango:monospace:size=$SIZE;1" + export FONT1="NotoEmoji:scale=$SCALE:antialias=false;1" + export FONT2="fontawesome:pixelsize=$SIZE;1" + export FONT3="JetBrains Mono Nerd Font:monospace:size=$SIZE;1" + export HEIGHT=${BAR_HEIGHT[$MONITOR]} + export RIGHT_BLOCKS=${BLOCKS[$MONITOR]} + polybar mybar & +done +``` + + +### General settings {#general-settings} + + +#### Colors {#colors} + +```ini +[colors] +; Palenight colorscheme https://github.com/JonathanSpeek/palenight-iterm2 +black = ${xrdb:color0} +red = ${xrdb:color1} +green = ${xrdb:color2} +yellow = ${xrdb:color3} +blue = ${xrdb:color4} +magenta = ${xrdb:color5} +cyan = ${xrdb:color6} +white = ${xrdb:color7} + +black-lighter = ${xrdb:color8} +red-lighter = ${xrdb:color9} +green-lighter = ${xrdb:color10} +yellow-lighter = ${xrdb:color11} +blue-lighter = ${xrdb:color12} +magenta-lighter = ${xrdb:color13} +cyan-lighter = ${xrdb:color14} +white-lighter = ${xrdb:color15} + +background = ${xrdb:background} +foreground = ${xrdb:foreground} +``` + + +#### Bar config {#bar-config} + +```ini +[bar/mybar] +monitor = ${env:MONITOR:} +width = 100% +height = ${env:HEIGHT:27} +offset-x = 0 +offset-y = 0 +radius = 0.0 +fixed-center = false +bottom=true + +background = ${colors.background} +foreground = ${colors.foreground} + +line-size = 3 +line-color = #f00 + +padding-left = 0 +padding-right = 0 + +module-margin-left = 1 +module-margin-right = 1 + +font-0 = ${env:FONT0:pango:monospace:size=10;1} +font-1 = ${env:FONT1:NotoEmoji:scale=10:antialias=false;0} +font-2 = ${env:FONT2:fontawesome:pixelsize=10;1} +font-3 = ${env:FONT3:JetBrains Mono Nerd Font:monospace:size=10;1} + +modules-left = i3 +; modules-center = test +modules-right = ${env:RIGHT_BLOCKS} + +tray-position = ${env:TRAY:right} +tray-padding = 0 +tray-maxsize = 16 +;tray-background = #0063ff + +wm-restack = i3 +; override-redirect = true + +scroll-up = i3wm-wsnext +scroll-down = i3wm-wsprev + +; cursor-click = pointer +; cursor-scroll = ns-resize + +[settings] +screenchange-reload = true +;compositing-background = xor +;compositing-background = screen +;compositing-foreground = source +;compositing-border = over +;pseudo-transparency = false + +[global/wm] +margin-top = 0 +margin-bottom = 0 +``` + + +### Modules {#modules} + +Some of the custom modules below use Org mode noweb to evaluate colors, because it's faster than querying `xrdb` at runtime. I wish I could reference polybar values there, but [it looks like this is impossible](https://github.com/polybar/polybar/issues/615). + +If you want to copy something, you can go to the [bin/polybar](bin/polybar/) folder. + + +#### ipstack-vpn {#ipstack-vpn} + +| Guix dependency | Description | +|-----------------|-------------------------| +| bind:utils | Provides dig | +| curl | | +| jq | util to work with JSONs | + +A module to get a country of the current IP and openvpn status. Uses [ipstack](https://ipstack.com/) API. + +```bash +ip=$(dig +short +timeout=1 myip.opendns.com @resolver1.opendns.com 2> /dev/null) +# API_KEY="$(pass show My_Online/APIs/ipstack | head -n 1)" +API_KEY=$IPSTACK_API_KEY +if [[ -z $ip || $ip == *"timed out"* ]]; then + echo "%{u<>}%{+u} ?? %{u-}" + exit +fi +ip_info=$(curl -s http://api.ipstack.com/${ip}?access_key=${API_KEY}) +# emoji=$(echo $ip_info | jq -r '.location.country_flag_emoji') +code=$(echo $ip_info | jq -r '.country_code') +vpn=$(pgrep -a openvpn$ | head -n 1 | awk '{print $NF }' | cut -d '.' -f 1) + +if [ -n "$vpn" ]; then + echo "%{u<>}%{+u}  $code %{u-}" +else + echo "%{u<>}%{+u}  $code %{u-}" +fi +``` + +```ini +[module/ipstack-vpn] +type = custom/script +exec = /home/pavel/bin/polybar/ipstack-vpn.sh +interval = 1200 +``` + + +#### weather {#weather} + +Gets current weather from [wttr.in](http://wttr.in/) + +```bash +bar_format="${BAR_FORMAT:-"%t"}" +location="${LOCATION:-"Saint-Petersburg"}" +format_1=${FORMAT_1:-"qF"} +format_2=${FORMAT_1:-"format=v2n"} + +bar_weather=$(curl -s wttr.in/${location}?format=${bar_format} || echo "??") +if [ -z "$bar_weather" ]; then + exit 1 +elif [[ "$bar_weather" == *"Unknown"* || "$bar_weather" == *"Sorry"* || "$bar_weather" == *"Bad Gateway"* ]]; then + echo "??" + exit 1 +else + echo ${bar_weather} +fi +``` + +```ini +[module/weather] +type = custom/script +exec = /home/pavel/bin/polybar/weather.sh +format-underline = ${colors.red} +interval = 1200 +``` + + +#### aw-afk {#aw-afk} + +Prints out a current uptime and non-AFK time from [ActivityWatch](https://github.com/ActivityWatch) server + +| Guix dependency | +|-----------------| +| dateutils | + +```bash +afk_event=$(curl -s -X GET "http://localhost:5600/api/0/buckets/aw-watcher-afk_$(hostname)/events?limit=1" -H "accept: application/json") +status=$(echo ${afk_event} | jq -r '.[0].data.status') +afk_time=$(echo "${afk_event}" | jq -r '.[0].duration' | xargs -I ! date -u -d @! +"%H:%M") + +uptime=$(uptime | awk '{ print substr($3, 0, length($3) - 1) }' | xargs -I ! date -d ! +"%H:%M") +res="${afk_time} / ${uptime}" +if [[ $status == 'afk' ]]; then + echo "%{u<>}%{+u} [AFK] $res %{u-}" +else + echo "%{u<>}%{+u} $res %{u-}" +fi +``` + +```ini +[module/aw-afk] +type = custom/script +exec = /home/pavel/bin/polybar/aw_afk.sh +interval = 60 +``` + + +#### sun {#sun} + +| Guix dependency | +|-----------------| +| sunwait | + +Prints out the time of sunrise/sunset. Uses [sunwait](https://github.com/risacher/sunwait) + +```bash +declare -A LAT_DATA=( + ["TMN"]="57.15N" + ["SPB"]="59.9375N" +) +declare -A LON_DATA=( + ["TMN"]="65.533333E" + ["SPB"]="30.308611E" +) +if [ -z "$LOC" ]; then + echo "LOC?" + exit -1 +fi +LAT=${LAT_DATA[$LOC]} +LON=${LON_DATA[$LOC]} + +time=$(sunwait poll daylight rise ${LAT} $LON) + +if [[ ${time} == 'DAY' ]]; then + sunset=$(sunwait list daylight set ${LAT} ${LON}) + echo "%{u<>}%{+u} $sunset %{u-}" +else + sunrise=$(sunwait list daylight rise ${LAT} ${LON}) + echo "%{u<>}%{+u} $sunrise %{u-}" +fi +``` + +```ini +[module/sun] +type = custom/script +exec = /home/pavel/bin/polybar/sun.sh +interval = 60 +``` + + +#### SEP {#sep} + +A simple separator + +```ini +[module/SEP] +type = custom/text +content = "|" +content-foreground = ${colors.magenta} +content-padding = 0 +content-margin = 0 +interval = 100000 +``` + + +#### TSEP {#tsep} + +A separator, which appears only if monitor is set to have a tray in the launch script + +```bash +if [ ! -z "$TRAY" ] && [ "$TRAY" != "none" ]; then + echo "| " +fi +``` + +```ini +[module/TSEP] +type = custom/script +exec = /home/pavel/bin/polybar/tray-sep.sh +format-foreground = ${colors.magenta} +interval = 100000 +``` + + +#### i3 {#i3} + +Show i3wm workspaces + +```ini +[module/i3] +type = internal/i3 +format = +index-sort = true +wrapping-scroll = false + +; Only show workspaces on the same output as the bar +pin-workspaces = true + +label-mode-padding = 1 +label-mode-foreground = #000 +label-mode-background = ${colors.blue} + +; focused = Active workspace on focused monitor +label-focused = % +; label-focused-background = ${colors.background-alt} +label-focused-underline= ${colors.blue} +label-focused-padding = 1 + +; unfocused = Inactive workspace on any monitor +label-unfocused = % +label-unfocused-padding = 1 + +; visible = Active workspace on unfocused monitor +label-visible = % +; label-visible-background = ${self.label-focused-background} +label-visible-underline = ${self.label-focused-underline} +label-visible-padding = ${self.label-focused-padding} + +; urgent = Workspace with urgency hint set +label-urgent = % +label-urgent-background = ${colors.red} +label-urgent-foreground = ${colors.black} +label-urgent-padding = 1 +``` + + +#### xkeyboard {#xkeyboard} + +Current keyboard layout + +```ini +[module/xkeyboard] +type = internal/xkeyboard +format = + +format-underline = ${colors.magenta} +label-layout = %icon% +layout-icon-0 = ru;RU +layout-icon-1 = us;US +``` + + +#### mpd {#mpd} + +[Music Player Daemon](https://www.musicpd.org/) status + +```ini +[module/mpd] +type = internal/mpd + +format-playing = +format-paused = +format-stopped =  +label-song = [%album-artist%] %title% +label-time = %elapsed%/%total% + +label-song-maxlen = 30 +label-song-ellipsis = true + +format-playing-underline = ${colors.yellow} +format-paused-underline = ${colors.yellow} +format-stopped-underline = ${colors.yellow} + +label-separator = 0 +separator-foreground = ${colors.red} + +icon-pause =  +icon-play =  +icon-stop =  +icon-prev = 1 +icon-next = 2 +``` + + +#### pulseaudio {#pulseaudio} + +PulseAudio status + +```ini +[module/pulseaudio] +type = internal/pulseaudio +use-ui-max = true + +bar-volume-width = 7 +bar-volume-foreground-0 = ${colors.white} +bar-volume-foreground-1 = ${colors.yellow} +bar-volume-foreground-2 = ${colors.yellow} +bar-volume-foreground-3 = ${colors.blue} +bar-volume-foreground-4 = ${colors.blue} +bar-volume-foreground-5 = ${colors.green} +bar-volume-foreground-6 = ${colors.green} +bar-volume-gradient = false +bar-volume-indicator = | +bar-volume-indicator-font = 2 +bar-volume-fill = ─ +bar-volume-fill-font = 2 +bar-volume-empty = ─ +bar-volume-empty-font = 2 +bar-volume-empty-foreground = ${colors.white-lighter} + +format-volume = ♪ +label-volume = %percentage%% + +format-mute = ♪ +label-muted = MUTE + +format-volume-underline = ${colors.white} +format-muted-underline = ${colors.black-lighter} +``` + + +#### cpu {#cpu} + +CPU usage + +```ini +[module/cpu] +type = internal/cpu +format = 