_import {arr, merge, isEmpty} from '@amekusa/util.js';
/**
* Returns an object with `key_code` property,
* which can be passed to {@link Rule#remap} as `from` or `to` properties.
* @param {string|string[]|array[]} code - key code(s)
* @param {string|object|string[]} mods - modifiers
* @param {object} [opts] - optional properties
* @return {object} an object like: `{ key_code: ... }`
*/
export function key(code, mods = null, opts = null) {
if (Array.isArray(code)) {
let r = [];
for (let i = 0; i < code.length; i++) {
let I = code[i];
if (Array.isArray(I)) {
r.push(key(
I[0],
I.length > 1 ? I[1] : mods,
I.length > 2 ? I[2] : opts
));
continue;
}
r.push(key(I, mods, opts));
}
return r;
}
let _mods = {
mandatory: [],
optional: []
};
function addModifier(mod) {
mod = mod.trim();
let m = mod.match(/^\((.+?)\)$/); // is '(optional-key)' ?
if (m) _mods.optional.push(m[1]);
else _mods.mandatory.push(mod);
}
// parse 'modifier + keycode' expression
code = (code + '').split('+');
for (let i = 0; i < code.length - 1; i++) addModifier(code[i]);
code = code[code.length - 1].trim();
// parse modifiers
if (mods) {
switch (typeof mods) {
case 'string':
mods.split('+').forEach(addModifier);
break;
case 'object':
if (Array.isArray(mods)) mods.forEach(addModifier);
else {
if (mods.mandatory) _mods.mandatory = _mods.mandatory.concat(arr(mods.mandatory));
if (mods.optional) _mods.optional = _mods.optional.concat(arr(mods.optional));
}
}
}
// format & return
let r = {key_code: code};
if (!isEmpty(_mods.optional)) r.modifiers = {optional: _mods.optional};
if (!isEmpty(_mods.mandatory)) {
if (r.modifiers) r.modifiers.mandatory = _mods.mandatory;
else r.modifiers = _mods.mandatory;
}
return opts ? merge(r, opts, {mergeArrays: true}) : r;
}
/**
* Returns an object with `pointing_button` property, which can be passed to {@link Rule#remap} as `from` or `to` properties.
* @param {string} btn - button name
* - `button1`
* - `button2`
* - `button3`
* - `left` (alias for `button1`)
* - `right` (alias for `button2`)
* - `middle` (alias for `button3`)
* @return {object} an object like: `{ pointing_button: ... }`
*/
export function click(btn) {
let btns = {
left: 'button1',
right: 'button2',
middle: 'button3'
};
return {
pointing_button: btn in btns ? btns[btn] : btn
};
}
/**
* Returns an object with `set_variable` property, which can be passed to {@link Rule#remap} as `to` property.
* @param {string} name - variable name
* @param {string|number} value - value to assign
* @param {object} [opts] - optional properties
* @return {object} an object like: `{ set_variable: { ... } }`
*/
export function set_var(name, value, opts = null) {
let r = {
set_variable: {
name: name,
value: value
}
};
return opts ? Object.assign(r, opts) : r;
}
/**
* Returns an object with `type: 'variable_if'` property, which can be passed to {@link Rule#cond} as a condition.
* @param {string} name - variable name
* @param {string|number} value - value to check
* @return {object} an object like: `{ type: 'variable_if', ... }`
*/
export function if_var(name, value) {
return {
type: 'variable_if',
name: name,
value: value
};
}
/**
* Returns an object with `type: 'variable_unless'` property, which can be passed to {@link Rule#cond} as a condition.
* @param {string} name - variable name
* @param {string|number} value - value to check
* @return {object} an object like: `{ type: 'variable_unless', ... }`
*/
export function unless_var(name, value) {
return {
type: 'variable_unless',
name: name,
value: value
};
}
/**
* Returns an object with `type: 'frontmost_application_if'` property, which can be passed to {@link Rule#cond} as a condition.
* @param {...string} id - application id
* @return {object} an object like: `{ type: 'frontmost_application_if', ... }`
*/
export function if_app(...id) {
return {
type: 'frontmost_application_if',
bundle_identifiers: id
};
}
/**
* Returns an object with `type: 'frontmost_application_unless'` property, which can be passed to {@link Rule#cond} as a condition.
* @param {...string} id - application id
* @return {object} an object like: `{ type: 'frontmost_application_unless', ... }`
*/
export function unless_app(...id) {
return {
type: 'frontmost_application_unless',
bundle_identifiers: id
};
}
/**
* Returns an object with `type: 'input_source_if'` property, which can be passed to {@link Rule#cond} as a condition.
* @param {...string} lang - language code
* @return {object} an object like: `{ type: 'input_source_if', ... }`
*/
export function if_lang(...lang) {
return {
type: 'input_source_if',
input_sources: lang.map(item => {
return {language: item};
})
};
}
/**
* Returns an object with `type: 'input_source_unless'` property, which can be passed to {@link Rule#cond} as a condition.
* @param {...string} lang - language code
* @return {object} an object like: `{ type: 'input_source_unless', ... }`
*/
export function unless_lang(...lang) {
return {
type: 'input_source_unless',
input_sources: lang.map(item => {
return {language: item};
})
};
}