Ver código fonte

feature: added tmux-sessionizer

Zander Hawke 10 meses atrás
pai
commit
3ad71c4d5e

+ 4 - 6
flake.nix

@@ -64,11 +64,9 @@
     modules = import ./modules;
     overlays = import ./overlays { inherit inputs; };
 
-    packages =
-      lib.eachSystem (import ./packages)
-      // lib.eachSystem (system: {
-        devenv-up = self.devShells.${system}.default.config.procfileScript;
-        devenv-test = self.devShells.${system}.default.config.test;
-      });
+    packages = lib.eachSystem (system: {
+      devenv-up = self.devShells.${system}.default.config.procfileScript;
+      devenv-test = self.devShells.${system}.default.config.test;
+    } // import ./packages { });
   };
 }

+ 24 - 16
home/features/cli/tmux.nix

@@ -2,7 +2,13 @@
 , config
 , lib
 , ...
-}: {
+}:
+let
+  isDarwin = pkgs.stdenv.isDarwin;
+  reattach-to-user-namespace = lib.getExe' pkgs.reattach-to-user-namespace "reattach-to-user-namespace";
+  tmux-sessionizer = lib.getExe config.programs.tmux.sessionizer.package;
+in
+{
   programs.tmux = {
     sensibleOnTop = true;
 
@@ -12,10 +18,14 @@
     escapeTime = 10;
     keyMode = "vi";
     mouse = true;
-    prefix = "C-a";
+    prefix = "C-Space";
     shell = "${lib.getExe config.programs.fish.package}";
     terminal = "tmux-256color";
 
+    sessionizer.enable = true;
+    sessionizer.searchPaths = [ "~/workspace" ];
+    sessionizer.maxDepth = 2;
+
     plugins = with pkgs.tmuxPlugins; [
       tmux-select-pane-no-wrap
       vim-tmux-navigator
@@ -35,14 +45,18 @@
           set -g @kanagawa-show-battery true
           set -g @kanagawa-show-powerline true
           set -g @kanagawa-show-location false
+          set -g @kanagawa-ignore-window-colors true
         '';
       }
     ];
 
     extraConfig = ''
-      # TODO: this should only run on macos
-      # sensible plugin assumes $SHELL is /bin/sh
-      set-option -g default-command "${lib.getExe' pkgs.reattach-to-user-namespace "reattach-to-user-namespace"} -l $SHELL"
+      ${lib.optionalString isDarwin ''
+        # sensible plugin assumes $SHELL is /bin/sh
+        # --- Darwin-Specific Settings (Raw Tmux Commands) ---
+        # This block is only included if the system is Darwin
+        set-option -g default-command "${reattach-to-user-namespace} -l $SHELL"
+      ''}
 
       # split windows on the current path
       unbind %
@@ -56,17 +70,11 @@
       bind -r j resize-pane -D 1
       bind -r k resize-pane -U 1
 
-      # change width of left status bar to allow space for session names
-      set -g status-left-length 30
-
-      # - Put this in your ~/.tmux.conf and replace XXX by your $TERM outside of tmux:
-      set-option -sa terminal-features ',xterm-256color:RGB'
-
-      # default layout
-      # set-hook -g after-new-window 'split-window -v -p 20'
-
-      # transparent please
-      set -g window-style 'fg=colour250,bg=default'
+      # additional keybindings for tmux-sessionizer
+      bind-key -r M-h run-shell "tmux neww ${tmux-sessionizer} -s 0"
+      bind-key -r M-t run-shell "tmux neww ${tmux-sessionizer} -s 1"
+      bind-key -r M-n run-shell "tmux neww ${tmux-sessionizer} -s 2"
+      bind-key -r M-s run-shell "tmux neww ${tmux-sessionizer} -s 3"
     '';
   };
 }

+ 2 - 1
home/features/core.nix

@@ -6,7 +6,8 @@
   imports = [
     # INFO: this is shared between home-manager, nixos, and darwin
     outputs.modules.global.nix-config
-  ];
+  ]
+  ++ (builtins.attrValues outputs.modules.home-manager);
 
   xdg.enable = true;
 

+ 10 - 0
home/features/desktop/ghostty.nix

@@ -10,6 +10,8 @@ let
     rev = "master";
     sha256 = "sha256-i54hTf4AEFTiJb+j5llC5+Xvepj43DiNJSq0vPZCIAg=";
   };
+
+  tmux-sessionizer = lib.getExe config.programs.tmux.sessionizer.package;
 in
 {
   xdg.configFile = {
@@ -52,6 +54,14 @@ in
       window-padding-x = 10;
       window-padding-y = "10,0";
       window-theme = "ghostty";
+
+      keybind = [
+        "ctrl+f=text:\"${tmux-sessionizer}\n\""
+        "alt+h=text:\"${tmux-sessionizer} -s 0\n\""
+        "alt+t=text:\"${tmux-sessionizer} -s 1\n\""
+        "alt+n=text:\"${tmux-sessionizer} -s 2\n\""
+        "alt+s=text:\"${tmux-sessionizer} -s 3\n\""
+      ];
     };
   };
 }

+ 12 - 0
home/features/nvim/default.nix

@@ -1,7 +1,12 @@
 { inputs
+, config
+, lib
 , pkgs
 , ...
 }:
+let
+  tmux-sessionizer = lib.getExe config.programs.tmux.sessionizer.package;
+in
 {
   imports = [
     inputs.nixvim.homeManagerModules.nixvim
@@ -110,6 +115,13 @@
 
       { key = "n"; action = "nzzzv"; mode = "n"; options.desc = "Find next and center cursor"; }
       { key = "N"; action = "Nzzzv"; mode = "n"; options.desc = "Find previous and center cursor"; }
+
+      # tmux-sessionizer
+      { mode = "n"; key = "<C-f>"; action = "<cmd>silent !tmux neww ${tmux-sessionizer}<CR>"; options.desc = "Tmux sessionizer"; }
+      { mode = "n"; key = "<M-h>"; action = "<cmd>silent !tmux neww ${tmux-sessionizer} -s 0<CR>"; options.desc = "Tmux sessionizer with session 0"; }
+      { mode = "n"; key = "<M-t>"; action = "<cmd>silent !tmux neww ${tmux-sessionizer} -s 1<CR>"; options.desc = "Tmux sessionizer with session 1"; }
+      { mode = "n"; key = "<M-n>"; action = "<cmd>silent !tmux neww ${tmux-sessionizer} -s 2<CR>"; options.desc = "Tmux sessionizer with session 2"; }
+      { mode = "n"; key = "<M-s>"; action = "<cmd>silent !tmux neww ${tmux-sessionizer} -s 3<CR>"; options.desc = "Tmux sessionizer with session 3"; }
     ];
   };
 }

+ 8 - 0
hosts/meili/system.nix

@@ -16,6 +16,14 @@
     };
 
     defaults = {
+      # TODO: to make <C-Space> work, we need to disable these
+      # hotkeys, but I don't know if that's possible with nix-darwin
+      # Preferences -> Keyboard -> Keyboard Shortcuts -> Input Sources
+      # "com.apple.symbolichotkeys" = {
+      #   "60" = 0; 
+      #   "61" = 0;
+      # };
+
       SoftwareUpdate.AutomaticallyInstallMacOSUpdates = true;
 
       dock = {

+ 3 - 1
modules/home-manager/default.nix

@@ -1 +1,3 @@
-{ }
+{
+  tmux-sessionizer = import ./tmux-sessionizer.nix;
+}

+ 167 - 0
modules/home-manager/tmux-sessionizer.nix

@@ -0,0 +1,167 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.tmux.sessionizer;
+
+  # Generate the configuration file content
+  configContent = ''
+    # tmux-sessionizer configuration
+    ${optionalString (cfg.searchPaths != []) ''
+    TS_SEARCH_PATHS=(${concatStringsSep " " cfg.searchPaths})
+    ''}
+
+    ${optionalString (cfg.extraSearchPaths != []) ''
+    TS_EXTRA_SEARCH_PATHS=(${concatStringsSep " " (map (entry: 
+      if entry.depth != null 
+      then ''"${entry.path}:${toString entry.depth}"''
+      else ''"${entry.path}"''
+    ) cfg.extraSearchPaths)})
+    ''}
+
+    ${optionalString (cfg.maxDepth != null) ''
+    TS_MAX_DEPTH=${toString cfg.maxDepth}
+    ''}
+
+    ${optionalString (cfg.sessionCommands != []) ''
+    TS_SESSION_COMMANDS=(${concatStringsSep " " (map (cmd: ''"${cmd}"'') cfg.sessionCommands)})
+    ''}
+
+    ${optionalString cfg.logging.enable ''
+    TS_LOG="${cfg.logging.type}"
+    ${optionalString (cfg.logging.file != null) ''
+    TS_LOG_FILE="${cfg.logging.file}"
+    ''}
+    ''}
+
+    ${cfg.extraConfig}
+  '';
+
+in
+{
+  options.programs.tmux.sessionizer = {
+    enable = mkEnableOption "tmux-sessionizer integration";
+
+    package = mkOption {
+      type = types.package;
+      default = pkgs.tmux-sessionizer;
+      description = "The tmux-sessionizer package to use.";
+    };
+
+    searchPaths = mkOption {
+      type = types.listOf types.str;
+      default = [ "~/" "~/personal" "~/personal/dev/env/.config" ];
+      description = ''
+        List of paths to search for directories. These override the default search paths.
+      '';
+      example = [ "~/" "~/projects" "~/work" ];
+    };
+
+    extraSearchPaths = mkOption {
+      type = types.listOf (types.submodule {
+        options = {
+          path = mkOption {
+            type = types.str;
+            description = "Path to search in addition to the main search paths.";
+          };
+          depth = mkOption {
+            type = types.nullOr types.ints.positive;
+            default = null;
+            description = "Maximum depth to search in this path.";
+          };
+        };
+      });
+      default = [ ];
+      description = ''
+        Additional search paths with optional depth specification.
+      '';
+      example = [
+        { path = "~/ghq"; depth = 3; }
+        { path = "~/Git"; depth = 3; }
+        { path = "~/.config"; depth = 2; }
+      ];
+    };
+
+    maxDepth = mkOption {
+      type = types.nullOr types.ints.positive;
+      default = null;
+      description = ''
+        Maximum depth for directory searches. Overrides the default depth of 1.
+      '';
+      example = 2;
+    };
+
+    sessionCommands = mkOption {
+      type = types.listOf types.str;
+      default = [ ];
+      description = ''
+        List of commands that can be executed in tmux sessions using the -s flag.
+        These commands run in windows with indices starting from 69.
+      '';
+      example = [ "nvim" "git status" "npm run dev" ];
+    };
+
+    logging = {
+      enable = mkEnableOption "logging for tmux-sessionizer";
+
+      type = mkOption {
+        type = types.enum [ "echo" "file" "true" ];
+        default = "file";
+        description = ''
+          Type of logging to use:
+          - "echo": Print logs to stdout
+          - "file": Write logs to a file
+          - "true": Enable logging (same as "file")
+        '';
+      };
+
+      file = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = ''
+          Custom log file path. If not specified, defaults to 
+          ~/.local/share/tmux-sessionizer/tmux-sessionizer.logs
+        '';
+        example = "~/.cache/tmux-sessionizer.log";
+      };
+    };
+
+    extraConfig = mkOption {
+      type = types.lines;
+      default = "";
+      description = ''
+        Extra configuration to add to the tmux-sessionizer config file.
+      '';
+      example = ''
+        # Custom configuration
+        export CUSTOM_VAR="value"
+      '';
+    };
+
+    keyBinding = mkOption {
+      type = types.nullOr types.str;
+      default = "f";
+      description = ''
+        Key binding to launch tmux-sessionizer. Set to null to disable.
+      '';
+      example = "f";
+    };
+  };
+
+  config = mkIf (config.programs.tmux.enable && cfg.enable) {
+    # Add the package to home packages
+    home.packages = [ cfg.package ];
+
+    # Create the configuration file
+    xdg.configFile."tmux-sessionizer/tmux-sessionizer.conf" = mkIf (configContent != "") {
+      text = configContent;
+    };
+
+    # Add key binding to tmux configuration
+    programs.tmux.extraConfig = mkIf (cfg.keyBinding != null) ''
+      # tmux-sessionizer key binding
+      bind-key -r ${cfg.keyBinding} run-shell "tmux neww ${lib.getExe cfg.package}"
+    '';
+  };
+}

+ 1 - 0
packages/default.nix

@@ -2,5 +2,6 @@
   hello = pkgs.callPackage ./hello.nix { };
   photo-cli = pkgs.callPackage ./photo-cli.nix { };
   tmux-select-pane-no-wrap = pkgs.callPackage ./tmux-select-pane-no-wrap.nix { };
+  tmux-sessionizer = pkgs.callPackage ./tmux-sessionizer.nix { };
   aerospace-tmux-focus = pkgs.callPackage ./aerospace-tmux-focus.nix { };
 }

+ 39 - 0
packages/tmux-sessionizer.nix

@@ -0,0 +1,39 @@
+{ lib, stdenv, fetchFromGitHub, makeWrapper, bash, tmux, fzf, findutils, gnugrep, procps, coreutils }:
+
+stdenv.mkDerivation rec {
+  pname = "tmux-sessionizer";
+  version = "0.1.0";
+
+  src = fetchFromGitHub {
+    owner = "theprimeagen";
+    repo = pname;
+    rev = "7edf8211e36368c29ffc0d2c6d5d2d350b4d729b";
+    sha256 = "sha256-4QGlq/cLbed7AZhQ3R1yH+44gmgp9gSzbiQft8X5NwU=";
+  };
+
+  nativeBuildInputs = [ makeWrapper ];
+  buildInputs = [ bash ];
+
+  installPhase = ''
+    mkdir -p $out/bin
+    cp tmux-sessionizer $out/bin/tmux-sessionizer
+    chmod +x $out/bin/tmux-sessionizer
+
+    wrapProgram $out/bin/tmux-sessionizer \
+      --prefix PATH : ${lib.makeBinPath [ 
+        tmux
+        fzf
+        findutils
+        gnugrep
+        procps
+        coreutils
+      ]}
+  '';
+
+  meta = with lib; {
+    description = "Tmux session manager with fuzzy finding";
+    license = licenses.mit;
+    platforms = platforms.unix;
+    mainProgram = pname;
+  };
+}