diff --git a/docs/plugins/external-selection-menu/manifest.json b/docs/plugins/external-selection-menu/manifest.json new file mode 100644 index 0000000..f60b934 --- /dev/null +++ b/docs/plugins/external-selection-menu/manifest.json @@ -0,0 +1,18 @@ +{ + "version": "1.0.1", + "manifestVersion": "0.1.0", + "name": "external-selection-menu", + "description": "Use an external menu such as dmenu when prompted to select an entry for auto-type", + "author": { + "name": "Benjamin", + "email": "b3nj4m1n@gmx.net", + "url": "https://github.com/b3nj5m1n" + }, + "resources": { + "js": "rUotQQLQ5DSTeJsvnZHwli7djmWl4gsrHLR9f9ZE3GUImbcnibZICTJrmOQAPMPKUGggT9+ZES6Zd2xVJynkYR9pi9Vh4Ena5jsBRJX43kKTHzTR9ghd1/tRcpy2sh67QBuqtP9YoR2PEZKd4n5fIMv6SP21Dx0BnkFHLi1TOlOlm1qRV13HIpa4Seh9PE9LpLe2BpwGMf0x9NKMIVWtgNokrrvec+ch2tUpz+8X1tL5kF3yl0+zUxUhiI1BH/UfwcdMKWLzIMLyCbK8/DZxUMAXdnQEm4oRg/VkNHWDAy9wsWwcQ/HBBq8pCwoqtiGQwsOuASwL7xL3QY2L7pU3tw==" + }, + "license": "MIT", + "url": "https://github.com/b3nj5m1n/keeweb-external-selection-menu", + "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6ibQ/D4FoT4AK0wQPalHvTLWKUMMa5oRL8jQi4fzRgCam/PhA/gzaaPZ/ttC/sjEBPOxhaQ4A76jWnMJ7E/f1zfHbPvpB+tvDGDKNHpjrldTOQIYcz4uU+y+qsFWSv0bJjDORxHbfQT3xXJ09wT7vjSXyD7ERuUIvm6jr+L5v168EZ8iscPnM3pUKp2wYJDR4AGWJ+WD7IHzDZZ8cUvMSsP7IPvVhSfHZZpkfakswgQ1kNWRNcFtmlxcR62xOiLIeJiAix1LXkkDJCT2MjH2XgCG3PNDSChPKr6rui90Wa5O5iGqn0bx6KAyxuP7/adM8ZzAW0HvDPGIV1RfevNpuQIDAQAB", + "desktop": true +} \ No newline at end of file diff --git a/docs/plugins/external-selection-menu/plugin.js b/docs/plugins/external-selection-menu/plugin.js new file mode 100644 index 0000000..2b3815a --- /dev/null +++ b/docs/plugins/external-selection-menu/plugin.js @@ -0,0 +1,106 @@ +/** + * KeeWeb plugin: external-selection-menu + * @author Benjamin + * @license MIT + */ + +const Logger = require('util/logger'); +const logger = new Logger.Logger('external-selection-menu'); + +const launcher = require('comp/launcher'); +const Launcher = launcher.Launcher; + +const autoType = require('auto-type/index.js'); +const originalProcessEventWithFilter = autoType.AutoType.processEventWithFilter; /* Preserve original method for uninstall */ + +const selectView = require('views/auto-type/auto-type-select-view.js'); +const AutoTypeSelectView = selectView.AutoTypeSelectView; + +// Function to pad number with leading zeroes +function pad(n, width, z) { + z = z || '0'; + n = n + ''; + return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; +} + +// Command to execute +let cmd = 'dmenu'; +let args = ['-c']; + +// Overwrite processEventWithFilter function +autoType.AutoType.processEventWithFilter = function (evt) { + // Default code for when a matching entry can be found without having to select one; disabled for now + // + // const initEntries = evt.filter.getEntries(); if (initEntries.length === 1 && AppSettingsModel.directAutotype) { + // this.hideWindow(() => { + // autoType.AutoType.runAndHandleResult({ entry: initEntries[0] }, evt.windowInfo.id); + // }); + // return; + // } + // Custom code replacing the selection menu + // + evt.filter.ignoreWindowInfo = true; /* Set filter to ignore windowInfo */ + this.selectEntryView = new AutoTypeSelectView({ filter: evt.filter }); /* Create new AutoTypeSelectView to gain access to entries */ + const entries = this.selectEntryView.model.filter.getEntries(); /* Get all entries from selectEntryView */ + this.selectEntryView = null; /* Remove selectEntryView */ + + this.data = ''; /* Init data string, will be used as stdin for the command */ + + // Loop over all entries and add information from that entry to the data string + for (let i = 0, len = entries.length; i < len; i++) { + this.data += pad([i], 3) + ': ' + entries[i].title + ' - ' + entries[i].user + ' - ' + entries[i].url + ' - ' + entries[i].tags + '\n'; + } + // Spawn a new command (dmenu) + Launcher.spawn({ + cmd: cmd, + args: args, + data: this.data, + complete: (err, stdout, code) => { + if (err) { + return; + } + // Callback function + const cb = function () { + const i = parseInt(stdout.split(':')[0], 10); /* From selection, get everything up to the first : (This will be the index of the entry) and parse it to an int to remove leading zeroes */ + autoType.AutoType.runAndHandleResult({ entry: entries[i] }, evt.windowInfo.id); /* runAndHandleResult with the selected entry */ + }; + cb(err, stdout, code); + } + }); +}; + +module.exports.getSettings = function() { + return [ + { + name: 'External menu command', + label: 'Command to be run every time the selection menu comes up', + type: 'text', + maxlength: 50, + placeholder: '', + value: 'dmenu' + }, + { + name: 'External menu command arguments', + label: 'Arguments to give to the command', + type: 'text', + maxlength: 50, + placeholder: '', + value: '-c' + } + ]; +}; + +module.exports.setSettings = function(changes) { + if (changes['External menu command']) { + cmd = changes['External menu command']; + } + if (changes['External menu command arguments']) { + args = changes['External menu command arguments'].split(' '); + } + logger.info('Menu command changed to: ' + cmd + ' ' + args); +}; + +module.exports.uninstall = function() { + delete autoType.AutoType.processEventWithFilter; + autoType.AutoType.processEventWithFilter = originalProcessEventWithFilter; +};