Incrementing/resetting variable based on selected text value

I would like a single shortcut to do the following:

  1. If text is selected, interpret it as an integer and assign the parsed number to a variable.
  2. If no text is selected, take the value of the variable, increment it, set the variable to the new value, and insert the text at the caret.
  3. If no text is selected and the variable is empty, initialize it with 1 and then insert that.

I thought this would do what I've described above, but it's not working. I have this "Transform & Replace Selection With JS" code:

(async (selection)=> {
    var out = selection;

    if (selection === undefined)
    {
        let variableName = 'incrementing_value';
        let variable = await callBTT('get_number_variable', {variable_name: variableName});

        if (variable === undefined)
        {
            await callBTT('set_number_variable', {variable_name: variableName, to: 1});
            variable = 1;
        } else {
            variable += 1;
            await callBTT('set_number_variable', {variable_name: variableName, to:variable});
        }
        out = `${variable}`;
    } else {
        let newVar = parseInt(selection);
        await callBTT('set_number_variable', {variable_name: variableName, to:newVar});
    }

    return out;
})();

I know the shortcut is working because I can replace all of this with the default toUpperCase() code and it successfully modifies the selected text. But when I select an integer and run the shortcut, nothing happens. And when I select nothing and run the shortcut, I get an error beep.

Is this the correct sort of action for what I want to achieve? I based it off answers to several prevoius questions, including:

I also tried using a Real JavaScript action, but was unable to get await callBTT('get_string_variable', {variableName: 'selected_text'}); working.

I'm using BTT 4.155 on Sonoma 14.6.1.

Thanks in advance!

Hmm, had a look at the Release Notes and discovered this:

BetterTouchTool >= 4.460 (March, 11, 2024)

  • macOS 14.4 fix: any BTT action that worked on the currently selected text would fail on macOS Sonoma 14.4. This should be resolved. For example the "Transform Selected Text With ChatGPT" or "Transform Selected Text With Java Script" actions.

That seemed to apply to me, so I bought a new license and upgraded. Now using 4.684.

Unfortunately, the problem remains. So I guess that wasn't the problem, or at least not the whole problem.

Got this mostly working, finally, with a Real JavaScript action:

async function storeOrIncrementVar() {
    let variableName = 'incrementing_value';
    let selectedText = await get_string_variable({ variable_name: 'selected_text' });

    if (selectedText === '') {
        var variable = await callBTT('get_number_variable', { variable_name: variableName });

        if (variable === undefined) {
            variable = 1;
        } else {
            variable += 1;
        }

        await callBTT('set_number_variable', { variable_name: variableName, to: variable });
        BTTActions.pasteString(`${variable}`);
    } else {
        let newVar = parseInt(selectedText);
        await callBTT('set_number_variable', { variable_name: variableName, to: newVar });
    }
	
    returnToBTT('');
}

The annoying thing, though, is that I'm still getting an error beep when there is no selected text and I press the shortcut. Would love to find a way to silence that.

Any idea why my real JavaScript action would be triggering an error beep with every execution? :confused:

In order to get the selected text, BTT needs to send the cmd+c shortcut to the system. If that shortcut is not applicable in the current context it will produce a beep unfortunately.

Ah, I see. Is it possible to just get the length of the selection without executing Cmd-C? Otherwise, I guess the solution is a separate command to copy text and set the variable.

unfortunately I don’t know any good way. Some apps support getting the length of selected text via apple script, but unfortunately not all

Understood. So here's the final solution I came to: two different commands, one to update the variable, and one to increment and insert it.

async function incrementAndPasteVar() {
    var variable = await callBTT('get_number_variable', { variable_name: 'STORED_NUMBER' });

    if (variable === undefined) {
        variable = 1;
    } else {
        variable += 1;
    }

    await callBTT('set_number_variable', { variable_name: 'STORED_NUMBER', to: variable });
    await paste_text({ text: `${variable}`, insert_by_pasting: false });
	
    returnToBTT('');
}

async function storeVar() {
    let selectedText = await get_string_variable({ variable_name: 'selected_text' });

    if (selectedText !== '') {
        let newVar = parseInt(selectedText);
        await callBTT('set_number_variable', { variable_name: 'STORED_NUMBER', to: newVar });
    }

    returnToBTT('');
}