From e7a20821c67fcc41e880dba62984f83ac036eb50 Mon Sep 17 00:00:00 2001 From: Oz Agent Date: Wed, 1 Apr 2026 15:50:37 +0000 Subject: [PATCH] Add pass (password-store) entry completion generator Add a Rust generator for the pass command that lists entries and directories from the password store (~/.password-store or $PASSWORD_STORE_DIR). Replace the JavaScript script/postProcess generators in pass.json with generatorName references to the new Rust generators. Two generators are provided: - entries: lists .gpg files (password entries) with the .gpg extension stripped - directories: lists subdirectories for the ls/list subcommand Fixes: https://github.com/warpdotdev/Warp/issues/2067 Co-Authored-By: Oz --- command-signatures/json/pass.json | 35 ++++---------------- command-signatures/src/generators/mod.rs | 2 ++ command-signatures/src/generators/pass.rs | 40 +++++++++++++++++++++++ 3 files changed, 49 insertions(+), 28 deletions(-) create mode 100644 command-signatures/src/generators/pass.rs diff --git a/command-signatures/json/pass.json b/command-signatures/json/pass.json index 5e1bc4d0..43bf5b61 100644 --- a/command-signatures/json/pass.json +++ b/command-signatures/json/pass.json @@ -4,10 +4,7 @@ "args": { "name": "pass-name", "description": "The password you want to show", - "generators": { - "script": "function(){return\"grep -r -l '' $HOME/.password-store --exclude-dir=.git\"}", - "postProcess": "_NuFrRa_s=>s.split(`\n`).map(o=>({name:o.split(\".password-store/\").pop().replace(\".gpg\",\"\"),icon:\"\\u{1F510}\"}))" - } + "generatorName": "entries" }, "options": [ { @@ -102,10 +99,7 @@ { "name": "old-path", "description": "The old password name or directory", - "generators": { - "script": "function(){return\"grep -r -l '' $HOME/.password-store --exclude-dir=.git\"}", - "postProcess": "_NuFrRa_s=>s.split(`\n`).map(o=>({name:o.split(\".password-store/\").pop().replace(\".gpg\",\"\"),icon:\"\\u{1F510}\"}))" - } + "generatorName": "entries" }, { "name": "new-path", @@ -129,10 +123,7 @@ { "name": "old-path", "description": "The old password name or directory", - "generators": { - "script": "function(){return\"grep -r -l '' $HOME/.password-store --exclude-dir=.git\"}", - "postProcess": "_NuFrRa_s=>s.split(`\n`).map(o=>({name:o.split(\".password-store/\").pop().replace(\".gpg\",\"\"),icon:\"\\u{1F510}\"}))" - } + "generatorName": "entries" }, { "name": "new-path", @@ -155,10 +146,7 @@ "args": { "name": "pass-name", "description": "The password name", - "generators": { - "script": "function(){return\"grep -r -l '' $HOME/.password-store --exclude-dir=.git\"}", - "postProcess": "_NuFrRa_s=>s.split(`\n`).map(o=>({name:o.split(\".password-store/\").pop().replace(\".gpg\",\"\"),icon:\"\\u{1F510}\"}))" - } + "generatorName": "entries" }, "options": [ { @@ -232,10 +220,7 @@ "name": "password sub-directory", "description": "The password sub directory you want to list", "isOptional": true, - "generators": { - "script": "function(){return\"ls -dR1a $HOME/.password-store/*/\"}", - "postProcess": "_NuFrRa_s=>s.split(`\n`).map(o=>({name:o.split(\".password-store/\").pop(),icon:\"\\u{1F4C1}\"}))" - } + "generatorName": "directories" } }, { @@ -252,10 +237,7 @@ "args": { "name": "pass-name", "description": "The password you want to show", - "generators": { - "script": "function(){return\"grep -r -l '' $HOME/.password-store --exclude-dir=.git\"}", - "postProcess": "_NuFrRa_s=>s.split(`\n`).map(o=>({name:o.split(\".password-store/\").pop().replace(\".gpg\",\"\"),icon:\"\\u{1F510}\"}))" - } + "generatorName": "entries" }, "options": [ { @@ -280,10 +262,7 @@ "args": { "name": "pass-name", "description": "The password you want to edit", - "generators": { - "script": "function(){return\"grep -r -l '' $HOME/.password-store --exclude-dir=.git\"}", - "postProcess": "_NuFrRa_s=>s.split(`\n`).map(o=>({name:o.split(\".password-store/\").pop().replace(\".gpg\",\"\"),icon:\"\\u{1F510}\"}))" - } + "generatorName": "entries" } }, { diff --git a/command-signatures/src/generators/mod.rs b/command-signatures/src/generators/mod.rs index b6100244..5c1b9eb6 100644 --- a/command-signatures/src/generators/mod.rs +++ b/command-signatures/src/generators/mod.rs @@ -35,6 +35,7 @@ mod node; mod npm; mod nx; mod pacman; +mod pass; mod phpunit_watcher; mod pip; mod powershell; @@ -74,6 +75,7 @@ pub fn dynamic_command_signature_data() -> HashMap CommandSignatureGenerators { + // The shell commands cd into the password store directory so that `find` + // outputs paths relative to it. sed then strips the leading `./` and, + // for entries, the trailing `.gpg` extension. + CommandSignatureGenerators::new("pass") + .add_generator( + "entries", + Generator::script( + CommandBuilder::single_command( + "(cd \"${PASSWORD_STORE_DIR:-$HOME/.password-store}\" 2>/dev/null && find . -name '*.gpg' ! -path '*/.git/*' | sed 's|^\\./||;s|\\.gpg$||' | sort)", + ), + |output| { + output + .lines() + .filter(|line| !line.is_empty()) + .map(|line| Suggestion::with_description(line.trim(), "Password entry")) + .collect_unordered_results() + }, + ), + ) + .add_generator( + "directories", + Generator::script( + CommandBuilder::single_command( + "(cd \"${PASSWORD_STORE_DIR:-$HOME/.password-store}\" 2>/dev/null && find . -type d ! -name '.git' ! -path '*/.git/*' -mindepth 1 | sed 's|^\\./||' | sort)", + ), + |output| { + output + .lines() + .filter(|line| !line.is_empty()) + .map(|line| Suggestion::with_description(line.trim(), "Password directory")) + .collect_unordered_results() + }, + ), + ) +}