Keep queued typing selections when reopening the menu
This commit is contained in:
1 parent
fbc6daea8b
commit
99f32458d6
5 files changed
+26
-7
No files matched your search
+12
-2
@@ -3,7 +3,7 @@
|
||||
# omarchy:summary=Pick one or multiple options from a menu
|
||||
# omarchy:group=menu
|
||||
# omarchy:name=select
|
||||
# omarchy:args=prompt [option...] [-- --multiple --selected <value> --on-change <command-json> --width <pixels> --maxheight <pixels>]
|
||||
# omarchy:args=prompt [option...] [-- --multiple --selected <value> --on-change <command-json> --change-key <key> --width <pixels> --maxheight <pixels>]
|
||||
# omarchy:examples=omarchy menu select Format jpg png|omarchy-menu-select Resolution 4k 1080p 720p -- --width 400
|
||||
|
||||
# An option may lead with an icon, as "<glyph><TAB><label>", and may trail a
|
||||
@@ -33,6 +33,7 @@ menu_width=""
|
||||
menu_maxheight=""
|
||||
multiple=0
|
||||
on_change="[]"
|
||||
change_key=""
|
||||
selected=()
|
||||
|
||||
while (( $# > 0 )); do
|
||||
@@ -48,6 +49,14 @@ while (( $# > 0 )); do
|
||||
fi
|
||||
on_change="$1"
|
||||
;;
|
||||
--change-key)
|
||||
shift
|
||||
if (( $# == 0 )); then
|
||||
echo "omarchy-menu-select: --change-key requires a value" >&2
|
||||
exit 1
|
||||
fi
|
||||
change_key="$1"
|
||||
;;
|
||||
--multiple)
|
||||
multiple=1
|
||||
;;
|
||||
@@ -110,13 +119,14 @@ payload=$(perl -MEncode=decode -MJSON::PP=encode_json,decode_json -e '
|
||||
multiple => $ARGV[6] ? JSON::PP::true : JSON::PP::false,
|
||||
selected => decode_json($ARGV[7]),
|
||||
onChange => decode_json($ARGV[8]),
|
||||
changeKey => $ARGV[9],
|
||||
selectionFile => decode("UTF-8", $ARGV[2]),
|
||||
doneFile => decode("UTF-8", $ARGV[3])
|
||||
};
|
||||
$payload->{width} = int($ARGV[4]) if length($ARGV[4] // "");
|
||||
$payload->{maxHeight} = int($ARGV[5]) if length($ARGV[5] // "");
|
||||
print encode_json($payload)
|
||||
' "$prompt" "$options_json" "$selection_file" "$done_file" "$menu_width" "$menu_maxheight" "$multiple" "$selected_json" "$on_change")
|
||||
' "$prompt" "$options_json" "$selection_file" "$done_file" "$menu_width" "$menu_maxheight" "$multiple" "$selected_json" "$on_change" "$change_key")
|
||||
|
||||
omarchy-shell shell summon omarchy.menu "$payload" >/dev/null || exit 2
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ def choose(title, catalog, selected, kind, overrides=None):
|
||||
rows = picker_rows(catalog, selected)
|
||||
args = ["omarchy-menu-select", title] + list(rows.values())
|
||||
on_change = ["python", str(setup.ROOT / "default/input-methods/typing.py"), "apply", kind, json.dumps({"catalog": catalog, "overrides": overrides or {}})]
|
||||
args += ["--", "--multiple", "--width", "620", "--maxheight", "650", "--on-change", json.dumps(on_change)]
|
||||
args += ["--", "--multiple", "--width", "620", "--maxheight", "650", "--on-change", json.dumps(on_change), "--change-key", "typing:" + kind]
|
||||
for key in selected:
|
||||
args += ["--selected", rows[key][1:]]
|
||||
result = subprocess.run(args, text=True, capture_output=True)
|
||||
|
||||
@@ -170,3 +170,5 @@ how the pickers behind menu actions (`omarchy-menu-plugin`,
|
||||
Pass `-- --multiple` to `omarchy-menu-select` for a multi-select request. Repeat `--selected <value>` to preselect returned values (labels plus any subtext, without icons). Clicking or pressing Enter toggles an option without closing the menu; Apply returns a JSON array in option order, including `[]` when all choices are deselected. Cancellation still exits 1. Selections survive filtering.
|
||||
|
||||
With `--on-change <JSON command array>`, each toggle runs that command with the proposed selection JSON appended as its final argument, and no Apply row is shown. The checkbox changes only after the command succeeds; a failed command retains the previous selection. Changes persist when the menu closes. The typing selectors use this mode.
|
||||
|
||||
For immediate multi-select requests, `--change-key <key>` identifies the setting being changed across picker openings. The menu keeps queued selections for that key when reopened, so a new toggle cannot discard a change still being saved. Without a key, the command array identifies the setting.
|
||||
@@ -59,6 +59,7 @@ Item {
|
||||
property var dmenuOptions: []
|
||||
property bool dmenuMultiple: false
|
||||
property var dmenuSelected: []
|
||||
property string dmenuChangeKey: ""
|
||||
property var dmenuOnChange: []
|
||||
property string selectionFile: ""
|
||||
property string doneFile: ""
|
||||
@@ -908,7 +909,10 @@ Item {
|
||||
dmenuMultiple = mode === "select" && payload.multiple === true
|
||||
dmenuOnChange = dmenuMultiple && Array.isArray(payload.onChange)
|
||||
&& payload.onChange.every(function(arg) { return typeof arg === "string" }) ? payload.onChange : []
|
||||
dmenuChangeKey = String(payload.changeKey || JSON.stringify(dmenuOnChange))
|
||||
dmenuSelected = MenuModel.dmenuSelections(dmenuOptions, Array.isArray(payload.selected) ? payload.selected : [], dmenuOnChange.length > 0)
|
||||
if (dmenuOnChange.length > 0)
|
||||
dmenuSelected = MenuModel.dmenuSelections(dmenuOptions, selectionProc.requestedSelection(), true)
|
||||
selectionFile = String(payload.selectionFile || "")
|
||||
doneFile = String(payload.doneFile || "")
|
||||
requestActive = !!doneFile
|
||||
@@ -988,22 +992,23 @@ Item {
|
||||
Process {
|
||||
id: selectionProc
|
||||
property int serial: 0
|
||||
property string changeKey: ""
|
||||
property var selected: []
|
||||
property var queue: []
|
||||
property string collected: ""
|
||||
|
||||
function requestedSelection() {
|
||||
for (var i = queue.length - 1; i >= 0; i--) {
|
||||
if (queue[i].serial === root.requestSerial) return queue[i].selected
|
||||
if (queue[i].key === root.dmenuChangeKey) return queue[i].selected
|
||||
}
|
||||
if (running && serial === root.requestSerial) return selected
|
||||
if (running && changeKey === root.dmenuChangeKey) return selected
|
||||
return root.dmenuSelected
|
||||
}
|
||||
|
||||
function enqueue(values) {
|
||||
var selected = MenuModel.dmenuSelections(root.dmenuOptions, values, true)
|
||||
queue = queue.concat([{
|
||||
serial: root.requestSerial, selected: selected,
|
||||
serial: root.requestSerial, key: root.dmenuChangeKey, selected: selected,
|
||||
command: root.dmenuOnChange.concat([JSON.stringify(selected)])
|
||||
}])
|
||||
if (!running) startNext()
|
||||
@@ -1014,6 +1019,7 @@ Item {
|
||||
var change = queue[0]
|
||||
queue = queue.slice(1)
|
||||
serial = change.serial
|
||||
changeKey = change.key
|
||||
selected = change.selected
|
||||
collected = ""
|
||||
command = change.command
|
||||
@@ -1025,7 +1031,7 @@ Item {
|
||||
onStreamFinished: selectionProc.collected = text
|
||||
}
|
||||
onExited: function(exitCode) {
|
||||
if (serial === root.requestSerial && root.dmenuActive) {
|
||||
if (changeKey === root.dmenuChangeKey && root.dmenuActive && root.dmenuOnChange.length > 0) {
|
||||
if (exitCode === 0) {
|
||||
var applied = selected
|
||||
if (collected.trim()) {
|
||||
|
||||
@@ -65,6 +65,7 @@ class TypingSetupTest(unittest.TestCase):
|
||||
args = process.call_args.args[0]
|
||||
self.assertEqual(args[2], "\tKorean")
|
||||
self.assertIn("--multiple", args)
|
||||
self.assertEqual(args[args.index("--change-key") + 1], "typing:input")
|
||||
self.assertEqual(args[-2:], ["--selected", "Korean"])
|
||||
|
||||
def test_apply_rejects_unknown_values(self):
|
||||
|
||||
Reference in new issue
Block a user