JustToThePoint English Website Version
JustToThePoint en español
Colaborate with us

NixOS IV. Shells

You have enemies? Good. That means you’ve stood up for something, sometime in your life, Winston Churchill

Introduction to NixOS

NixOS is a unique, innovative, and powerful Linux distribution that leverages the Nix package manager. Unlike traditional Linux distributions that update packages and system configurations in-place, NixOS uses a purely functional and declarative approach to define the system state, reducing the risk of system breakage.

NixOS is a Linux distribution that uses the Nix package manager to handle packages and system configuration in a purely functional manner. This approach ensures that builds are reproducible and that the system state can be reliably replicated or rolled back.

  1. Immutable Design: It uses a configuration file (usually /etc/nixos/configuration.nix) to define the entire system state, including installed packages, services, and system settings. This makes the system “immutable” in the sense that you don’t manually modify system files. Instead, you declare what you want, and NixOS builds the system from that declaration.
  2. Atomic Updates: When you run nixos-rebuild switch, the system builds a new generation of the environment. If the build is successful, you can switch to this new environment atomically. This means that either the entire update is applied, or nothing changes at all, preventing partial updates that could leave the system in an inconsistent state: sudo nixos-rebuild switch, build and switch to the new generation. If anything goes wrong, you can easily roll back to a previous generation: sudo nix-env ‐‐rollback This rollback is seamless because each generation is stored separately.

    sudo nix-env ‐‐rollback is a command used to revert your system to the previous configuration. It’s a powerful tool for undoing unintended changes or recovering from failed package installations. Before rolling back, consider if there’s a more targeted solution, like uninstalling specific packages or reverting configuration files.

  3. Purely Functional System Configuration: NixOS uses a functional paradigm for configuration. This means that changes are expressed as pure functions from a configuration to a system state, ensuring reproducible builds and easy rollback. NixOS

ZSH with Starship and zoxide

Zsh (Z shell) is a popular alternative to the default Bash shell. It is an extended shell designed for interactive use, known for its extensive customization options, plugin ecosystem, theme support, and advanced features that improve the user experience. Let’s configure it with its own NixOS configuration file: vim /home/nmaximo/dotfiles/shell.nix.

Starship is a minimal, blazing-fast, and infinitely customizable prompt for any shell. It is designed to be fast, portable, and easily configurable.zoxide is a smarter cd command. It remembers which directories you use most frequently, so you can “jump” (z -tab-) to them with a few keystrokes.

{ config, pkgs, ... }:

let
  # Retrieve the username from the home configuration
  username = config.home.username;

  # Define the path to the dotfiles directory
  dotDir = "/home/${username}/dotfiles";
in

{
  programs.zsh = {
    enable = true;  # Enable Zsh as the shell.
    enableCompletion = true; # Enable autocompletion features.
    autosuggestion.enable = true; # Enable autosuggestions for commands.

❯ rm -r < TAB > # It suggest commands and options as you type
-d  -- remove directories as well
-f  -- ignore nonexistent files, never prompt
-i  -- prompt before every removal
-I  -- prompt when removing many files
-v  -- explain what is being done
    syntaxHighlighting.enable = true; # Enable syntax highlighting in the Zsh shell.

    # Configure Zsh plugins
    plugins = [
      {
        # Plugin for searching through Zsh history using substrings
        name = "zsh-history-substring-search";
        src = pkgs.fetchFromGitHub {
          owner = "zsh-users";  # GitHub user or organization
          repo = "zsh-history-substring-search";  # Repository name
          rev = "v1.0.2";  # Specific version to fetch
          sha256 = "0y8va5kc2ram38hbk2cibkk64ffrabfv1sh4xm7pjspsba9n5p1y";  # Integrity check for the fetched source
        };
      }
    ];

    # Set session variables for Zsh
    sessionVariables = {
      # Define the highlight style for autosuggestions
      ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE = "underline";
    };

    # Extra initialization commands to run on Zsh startup
    initExtra = ''
      # A custom function to search using ripgrep (rg) in specified directories
      myripgrep() {
        rg "$@" ~/justtothepoint/content/
        rg "$@" ~/myNewPython/
      }
      # Initialize zoxide for Zsh (zoxide init zsh), replacing 'cd' with zoxide's smarter navigation (--cmd cd)
      eval "$(zoxide init zsh --cmd cd)"
      # Call fastfetch on startup to display system information
      fastfetch
    '';

    # Define shell aliases for common commands
    shellAliases = {
      ll = "exa -a --icons"; # List files with exa, showing all files and icons
      tree = "exa --tree --icons"; # Display directory structure as a tree
      gs = "git status"; # Alias for checking Git status
      reload = "source ~/.zshrc"; # Reload the Zsh configuration
      cat = "bat --paging=never --style=plain"; # Use bat for enhanced cat functionality
      df = "df -h"; # Display disk usage in a human-readable format
      free = "free -m"; # Show memory usage in MB
      rebuild = "sudo nixos-rebuild switch"
      # Applies changes made in your NixOS configuration file and switches to the new configuration immediately without rebooting.
      hyprreload = "hyprctl reload"
      # Reloads the configuration of the Hyprland window manager without needing to restart the entire session.
      nix-clean="nix-collect-garbage -d"
      # Removes old and unused generations of packages, including old system configurations and dependencies that are no longer needed.
      ...
    };
  };

  # Configuration for Starship, a cross-shell prompt
  programs.starship = {
    enable = true;  # Enable Starship prompt

    settings = {
      username = {
        style_user = "blue bold";  # Style for normal user
        style_root = "red bold";  # Style for root user
        format = "[$user]($style) ";  # Format for displaying the username
        disabled = false;  # Ensure this section is not disabled
        show_always = true;  # Always show the username
      };
      hostname = {
        ssh_only = false;  # Show hostname in all contexts, not just in SSH sessions
        ssh_symbol = "🌐 ";  # Symbol to use for SSH sessions
        format = "on [$hostname](bold red) ";  # Format for the hostname
        trim_at = ".local";  # Trim the hostname at .local
        disabled = false;  # Ensure this section is not disabled
      };
    };
  };

  # Configuration for Zoxide, a smart directory jumper
  programs.zoxide = {
    enable = true;  # Enable Zoxide
    enableZshIntegration = true;  # Enable Zsh integration for Zoxide
  };
}

The line eval “$(zoxide init zsh ‐‐cmd cd)” is made of these elements:

  1. zoxide init zsh: it initializes zoxide specifically for the Zsh shell.
  2. ‐‐cmd cd: This flag specifies that you want to replace the default cd command with zoxide’s functionality.
  3. eval “$( … )”. The $( … ) syntax captures the output of the command inside it, which in this case is zoxide init zsh ‐‐cmd cd. The eval command then executes that output (these commands) in your current shell session.

Separating Aliases and Zsh Configuration

A better approach (readability, maintainability) is to keep your aliases in a separate file. This approach is more modular and makes it easier to manage and organize your shell configuration, as you don’t have all settings cluttered in a single, big fat file.

 { config, pkgs, ... }:

let
  username = config.home.username;
  dotDir = "/home/${username}/dotfiles";
  aliases = import ./aliases.nix;
  # We keep track of aliases in a separated file named aliases.nix
in

{
  programs.zsh = {
    enable = true;
    enableCompletion = true;
    [...]
    shellAliases = aliases; # Use imported aliases
    };
}

The aliases.nix file might look like this:

{
      ll = "exa -a --icons"; # List files with exa, showing all files and icons
      tree = "exa --tree --icons"; # Display directory structure as a tree
      gs = "git status"; # Alias for checking Git status
      reload = "source ~/.zshrc"; # Reload the Zsh configuration
      cat = "bat --paging=never --style=plain";  # Use bat for enhanced cat functionality
      [...]
}

Setting Up Kitty

Kitty is a fast, feature-rich terminal emulator optimized for speed and beauty, leveraging the GPU for rendering. It supports multiple tabs and windows, customizable themes, unique capabilities like image preview within the terminal itself, and has built-in Unicode support.

Using NixOS and the Home Manager approach, we can declaratively configure Kitty in a .nix file, ensuring that our configuration is version-controlled, easily reproducible, and consistent across different machines: nvim /home/nmaximo7/dotfiles/kitty.nix:

{ config, pkgs, ... }:

{
  programs.kitty = {
    enable = true;  # Enable the Kitty terminal emulator
    font = { # Configure the font settings for Kitty
      name = "JetBrainsMono Nerd Font";  # Use JetBrains Mono Nerd Font for better programming readability and icons.
      size = 14.0;  # Set a default font size
    };

    # Additional settings for Kitty
    settings = {
      # Confirm before closing the OS window; set to false for no confirmation
      confirm_os_window_close =  -0;

      # Automatically copy selected text to the clipboard
      copy_on_select = true;

      # This allows Kitty to integrate with the system clipboard and primary selection.
      clipboard_control = "write-clipboard read-clipboard write-primary read-primary";
      background_opacity = "0.9"; # Slightly transparent background.
      scrollback_lines = 10000; # Increase scrollback history
      cursor_shape = "beam"; # Set the cursor shape to a vertical beam
      cursor_blink = false; # Disable cursor blinking for a steady visual experience
      url_launcher = "xdg-open"; # Use xdg-open to handle URLs in the default browser
      window_title = "{title} - kitty";  # Customize and dynamic window title
    };
    # Keybindings in Kitty are straightforward: map combinations to actions.
    # These allow quick access to copying, pasting, opening new tabs, and cycling through tabs using intuitive shortcuts.
    keybindings = {
      "ctrl+shift+c" = "copy_to_clipboard";
      "ctrl+shift+v" = "paste_from_clipboard";
      "ctrl+shift+t" = "new_tab";
      "ctrl+shift+w" = "close_tab";
      "ctrl+shift+left" = "previous_tab";
      "ctrl+shift+right" = "next_tab";
      # Bind Ctrl + Shift + +/- to increase/decrease font size.
      "ctrl+shift+plus" = "change_font_size all +2.0";
      "ctrl+shift+minus" = "change_font_size all -2.0";
    };
  };
}

Setting Up Alacritty

Alacritty is a modern, fast, cross-platform, GPU-accelerated terminal emulator. Using NixOS and the Home Manager approach, we can declaratively configure Alacritty in a .nix file: nvim /home/nmaximo7/dotfiles/alacritty.nix

{ config, pkgs, ... }:

{
  programs.alacritty = {
    enable = true; # Enable the Alacritty terminal emulator

    settings = {
      scrolling = {
        history = 1000;  # Set the scrollback history to 1000 lines.
      };
      # Window settings for Alacritty
      window = {
        # It allows Alacritty to dynamically change the window title based on the running command or application.
        dynamic_title = true;
        # Sets the opacity of the Alacritty terminal to 90%.
        # A value of 1.0 would be fully opaque, while a value of 0.0 would be completely transparent.
        # 0.9 is a subtle transparency.
        opacity = 0.9;
        # Padding around the terminal window
        padding = {
          x = 10;  # Set horizontal padding for the window (left and right)
          y = 10;  # Set vertical padding for the window (top and bottom)
        };
      };
      env = {
        WINIT_X11_SCALE_FACTOR = "1.0";
        # This environment variable is used to control the scaling factor of the window when running under X11.
        # A scale factor of 1.0 indicates that the window should be displayed at its native resolution without any scaling.
        # Adjusting this factor can be useful on high-DPI displays, where you might want to scale the interface elements to make them more readable.
      };
      font = { # Configures the font (FiraCode Nerd Font)
        normal = { # Normal font settings
          family = "FiraCode Nerd Font"; # Normal font family
          style = "Regular"; # Normal font style
        };
        bold = { # Bold font settings
          family = "FiraCode Nerd Font"; # Bold font family
          style = "Bold"; # Bold font style
        };
        italic = { # Italic font settings
          family = "FiraCode Nerd Font"; # Italic font family
          style = "Italic"; # Italic font style
        };
        size = 16; # Set the font size
      };

      # Sets up a color scheme
      colors = {
        # Default colors (Drakula) for the terminal
        primary = {
          background = "0x000000";  # Background color
          foreground = "0xEBEBEB";  # Foreground (text) color
        };
        cursor = {
          text   = "0xFF261E";
          cursor = "0xFF261E";
        };
        # Normal colors (used for basic terminal output)
        normal = {
          black =   "0x0D0D0D";  # Black color
          red =     "0xFF301B";  # Red color
          green =   "0xA0E521";  # Green color
          yellow =  "0xFFC620";  # Yellow color
          blue =    "0x1BA6FA";  # Blue color
          magenta = "0x8763B8";  # Magenta color
          cyan =    "0x21DEEF";  # Cyan color
          white =   "0xEBEBEB";  # White color
        };
        # Bright colors (used for bright versions of normal colors)
        bright = {
          black =   "0x6D7070";  # Bright black color
          red =     "0xFF4352";  # Bright red color
          green =   "0xB8E466";  # Bright green color
          yellow =  "0xFFD750";  # Bright yellow color
          blue =    "0x1BA6FA";  # Bright blue color
          magenta = "0xA578EA";  # Bright magenta color
          cyan =    "0x73FBF1";  # Bright cyan color
          white =   "0xFEFEF8";  # Bright white color
        };
      };

      # Keyboard bindings for custom shortcuts
      selection = {
        semantic_escape_chars = ",?`|:\"' ()[]{}<>"; # Characters that are considered special and won't be selected.
        save_to_clipboard = true;  # Automatically copy selected text to the clipboard.
      };
      keyboard.bindings = [
        { key = "C"; mods = "Control"; action = "Copy"; }  # Bind Ctrl+C to copy selected text.
        { key = "V"; mods = "Control"; action = "Paste"; }  # Bind Ctrl+V to paste from clipboard.
        { key = "Q"; mods = "Control"; action = "Quit"; }  # Bind Ctrl+Q to quit Alacritty.
        { key = "N"; mods = "Control"; action = "SpawnNewInstance"; } # Bind Ctrl+N to open a new instance of Alacritty.
        { key = "Plus"; mods = "Control"; action = "IncreaseFontSize"; } # Bind Ctrl + "+" to increase font size.
        { key = "Minus"; mods = "Control"; action = "DecreaseFontSize"; } # Bind Ctrl + "-" to increase font size.
      ];
    };
  };
}
Bitcoin donation

JustToThePoint Copyright © 2011 - 2025 Anawim. ALL RIGHTS RESERVED. Bilingual e-books, articles, and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun. Social Issues, Join us.

This website uses cookies to improve your navigation experience.
By continuing, you are consenting to our use of cookies, in accordance with our Cookies Policy and Website Terms and Conditions of use.