From f0b9f1b04beb800470561c8c81e036e4388ab50a Mon Sep 17 00:00:00 2001 From: linbin <495561397@qq.com> Date: Wed, 1 Oct 2025 04:09:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + cmd.sh | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 .gitignore create mode 100755 cmd.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6c8b771 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +#过滤target文件下生成的编译文件 +script/ +my_commands \ No newline at end of file diff --git a/cmd.sh b/cmd.sh new file mode 100755 index 0000000..ee8dd48 --- /dev/null +++ b/cmd.sh @@ -0,0 +1,204 @@ +#!/bin/bash +# (v9) 支持新格式:名称 # 说明 # 命令 + +interactive_mode() { + local command_file="${1:-/Users/linbin/SynologyDrive/附件/590/cmd/my_commands}" + local initial_query="${2:-}" + + # 使用临时文件来避免复杂的引号转义问题 + local preview_script="/tmp/preview_$$" + cat > "$preview_script" << 'EOF' +#!/bin/bash +command_file="$1" +line_content="$2" + +# trim空格 +name_part=$(echo "$line_content" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') +# 从原文件中获取完整的行 +full_line=$(grep -v "^#" "$command_file" | awk -F'#' -v name="$name_part" '{ + first_field = $1 + gsub(/^[[:space:]]+|[[:space:]]+$/, "", first_field) + if (first_field == name) print $0 +}' | head -1) + +if [ -n "$full_line" ]; then + # 提取三部分:名称、说明、命令 + name=$(echo "$full_line" | awk -F'#' '{print $1}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + desc=$(echo "$full_line" | awk -F'#' '{print $2}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + command_part=$(echo "$full_line" | awk -F'#' '{print $3}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + + # 预览窗口的显示逻辑 + echo "--- 名称 ---" + echo "$name" + echo "" + echo "--- 说明 ---" + echo "$desc" + echo "" + echo "--- 命令 ---" + if [ -f "$command_part" ]; then + echo "$command_part" + echo "" + echo "--- 文件内容 ---" + cat "$command_part" 2>/dev/null || echo "无法读取文件内容" + else + echo "$command_part" + fi +else + echo "未找到对应的命令" +fi +EOF + + chmod +x "$preview_script" + + # --- 模糊搜索 --- + local selected_line + selected_line=$(grep -v "^#" "$command_file" | + # 使用#作为分隔符,让fzf只搜索第一部分(名称) + awk -F'#' '{print $1}' | + sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | + fzf --height=40% --tac \ + --query="$initial_query" \ + --header "↑↓ 选择, Enter 执行, Esc 退出 (或 cmd <快捷词> 直接调用)" \ + --preview "$preview_script '$command_file' {}") + + # 清理临时文件 + rm -f "$preview_script" + + # 如果用户选择了,获取名称部分 + if [ -n "$selected_line" ]; then + selected_line=$(echo "$selected_line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + fi + + if [ -z "$selected_line" ]; then + echo "已取消。" + return 0 + fi + + # 从原文件中重新获取完整命令 + local full_line + full_line=$(grep -v "^#" "$command_file" | awk -F'#' -v name="$selected_line" '{ + first_field = $1 + gsub(/^[[:space:]]+|[[:space:]]+$/, "", first_field) + if (first_field == name) print $0 + }' | head -1) + + # 提取三部分 + local name_part desc_part command_to_run + name_part=$(echo "$full_line" | awk -F'#' '{print $1}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + desc_part=$(echo "$full_line" | awk -F'#' '{print $2}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + command_to_run=$(echo "$full_line" | awk -F'#' '{print $3}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + + echo "▶ $name_part【$desc_part】" + + # 执行逻辑 - 对sh文件使用source执行 + if [ -f "$command_to_run" ]; then + if [[ "$command_to_run" == *.sh ]]; then + source "$command_to_run" + elif [ -x "$command_to_run" ]; then + "$command_to_run" + else + source "$command_to_run" + fi + else + eval "$command_to_run" + fi +} + +cmd() { + local command_file="/Users/linbin/SynologyDrive/附件/590/cmd/my_commands" + + # 检查命令文件是否存在 + if [ ! -f "$command_file" ]; then + echo "命令文件 $command_file 不存在。" + return 1 + fi + + # --- 处理直接调用(支持模糊匹配)--- + # 检查是否提供了参数 (如: cmd lsa) + if [ "$#" -gt 0 ]; then + # 将所有参数用空格连接起来构造精确匹配模式 + local shortcut="" + for arg in "$@"; do + if [ -n "$shortcut" ]; then + shortcut="$shortcut $arg" + else + shortcut="$arg" + fi + done + + # 统一使用模糊匹配逻辑处理所有输入 + # 将所有参数用空格连接起来进行模糊匹配 + local all_args="" + for arg in "$@"; do + if [ -n "$all_args" ]; then + all_args="$all_args $arg" + else + all_args="$arg" + fi + done + + fuzzy_matches=$(grep -v "^#" "$command_file" | awk -v keywords="$all_args" -F'#' ' + { + # 提取第一部分(名称)并trim空格 + name_part = $1 + gsub(/^[[:space:]]+|[[:space:]]+$/, "", name_part) + + # 将关键字按空格分割并检查每个关键字是否都匹配 + n = split(keywords, kw_array, " ") + match_all = 1 + for (i = 1; i <= n; i++) { + # 检查关键字是否为空,并且是否在name_part中存在 + if (kw_array[i] != "" && index(name_part, kw_array[i]) == 0) { + match_all = 0 + break + } + } + if (match_all == 1) print $0 + }') + + if [ -n "$fuzzy_matches" ]; then + # 统计匹配数量 - 只统计非空行 + local match_count + match_count=$(echo "$fuzzy_matches" | grep -c '.') + + if [ "$match_count" -eq 1 ]; then + # 只有一个模糊匹配,直接执行 + local name_part desc_part command_to_run + name_part=$(echo "$fuzzy_matches" | awk -F'#' '{print $1}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + desc_part=$(echo "$fuzzy_matches" | awk -F'#' '{print $2}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + command_to_run=$(echo "$fuzzy_matches" | awk -F'#' '{print $3}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + echo "▶ $name_part【$desc_part】" + + # 执行命令 - 对sh文件使用source执行 + if [ -f "$command_to_run" ]; then + if [[ "$command_to_run" == *.sh ]]; then + source "$command_to_run" + elif [ -x "$command_to_run" ]; then + "$command_to_run" + else + source "$command_to_run" + fi + else + eval "$command_to_run" + fi + return 0 + else + # 多个匹配,进入交互模式让用户选择 + echo "找到 $match_count 个匹配项:" + echo "$fuzzy_matches" | awk -F'#' '{print $1}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | nl -b a + echo "" + + # 直接进入交互模式 + interactive_mode "" "$all_args" + return 0 + fi + else + echo "未找到匹配项,进入交互搜索模式..." + # 进入交互模式 + interactive_mode "" "$all_args" + fi + # 如果没有提供参数,直接进入交互模式 + else + interactive_mode + fi +} \ No newline at end of file