[PATCH] Extend --clip/--qrcode to support copying/displaying non-password fields

Dan Crawford dnlcrwfrd at gmail.com
Wed Apr 24 18:15:03 UTC 2024


Given a passfile of the format

<password>
field1: key1
field2: key2

one can copy the password with -c1, the second line with -c2, and so on.
Copying the second line simply copies the whole line, including the
`field: ` section. This renders copying these lines essentially
pointless, as the values cannot be pasted as-is into some field.
For example, I might have a password for some website, and also an API
token, in the same passfile. I want an easy way to copy both values.

This patch extends --clip (and incidentally, --qrcode) to support either
copying arbitrary lines (with the existing syntax), or copying the value
of some field. Given the above passfile, --clip="field1" or -c"field1"
will add `key1` to the clipboard. 

Let me know if there are any comments on the implementation or similar.


diff --git a/src/password-store.sh b/src/password-store.sh
index 22e818f..5b3e940 100755
--- a/src/password-store.sh
+++ b/src/password-store.sh
@@ -365,6 +364,16 @@ cmd_init() {
 	git_add_file "$PREFIX/$id_path" "Reencrypt password store using new GPG id ${id_print%, }${id_path:+ ($id_path)}."
 }
 
+trim() {
+	# https://stackoverflow.com/a/3352015
+	local var="$*"
+	# remove leading whitespace characters
+	var="${var#"${var%%[![:space:]]*}"}"
+	# remove trailing whitespace characters
+	var="${var%"${var##*[![:space:]]}"}"
+	printf '%s' "$var"
+}
+
 cmd_show() {
 	local opts selected_line clip=0 qrcode=0
 	opts="$($GETOPT -o q::c:: -l qrcode::,clip:: -n "$PROGRAM" -- "$@")"
@@ -387,9 +396,27 @@ cmd_show() {
 			pass="$($GPG -d "${GPG_OPTS[@]}" "$passfile" | $BASE64)" || exit $?
 			echo "$pass" | $BASE64 -d
 		else
-			[[ $selected_line =~ ^[0-9]+$ ]] || die "Clip location '$selected_line' is not a number."
-			pass="$($GPG -d "${GPG_OPTS[@]}" "$passfile" | tail -n +${selected_line} | head -n 1)" || exit $?
-			[[ -n $pass ]] || die "There is no password to put on the clipboard at line ${selected_line}."
+			if [[ "$selected_line" =~ ^[0-9]+$ ]]; then
+				pass="$($GPG -d "${GPG_OPTS[@]}" "$passfile" | tail -n +${selected_line} | head -n 1)" || exit $?
+				[[ -n $pass ]] || die "There is no password to put on the clipboard at line ${selected_line}."
+			else
+				pass="$($GPG -d "${GPG_OPTS[@]}" "$passfile")"
+				mapfile -t -s 1 <<<"$pass"
+				found=false
+				for value in "${MAPFILE[@]}"; do
+					mapfile -td ": " kv <<<"$value"
+					key=$(trim "${kv[0]}")
+					value=$(trim "${kv[1]}")
+					if [ "$key" == "$selected_line" ]; then
+						pass="$value"
+						found=true
+					fi
+				done
+				if [ $found = false ]; then
+					die "Selected clip '$selected_line' not in passfile."
+				fi
+			fi
+
 			if [[ $clip -eq 1 ]]; then
 				clip "$pass" "$path"
 			elif [[ $qrcode -eq 1 ]]; then


More information about the Password-Store mailing list