zsh and GNU stow				#14
		
		
	
					 1 changed files with 406 additions and 0 deletions
				
			
		
							
								
								
									
										406
									
								
								2025-06-05_zsh-gnu-stow.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										406
									
								
								2025-06-05_zsh-gnu-stow.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,406 @@ | ||||||
|  | --- | ||||||
|  | 
 | ||||||
|  | date: 2025-06-05 | ||||||
|  | title: zsh and GNU stow | ||||||
|  | tags: | ||||||
|  | 
 | ||||||
|  | - software | ||||||
|  | - linux | ||||||
|  | - development | ||||||
|  | 
 | ||||||
|  | --- | ||||||
|  | 
 | ||||||
|  | In [my last post exploring `nvim`](https://blog.mcknight.tech/2025/05/21/nvim/), I mentioned some potential next projects on my agenda. | ||||||
|  | Well, I wasted no time continuing down the path of trying to perfect my shell experience. I very quickly updated my | ||||||
|  | [dotfiles repository](https://forge.mcknight.tech/d_mcknight/dotfiles) to be compatible with GNU `stow` and then went on to work on my | ||||||
|  | `.zshrc` file. Neither of these are major projects, so I figured they can share this one post. | ||||||
|  | 
 | ||||||
|  | ## GNU stow | ||||||
|  | 
 | ||||||
|  | There are a few ways to use GNU stow and I always recommend people to | ||||||
|  | [RTFM](https://www.gnu.org/software/stow/manual/stow.html#Invoking-Stow) if you ever run into problems or have questions about | ||||||
|  | CLI arguments. Alternatively, this package is old and stable enough that Claude or ChatGPT can easily answer any questions you | ||||||
|  | may have. For my use, I am [already keeping my dotfiles](https://blog.mcknight.tech/2024/06/21/Dotfiles/) in `~/.dotfiles`, so | ||||||
|  | it makes sense for me to make that repository look like my home directory. By default, `stow` will apply the contents of | ||||||
|  | my stow directory (`~/.dotfiels`) to its parent directory (`~/`). | ||||||
|  | 
 | ||||||
|  | You can see my [dotfiles repository](https://forge.mcknight.tech/d_mcknight/dotfiles/src/commit/e23e66f801b0549d6195d7115ed6f033ed4318e6) | ||||||
|  | now contains the same files it did before, but they are organized as if the repository root is my Home directory. One potential downside | ||||||
|  | of this organization is that it adds complexity if I wanted to apply only specific dotfiles or directories, but I can't think of anything | ||||||
|  | here that I would want to selectively apply to any environments. It is also worth noting that I had to remove any existing files or | ||||||
|  | symlinks before running `stow .` from my `~/.dotfiles` directory, otherwise `stow` would refuse to overwrite existing files. There may be | ||||||
|  | an argument to force overwrite destination files, but I prefer to manually delete things, just to make sure I'm not deleting/overwriting | ||||||
|  | something I want to keep. | ||||||
|  | 
 | ||||||
|  | ### Some dotfiles updates | ||||||
|  | 
 | ||||||
|  | There are a few updates to my dotfiles that I never documented in my | ||||||
|  | [original dotfiles post](https://blog.mcknight.tech/2024/06/21/Dotfiles/), or [Neovim post](https://blog.mcknight.tech/2025/05/21/nvim/). | ||||||
|  | This may not be exhaustive, but here are some of the highlights: | ||||||
|  | 
 | ||||||
|  | #### `alacritty.toml` | ||||||
|  | 
 | ||||||
|  | I have been using [Alacritty](https://alacritty.org/) for my regular terminal emulator, | ||||||
|  | so I have [some customizations](https://forge.mcknight.tech/d_mcknight/dotfiles/src/commit/e23e66f801b0549d6195d7115ed6f033ed4318e6/.config/alacritty/alacritty.toml) | ||||||
|  | I like to apply. Below is my configuration with annotations explaining everything. | ||||||
|  | 
 | ||||||
|  | ```toml | ||||||
|  | [general] | ||||||
|  | # Apply a GitHub dark theme for a consistent look | ||||||
|  | import = ["./github_dark_high_contrast.toml" ] | ||||||
|  | 
 | ||||||
|  | [colors.primary] | ||||||
|  | # Override background to a neutral dark color | ||||||
|  | background = "#111111" | ||||||
|  | 
 | ||||||
|  | [colors.normal] | ||||||
|  | # I picked this color when configuring tmux, override terminal text color to match | ||||||
|  | cyan = '#008b8b' | ||||||
|  | 
 | ||||||
|  | [font.normal] | ||||||
|  | # Use a Nerd Font for extra symbols. I have this included in my `dotfiles` repository | ||||||
|  | family = 'JetBrainsMono Nerd Font Mono' | ||||||
|  | style = 'Regular' | ||||||
|  | 
 | ||||||
|  | [cursor] | ||||||
|  | # I prefer a blinking input cursor | ||||||
|  | blink_interval = 500 | ||||||
|  | blink_timeout = 0 | ||||||
|  | 
 | ||||||
|  | [cursor.style] | ||||||
|  | # I tried `Underline`, but I think I prefer the default block | ||||||
|  | blinking = "Always" | ||||||
|  | #shape = "Underline" | ||||||
|  | 
 | ||||||
|  | [window] | ||||||
|  | # Make the window slightly transparent to peek at what's behind | ||||||
|  | opacity = 0.95 | ||||||
|  | # Hide the top bar because I never close the terminal and use gTile to position it on screen | ||||||
|  | decorations = "None" | ||||||
|  | # I have `level` set, but it doesn't appear to do anything in Cinnamon :/ | ||||||
|  | level = "AlwaysOnTop" | ||||||
|  | # dynamic_padding splits extra vertical/horizontal space which makes tmux and nvim status bars look a little nicer | ||||||
|  | dynamic_padding = true | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | #### JetBrains Nerd Font | ||||||
|  | 
 | ||||||
|  | [Nerd Fonts](https://www.nerdfonts.com/font-downloads) let you get a consistent font | ||||||
|  | that includes extra characters like filetype icons, emojis, and ligatures (special | ||||||
|  | characters for things like `==`, `->`, and other character combinations). Since I | ||||||
|  | have this configured in my terminal config, it makes sense to make sure the font is | ||||||
|  | always available so I just include it in my dotfiles repository. | ||||||
|  | 
 | ||||||
|  | ## zsh | ||||||
|  | 
 | ||||||
|  | [`zsh`](https://www.zsh.org/) is a shell, like [`bash`](https://www.gnu.org/software/bash/), | ||||||
|  | but with some different features that are interesting. It's worth nothing that I fully intend on using `bash` | ||||||
|  | for scripting since it is far more ubiquitous than `zsh` and I am more familiar with it and its quirks. | ||||||
|  | I will also note that zsh is NOT a [POSIX shell](https://en.wikipedia.org/wiki/POSIX); | ||||||
|  | this is a common complaint that I see. Personally, I am okay with this since I | ||||||
|  | haven't run into any issues thus far and `zsh` is good enough to be the default shell in popular | ||||||
|  | operating systems, including macOS and TrueNAS. | ||||||
|  | 
 | ||||||
|  | There are a couple reasons I decided to try `zsh`, the first being tab completion which | ||||||
|  | I find helpful when completing a path or command where there are only a couple options to tab through. | ||||||
|  | I also wanted to try out some of the plugins and the configuration, which I find much easier to work with, | ||||||
|  | compared to `bashrc`. | ||||||
|  | 
 | ||||||
|  | ### RC Files | ||||||
|  | 
 | ||||||
|  | [Run Commands files](https://en.wikipedia.org/wiki/RUNCOM) are basically files that | ||||||
|  | are executed when a program starts. I | ||||||
|  | [previously detailed my `.bashrc` file](https://blog.mcknight.tech/2024/03/27/Shell-Customizations/#BASH-Configuration), | ||||||
|  | which is executed whenever I open a new `bash` shell. | ||||||
|  | I wanted to experiment with `zsh` configuration because it feels a little more modern | ||||||
|  | and powerful to me compared to `bash`. For example, my `bash` shell prompt looks like: | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  |     color_off="\[\033[0m\]"  # Text Reset | ||||||
|  | 
 | ||||||
|  |     # Regular Colors | ||||||
|  |     black="\[\033[0;30m\]" | ||||||
|  |     red="\[\033[0;31m\]" | ||||||
|  |     green="\[\033[0;32m\]" | ||||||
|  |     yellow="\[\033[0;33m\]" | ||||||
|  |     blue="\[\033[0;34m\]" | ||||||
|  |     purple="\[\033[0;35m\]" | ||||||
|  |     cyan="\[\033[0;36m\]" | ||||||
|  |     white="\[\033[0;37m\]" | ||||||
|  |      | ||||||
|  |     path_color=$blue | ||||||
|  |     chrome_color=$purple | ||||||
|  |     context_color=$cyan | ||||||
|  |     prompt_symbol=@  # 🚀💲 | ||||||
|  |     prompt='\$' | ||||||
|  |     if [ "$EUID" -eq 0 ]; then # Change prompt colors for root user | ||||||
|  |       context_color=$red | ||||||
|  |       prompt_symbol=💀 | ||||||
|  |     fi | ||||||
|  |     PROMPT_COMMAND='if [[ $? != 0 && $? != 130 ]];then echo -e "⚠️ \a";else echo -e "\a";fi' | ||||||
|  |     PS1="$chrome_color┌──"'${debian_chroot:+('${path_color}'$debian_chroot'${chrome_color}')─}${VIRTUAL_ENV:+('${path_color}'$(realpath $VIRTUAL_ENV --relative-to $PWD --relative-base /home)'${chrome_color}')─}'"[${context_color}\u${chrome_color}${prompt_symbol}${context_color}\h${chrome_color}]─(${path_color}\w${chrome_color})\n${chrome_color}└${context_color}${prompt}${color_off} " | ||||||
|  |     PS2="$chrome_color└>$color_off " | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | and in zsh: | ||||||
|  | 
 | ||||||
|  | ```zsh | ||||||
|  | function precmd { | ||||||
|  |   # Check previous command output and notify | ||||||
|  |   if [[ $? != 0 && $? != 130 ]];then | ||||||
|  |     echo -e "⚠️ \a" | ||||||
|  |   else | ||||||
|  |     echo -e "\a" | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   if [ "$EUID" -eq 0 ];then | ||||||
|  |     chrome_color="{red}" | ||||||
|  |   else | ||||||
|  |     chrome_color="{magenta}" | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   # Static prefix | ||||||
|  |   prefix="%F$chrome_color┌──[%F{cyan}%n%F$chrome_color@%F{cyan}%m%F$chrome_color]-" | ||||||
|  | 
 | ||||||
|  |   # Calculate extra path | ||||||
|  |   if [[ ${debian_chroot} ]]; then | ||||||
|  |     path_extra="(%F{red}${debian_chroot}%F$chrome_color)-" | ||||||
|  |   elif [[ ${VIRTUAL_ENV} ]]; then | ||||||
|  |     rel_venv=$(realpath $VIRTUAL_ENV --relative-to $PWD --relative-base /home) | ||||||
|  |     path_extra="[%F{blue}${rel_venv}%F$chrome_color]-" | ||||||
|  |   else; | ||||||
|  |     path_extra="" | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   # Static suffix | ||||||
|  |   suffix="(%F{blue}%~%F${chrome_color})"$'\n'"└%F{cyan}%#%F{white} " | ||||||
|  | 
 | ||||||
|  |   PROMPT=$prefix$path_extra$suffix | ||||||
|  |   PS2="%F$chrome_color└%F{cyan}>%F{white} " | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | I find the `zsh` version to be much more readable and easier to modify, since I have a | ||||||
|  | method to generate the prompt instead of a single variable to cram everything into. | ||||||
|  | I believe I have these two prompts looking identical in all cases and it only took me | ||||||
|  | about an hour to get my `zshrc` working identically to my `bashrc`; this included | ||||||
|  | some refactoring from `.bashrc` into `.bash_aliases` and `.profile`. I also | ||||||
|  | made sure `.profile` is always sourced in `bash` and `zsh` shells to avoid duplicating | ||||||
|  | code in those rc files. I considered using a common `aliases` file, but decided against it since | ||||||
|  | I use different aliases for different shells (i.e. `sudosu` is shell-specific). | ||||||
|  | 
 | ||||||
|  | ### `zsh` Plugins | ||||||
|  | 
 | ||||||
|  | Another interesting feature of `zsh` is that it supports plugins. | ||||||
|  | Now, just like with Neovim, there are a number of different plugin managers that can be | ||||||
|  | used with `zsh`. I don't know if there is a "best" choice, but after some light reading | ||||||
|  | up on the popular options I could find and some [LLM summary comparisons](https://search.brave.com/search?q=zinit+vs+omz&source=desktop&summary=1&conversation=f5495011020a89faf13bf1), | ||||||
|  | I settled on [Zinit](https://github.com/zdharma-continuum/zinit) as a lightweight and | ||||||
|  | apparently maintained option. | ||||||
|  | 
 | ||||||
|  | #### OMZ extract | ||||||
|  | 
 | ||||||
|  | This convenience command lets me extract files without having to remember the syntax for | ||||||
|  | extracting `.tar.xz`, `.zip`, `.tar.gz`, etc. A simple `extract <file>` is much easier | ||||||
|  | to remember than the specific commands for each compression algorithm. | ||||||
|  | 
 | ||||||
|  | #### OMZ colored-man-pages | ||||||
|  | 
 | ||||||
|  | This adds some color to man pages which I think makes it a little easier to skim to find | ||||||
|  | CLI args and section headers. Its not the *best* IMO, but something is better than nothing | ||||||
|  | when trying to skim through what can be pretty dense documentation. | ||||||
|  | 
 | ||||||
|  | #### OMZ encode64 | ||||||
|  | 
 | ||||||
|  | It isn't every day that I need to get a b64-encoded representation of a string, but its | ||||||
|  | handy to be able to do so quickly and easily. | ||||||
|  | 
 | ||||||
|  | #### OMZ pip | ||||||
|  | 
 | ||||||
|  | I like having tab completion for pip. I haven't used it too much yet, but I already see | ||||||
|  | how this will save me from trying to `pip isntall` when I really mean `pip install`. I | ||||||
|  | do this more than I'd like to admit. Other than that, its nice to have reminders for the | ||||||
|  | less commonly used flags. | ||||||
|  | 
 | ||||||
|  | #### OMZ sudo | ||||||
|  | 
 | ||||||
|  | The Oh My Zsh sudo plugin adds a convenience keybind (`esc`+`esc`) to prepend `sudo` to | ||||||
|  | the current command or the previous command if the input is empty. I find this to be | ||||||
|  | convenient as it is fairly common to re-run the previous command with elevated privileges | ||||||
|  | or to prepend `sudo` if I forgot to start with that (saving 5 keystrokes compared to | ||||||
|  | `sudo !!`) | ||||||
|  | 
 | ||||||
|  | #### zsh-autosuggestions | ||||||
|  | 
 | ||||||
|  | This plugin feels much like suggestions in an IDE, providing a suggested command completion | ||||||
|  | that can be filled in with a bound key (I am using `Shift`+`Tab`). | ||||||
|  | I find this mapping more convenient than the default `->`, since I can reach it without | ||||||
|  | moving my fingers from the home row and it is easy to remember `tab` and `shift`+`tab` | ||||||
|  | are both a kind of completion. | ||||||
|  | 
 | ||||||
|  | #### zsh-syntax-highlighting | ||||||
|  | 
 | ||||||
|  | This plugin highlights syntax as you type in a command. This clearly identifies unresolved | ||||||
|  | commands or files to help catch errors before trying to run an incomplete command. It also | ||||||
|  | helps to identify un-escaped characters in a quoted string. | ||||||
|  | 
 | ||||||
|  | ### `.zshrc` | ||||||
|  | 
 | ||||||
|  | Now that I've explained the components, here's my `.zshrc` file in its entirety: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | # Lines configured by zsh-newuser-install | ||||||
|  | HISTFILE=~/.histfile | ||||||
|  | HISTSIZE=1000 | ||||||
|  | SAVEHIST=1000 | ||||||
|  | setopt autocd notify | ||||||
|  | unsetopt beep | ||||||
|  | bindkey -v | ||||||
|  | # End of lines configured by zsh-newuser-install | ||||||
|  | 
 | ||||||
|  | # SSH completion | ||||||
|  | zstyle ':completion:*:(ssh|scp|ftp|sftp|rsync):*' hosts $hosts | ||||||
|  | 
 | ||||||
|  | # The following lines were added by compinstall | ||||||
|  | zstyle :compinstall filename '/home/d_mcknight/.zshrc' | ||||||
|  | 
 | ||||||
|  | autoload -Uz compinit | ||||||
|  | compinit | ||||||
|  | # End of lines added by compinstall | ||||||
|  | 
 | ||||||
|  | # Source common envvars | ||||||
|  | [ -f ~/.profile ] && source ~/.profile | ||||||
|  | 
 | ||||||
|  | # Prompt | ||||||
|  | function precmd { | ||||||
|  |   # Check previous command output and notify | ||||||
|  |   if [[ $? != 0 && $? != 130 ]];then | ||||||
|  |     echo -e "⚠️ \a" | ||||||
|  |   else | ||||||
|  |     echo -e "\a" | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   if [ "$EUID" -eq 0 ];then | ||||||
|  |     chrome_color="{red}" | ||||||
|  |   else | ||||||
|  |     chrome_color="{magenta}" | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   # Static prefix | ||||||
|  |   prefix="%F$chrome_color┌──[%F{cyan}%n%F$chrome_color@%F{cyan}%m%F$chrome_color]-" | ||||||
|  | 
 | ||||||
|  |   # Calculate extra path | ||||||
|  |   if [[ ${debian_chroot} ]]; then | ||||||
|  |     path_extra="(%F{red}${debian_chroot}%F$chrome_color)-" | ||||||
|  |   elif [[ ${VIRTUAL_ENV} ]]; then | ||||||
|  |     rel_venv=$(realpath $VIRTUAL_ENV --relative-to $PWD --relative-base /home) | ||||||
|  |     path_extra="[%F{blue}${rel_venv}%F$chrome_color]-" | ||||||
|  |   else; | ||||||
|  |     path_extra="" | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   # Static suffix | ||||||
|  |   suffix="(%F{blue}%~%F${chrome_color})"$'\n'"└%F{cyan}%#%F{white} " | ||||||
|  | 
 | ||||||
|  |   PROMPT=$prefix$path_extra$suffix | ||||||
|  |   PS2="%F$chrome_color└%F{cyan}>%F{white} " | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # Aliases | ||||||
|  | alias .=source | ||||||
|  | alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' | ||||||
|  | alias k9=k9s | ||||||
|  | alias rsync="rsync -e 'ssh -o RemoteCommand=none'" | ||||||
|  | alias sudosu="sudo ZDOTDIR=$(dirname ${0:a}) zsh" | ||||||
|  | alias ll='ls -alFh' | ||||||
|  | alias ls="ls --color=auto" | ||||||
|  | alias lsl="ls --color=auto -lah" | ||||||
|  | alias ssh=ssh | ||||||
|  | # Use tmux for local unelevated shells | ||||||
|  | if [ -z "${SUDO_USER}" ] && [ -z "${SSH_CONNECTION}" ] && [ -z "${TERM_PROGRAM}" ]; then | ||||||
|  |   tmux new -A -s local_tmux | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Define a function to use autossh with a custom bashrc | ||||||
|  | function assh() { | ||||||
|  |   remote_file=$(mktemp) | ||||||
|  |   if $(ssh "$@" "cat > ${remote_file}" < ~/.bashrc > /dev/null 2>&1); then | ||||||
|  |     # Successfully copied bashrc to the remote. Source it upon ssh | ||||||
|  |     autossh -t "$@" "bash --rcfile ${remote_file}; rm ${remote_file}" | ||||||
|  |   else | ||||||
|  |     # SSH Config specifies a RemoteCommand; connect normally | ||||||
|  |     autossh "$@" | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | # Use ssh completion for autossh | ||||||
|  | compdef autossh=ssh | ||||||
|  | compdef assh=ssh | ||||||
|  | 
 | ||||||
|  | # Custom dircolors | ||||||
|  | [ -f ~/.dircolors ] && eval "$(dircolors ~/.dircolors)" | ||||||
|  | 
 | ||||||
|  | # Kubernetes Completion | ||||||
|  | which kubectl 1> /dev/null && source <(kubectl completion zsh) | ||||||
|  | which helm 1> /dev/null && source <(helm completion zsh) | ||||||
|  | 
 | ||||||
|  | # doctl completion | ||||||
|  | which doctl 1> /dev/null && source <(doctl completion zsh) | ||||||
|  | 
 | ||||||
|  | # Start in the home directory | ||||||
|  | cd ~ | ||||||
|  | 
 | ||||||
|  | # Ensure zinit is installed | ||||||
|  | ZINIT_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}/zinit/zinit.git" | ||||||
|  | [ ! -d $ZINIT_HOME ] && mkdir -p "$(dirname $ZINIT_HOME)" | ||||||
|  | [ ! -d $ZINIT_HOME/.git ] && git clone https://github.com/zdharma-continuum/zinit.git "$ZINIT_HOME" | ||||||
|  | source "${ZINIT_HOME}/zinit.zsh" | ||||||
|  | 
 | ||||||
|  | # Load zinit plugins | ||||||
|  | zinit snippet OMZP::extract | ||||||
|  | zinit snippet OMZP::colored-man-pages | ||||||
|  | zinit snippet OMZP::encode64 | ||||||
|  | zinit snippet OMZP::gh | ||||||
|  | zinit snippet OMZP::pip | ||||||
|  | zinit snippet OMZP::sudo | ||||||
|  | 
 | ||||||
|  | zinit light zsh-users/zsh-autosuggestions | ||||||
|  | zinit light zsh-users/zsh-syntax-highlighting | ||||||
|  | 
 | ||||||
|  | # Key bindings config | ||||||
|  | KEYTIMEOUT=5 | ||||||
|  | # ^[ for esc; ^I for tab | ||||||
|  | bindkey '^[[Z' autosuggest-accept | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | #### Some notes on `autossh` | ||||||
|  | 
 | ||||||
|  | I have only been using `autossh` for a couple hours at this point, based on internet recommendations | ||||||
|  | that it will do better at resuming with `tmux` (via `tmux-resurrect`). Based on initial testing, it | ||||||
|  | appears to be working but I don't yet know if it is markedly better than plain `ssh`. | ||||||
|  | 
 | ||||||
|  | Not necessarily related to `autossh`, the `assh` function I included allows for connecting to a | ||||||
|  | server and applying my `.bashrc` without making permanent changes to the remote server. This does | ||||||
|  | not apply to connections that use a `RemoteCommand` in the SSH config, which is intentional; I have | ||||||
|  | remotes that run a `tmux` session for remote connections and I wouldn't want to mess with shell | ||||||
|  | configurations when multiple connections will be attaching the same `tmux` session. | ||||||
|  | This also highlights that I still do use `bash` for most of my remote connections, since `bash` | ||||||
|  | is available by default on every Linux distribution I've come across and `zsh` is far less ubiquitous. | ||||||
|  | 
 | ||||||
|  | ### Conclusion | ||||||
|  | 
 | ||||||
|  | I don't think my shell configuration will ever be "done", but I've reached a point where I'm | ||||||
|  | satisfied for now. GNU `stow` has simplified my dotfile management and made it easier to | ||||||
|  | manage more configurations as I add tools to my repertoire. I now have `zsh` looking like | ||||||
|  | my `bash` shell and all of my aliases and `PATH` management better organized to minimize | ||||||
|  | redundant code in shell-specific config files. I've enabled a few zsh plugins that create a | ||||||
|  | more pleasant shell experience with extra text highlighting and shortkeys. | ||||||
|  | 
 | ||||||
|  | I have no immediate plans for what to work on next, though I | ||||||
|  | [still have some ideas](https://blog.mcknight.tech/2025/05/21/nvim/#What-to-do-next). I may continue my search for a good | ||||||
|  | visual file manager in the terminal, or try out Pop!_OS for its window tiling features, | ||||||
|  | although I'll likely wait for their [Cosmic DE](https://system76.com/cosmic/) to graduate to | ||||||
|  | beta and try that. | ||||||
|  | 
 | ||||||
|  | I also still have some [IDE exploration to do](https://blog.mcknight.tech/2025/05/18/Code-Server/#Future-Plans). | ||||||
|  | As I spend more time using `nvim`, I am starting to use it more for coding tasks and it may become my primary "IDE". | ||||||
|  | In any case, I am actively adding to my `nvim` configuration, so I probably have enough thoughts for another post | ||||||
|  | about that. | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue