-
-
Save scrubmx/905e2ecf6f45e8c5c4537a5f010cf33b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- Copy file path / selection reference for pasting into AI chats | |
| local function copy_ref(opts) | |
| -- "%" is the current buffer's file name; ":." makes it relative to the cwd | |
| local path = vim.fn.expand("%:.") | |
| -- ref is what ends up in the clipboard; start with just the path | |
| local ref = path | |
| if opts.visual then | |
| -- '< and '> are only set after leaving visual mode, so read the live selection: | |
| -- "v" is the line where visual mode was started (the anchor) | |
| local start_line = vim.fn.line("v") | |
| -- "." is the line the cursor is on now (the moving end of the selection) | |
| local end_line = vim.fn.line(".") | |
| -- if the selection was made upward, swap so start is always the smaller line | |
| if start_line > end_line then | |
| start_line, end_line = end_line, start_line | |
| end | |
| -- append the range, e.g. "lua/config/keymaps.lua:1:23" | |
| ref = path .. ":" .. start_line .. ":" .. end_line | |
| end | |
| -- ask for an optional free-text note on the command line (Enter to skip) | |
| local note = vim.fn.input("Prompt (optional): ") | |
| if note ~= "" then | |
| -- append the note after the ref, separated by a space | |
| ref = ref .. " " .. note | |
| end | |
| -- write ref into the "+" register, which is the system clipboard | |
| vim.fn.setreg("+", ref) | |
| -- show a confirmation message with what was copied | |
| vim.notify("Copied: " .. ref) | |
| end | |
| -- normal mode: copy just the file path | |
| vim.keymap.set("n", "<leader>cp", function() | |
| copy_ref({}) | |
| end, { desc = "Copy file path" }) | |
| -- visual mode: copy the file path plus the selected line range | |
| vim.keymap.set("v", "<leader>cp", function() | |
| copy_ref({ visual = true }) | |
| end, { desc = "Copy file path with line range" }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| PROJECTS_DIR="$HOME/Projects" | |
| # Menu lines: display_label<TAB>session_name<TAB>path<TAB>type | |
| menu="" | |
| # 1. Existing tmux sessions (skip worktree sessions, handled in section 3) | |
| if tmux ls &>/dev/null; then | |
| while IFS= read -r sess; do | |
| [[ "$sess" == *"("* ]] && continue | |
| menu+="[switch] ${sess}"$'\t'"${sess}"$'\t'"$sess"$'\t'"switch"$'\n' | |
| done < <(tmux list-sessions -F '#{session_name}') | |
| fi | |
| # 2. Top-level projects not already a session | |
| for dir in "$PROJECTS_DIR"/*/; do | |
| [ -d "$dir" ] || continue | |
| name=$(basename "$dir") | |
| tmux has-session -t "$name" 2>/dev/null && continue | |
| menu+="[new] ${name}"$'\t'"${name}"$'\t'"${dir}"$'\t'"new"$'\n' | |
| done | |
| # 3. Worktrees inside each project's .worktrees/ | |
| for dir in "$PROJECTS_DIR"/*/; do | |
| { [ -d "$dir/.git" ] || [ -f "$dir/.git" ]; } || continue | |
| (cd "$dir" && git worktree prune 2>/dev/null) || true | |
| wt_dir="${dir}.worktrees" | |
| [ -d "$wt_dir" ] || continue | |
| project_name=$(basename "$dir") | |
| for branch_dir in "$wt_dir"/*/; do | |
| [ -d "$branch_dir" ] || continue | |
| branch_name=$(basename "$branch_dir") | |
| sess_name="${project_name}(${branch_name})" | |
| if tmux has-session -t "$sess_name" 2>/dev/null; then | |
| label="[switch] ${project_name} (${branch_name})" | |
| type="switch" | |
| else | |
| label="[new] ${project_name} (${branch_name}) [worktree]" | |
| type="new" | |
| fi | |
| menu+="${label}"$'\t'"${sess_name}"$'\t'"${branch_dir}"$'\t'"${type}"$'\n' | |
| done | |
| done | |
| [ -z "$menu" ] && exit 0 | |
| selection=$(printf '%s' "$menu" | LC_ALL=C sort -t$'\t' -k4,4r -k1,1 | fzf --height 100% --delimiter=$'\t' --with-nth=1) | |
| [ -z "$selection" ] && exit 0 | |
| sess=$(printf '%s' "$selection" | cut -f2) | |
| path=$(printf '%s' "$selection" | cut -f3) | |
| type=$(printf '%s' "$selection" | cut -f4) | |
| if [ "$type" = "switch" ]; then | |
| if [ -z "${TMUX:-}" ]; then | |
| tmux attach -t "$sess" | |
| else | |
| tmux switch-client -t "$sess" | |
| fi | |
| else | |
| if [ -z "${TMUX:-}" ]; then | |
| tmux new-session -s "$sess" -c "$path" | |
| else | |
| tmux new-session -d -s "$sess" -c "$path" | |
| tmux switch-client -t "$sess" | |
| fi | |
| fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| PROJECTS_DIR="$HOME/Projects" | |
| project_dir=$(find "$PROJECTS_DIR" -mindepth 1 -maxdepth 1 -type d | fzf --height 100% --prompt="Project> ") | |
| [ -z "$project_dir" ] && exit 0 | |
| project_name=$(basename "$project_dir") | |
| cd "$project_dir" | |
| if [ ! -d .git ] && [ ! -f .git ]; then | |
| echo "Not a git repo: $project_dir" | |
| read -r -p "Press enter to close..." | |
| exit 1 | |
| fi | |
| git worktree prune 2>/dev/null || true | |
| branches=$(git branch --format='%(refname:short)') | |
| selection=$(printf '%s\n[new branch]\n' "$branches" | fzf --height 100% --prompt="Branch> ") | |
| [ -z "$selection" ] && exit 0 | |
| if [ "$selection" = "[new branch]" ]; then | |
| read -r -p "New branch name: " branch | |
| [ -z "$branch" ] && exit 0 | |
| is_new=true | |
| else | |
| branch="$selection" | |
| is_new=false | |
| fi | |
| wt_root="$project_dir/.worktrees" | |
| mkdir -p "$wt_root" | |
| if ! grep -qxF '.worktrees/' .gitignore 2>/dev/null; then | |
| echo '.worktrees/' >> .gitignore | |
| fi | |
| wt_path="$wt_root/$branch" | |
| existing_path=$(git worktree list --porcelain | awk -v b="refs/heads/$branch" ' | |
| /^worktree / { path=$2 } | |
| $0 == "branch " b { print path } | |
| ') | |
| if [ -n "$existing_path" ]; then | |
| wt_path="$existing_path" | |
| elif [ -d "$wt_path" ]; then | |
| echo "Directory exists but isn't a registered worktree: $wt_path" | |
| read -r -p "Press enter to close..." | |
| exit 1 | |
| else | |
| if [ "$is_new" = true ]; then | |
| git worktree add "$wt_path" -b "$branch" | |
| else | |
| git worktree add "$wt_path" "$branch" | |
| fi | |
| fi | |
| sanitized_branch=$(echo "$branch" | tr '.:/ ' '----') | |
| sess_name="${project_name}(${sanitized_branch})" | |
| tmux has-session -t "$sess_name" 2>/dev/null || tmux new-session -d -s "$sess_name" -c "$wt_path" | |
| if [ -z "${TMUX:-}" ]; then | |
| tmux attach -t "$sess_name" | |
| else | |
| tmux switch-client -t "$sess_name" | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment