CopyQ icon indicating copy to clipboard operation
CopyQ copied to clipboard

'Cycle Items', but with the ability to paste row 0 and cancel

Open dominicpalmer opened this issue 1 year ago • 2 comments

I'm working on a modification to the Cycle Items command.

Currently the behaviour of Cycle Items is:

  • Focus the window on first keypress
  • Cycle to the next rows on subsequent keypresses
  • Paste on key release release, but only if the user has moved the row at least one time. If the key is released when no subsequent keypresses have been processed, the window stays focused and nothing is pasted.

I made a modification to Cycle Items so that the first row is pasted even if the user hasn't made any subsequent keypresses. But there's an issue, I have no way to 'cancel' pasting if I change my mind after focusing the window. I'm looking for a way to listen for a particular keypress that blocks any paste from happening, whether the selected row has changed or not.

My current implementation is below. I also have an equivalent Cycle Items Backward command that uses const row = rows.length > 0 ? (rows[0] - 1) % length() : 0; instead.

[Command]
Command="
    copyq:
    // Pops up the main window (if the shortcut is pressed once), cycles through items
    // (if the shortcut is pressed again) and pastes selected item when the shortcut
    // is released.
    const selectedRowOption = 'cycleItemsSelectedRow';
    const selectedTabOption = 'cycleItemsSelectedTab';

    if (focused()) {
        // When the window is focused, the command should cycle through the rows
        const sel = ItemSelection().current();
        const rows = sel.rows();
        const row = rows.length > 0 ? (rows[0] + 1) % length() : 0;
        settings(selectedRowOption, row);
        settings(selectedTabOption, selectedTab());
        selectItems(row);
    } else {
        // If the window isn't open, default to selecting the first row
        settings(selectedRowOption, 0);
        selectItems(0);
        show();

        // Then wait at most 20 milliseconds for key release
        while (queryKeyboardModifiers().length > 0) {
            sleep(20);
        }

        const row = settings(selectedRowOption)
        settings(selectedRowOption, row);
        settings(selectedTabOption, selectedTab());
        selectItems(row);

        tab(settings(selectedTabOption));
        select(row);
        hide();
        paste();
    }"
GlobalShortcut="ctrl+alt+y"
Icon=\xf1b8
InMenu=true
IsGlobalShortcut=true
Name=Cycle Items Forward

dominicpalmer avatar Oct 17 '23 22:10 dominicpalmer

You can assign another shortcut to reset the cycle items - e.g. Ctrl+Alt+U:

[Command]
Command="
    copyq:
    // Pops up the main window (if the shortcut is pressed once), cycles through items
    // (if the shortcut is pressed again) and pastes selected item when the shortcut
    // is released.
    const selectedRowOption = 'cycleItemsSelectedRow';
    const selectedTabOption = 'cycleItemsSelectedTab';

    if ( str(data(mimeShortcut)) === 'ctrl+alt+u' ) {
        settings(selectedRowOption, -1);
        selectItems(0)
        selectItems([]);
        hide();
    } else if (focused()) {
        // When the window is focused, the command should cycle through the rows
        const sel = ItemSelection().current();
        const rows = sel.rows();
        const row = rows.length > 0 ? (rows[0] + 1) % length() : 0;
        settings(selectedRowOption, row);
        settings(selectedTabOption, selectedTab());
        selectItems(row);
    } else {
        // If the window isn't open, default to selecting the first row
        settings(selectedRowOption, 0);
        selectItems(0);
        show();

        // Then wait at most 20 milliseconds for key release
        while (queryKeyboardModifiers().length > 0) {
            sleep(20);
        }

        const row = settings(selectedRowOption)
        settings(selectedRowOption, row);
        settings(selectedTabOption, selectedTab());
        selectItems(row);

        tab(settings(selectedTabOption));
        select(row);
        hide();
        paste();
    }"
GlobalShortcut=ctrl+alt+y, ctrl+alt+u
Icon=\xf1b8
InMenu=true
IsGlobalShortcut=true
Name=Cycle Items Forward

hluk avatar Dec 12 '23 12:12 hluk

Works great, thanks!

dominicpalmer avatar Dec 12 '23 19:12 dominicpalmer