From 6756596d8f467843f8f97fd178eb3130a15a6ffa Mon Sep 17 00:00:00 2001 From: CalebJohn Date: Wed, 17 Apr 2024 14:59:35 -0600 Subject: [PATCH] Support checking on selections Adds new right-click options to uncheck or check all when the selection spans multiple lines --- src/clickHandlers.ts | 38 +++++++++++++++++++++++++++++++---- src/index.ts | 48 +++++++++++++++++++++++++++++++++++++++----- src/richMarkdown.ts | 10 ++++++++- 3 files changed, 86 insertions(+), 10 deletions(-) diff --git a/src/clickHandlers.ts b/src/clickHandlers.ts index 45f0fe6..c487559 100644 --- a/src/clickHandlers.ts +++ b/src/clickHandlers.ts @@ -63,7 +63,7 @@ export function clickAt(cm: any, coord: any) { } if (settings.checkbox) { - if (toggleCheckbox(cm, coord)) + if (toggleCheckbox(cm, coord, '')) return null; } @@ -182,15 +182,22 @@ function getCheckboxInfo(cm:any, coord:any) { return { match, lineText, line }; } -export function toggleCheckbox(cm: any, coord: any) { +function toggleCheckboxInner(cm: any, coord: any, replacement: string) { const cursor = cm.getCursor(); - const { match, line, lineText } = getCheckboxInfo(cm, coord); + const info = getCheckboxInfo(cm, coord); + + if (!info) return false; + + const { match, line, lineText } = info; let from = lineText.indexOf(match[3]) let to = from + match[3].length; - const replace = match[3][1] === ' ' ? '[x]' : '[ ]'; + let replace = replacement; + if (replace === '') { + replace = match[3][1] === ' ' ? '[x]' : '[ ]'; + } cm.replaceRange(replace, { ch: from, line }, { ch: to, line }, '+input'); // This isn't exactly needed, but the replaceRange does move the cursor @@ -200,3 +207,26 @@ export function toggleCheckbox(cm: any, coord: any) { return true; } +export function toggleCheckbox(cm: any, coord: any, replacement: string) { + if (!cm.somethingSelected()) { + return toggleCheckboxInner(cm, coord, replacement); + } + + for (let selection of cm.listSelections()) { + let start, end; + if (selection.anchor.line > selection.head.line) { + start = selection.head; + end = selection.anchor; + } else { + start = selection.anchor; + end = selection.head; + } + + for (let i = start.line; i <= end.line; i++) { + toggleCheckboxInner(cm, {line: i, ch: 0}, replacement); + } + } + + return true; +} + diff --git a/src/index.ts b/src/index.ts index f09bdcf..bd34175 100644 --- a/src/index.ts +++ b/src/index.ts @@ -56,6 +56,24 @@ joplin.plugins.register({ }); }, }); + await joplin.commands.register({ + name: 'editor.richMarkdown.checkCheckbox', + execute: async (coord: any) => { + await joplin.commands.execute('editor.execCommand', { + name: 'checkCheckbox', + args: [coord], + }); + }, + }); + await joplin.commands.register({ + name: 'editor.richMarkdown.uncheckCheckbox', + execute: async (coord: any) => { + await joplin.commands.execute('editor.execCommand', { + name: 'uncheckCheckbox', + args: [coord], + }); + }, + }); await joplin.commands.register({ name: 'editor.richMarkdown.copyPathToClipboard', @@ -68,6 +86,7 @@ joplin.plugins.register({ const textItems: TextItem[] = await joplin.commands.execute('editor.execCommand', { name: 'getItemsUnderCursor', }); + const selection = await joplin.commands.execute('selectedText'); if (!textItems.length) return object; @@ -104,11 +123,30 @@ joplin.plugins.register({ commandArgs: [urlToCopy], }); } else if (textItem.type === TextItemType.Checkbox) { - newItems.push({ - label: 'Toggle checkbox', - commandName: 'editor.richMarkdown.toggleCheckbox', - commandArgs: [textItem.coord], - }); + const newlineRegex = /[\r\n]/; + if (newlineRegex.test(selection)) { + newItems.push({ + label: 'Toggle all', + commandName: 'editor.richMarkdown.toggleCheckbox', + commandArgs: [textItem.coord], + }); + newItems.push({ + label: 'Uncheck all', + commandName: 'editor.richMarkdown.uncheckCheckbox', + commandArgs: [textItem.coord], + }); + newItems.push({ + label: 'Check all', + commandName: 'editor.richMarkdown.checkCheckbox', + commandArgs: [textItem.coord], + }); + } else { + newItems.push({ + label: 'Toggle checkbox', + commandName: 'editor.richMarkdown.toggleCheckbox', + commandArgs: [textItem.coord], + }); + } } } diff --git a/src/richMarkdown.ts b/src/richMarkdown.ts index 995802b..5a8548e 100644 --- a/src/richMarkdown.ts +++ b/src/richMarkdown.ts @@ -91,7 +91,15 @@ module.exports = { }); CodeMirror.defineExtension('toggleCheckbox', function(coord:any) { - ClickHandlers.toggleCheckbox(this, coord); + ClickHandlers.toggleCheckbox(this, coord, ''); + }); + + CodeMirror.defineExtension('checkCheckbox', function(coord:any) { + ClickHandlers.toggleCheckbox(this, coord, '[x]'); + }); + + CodeMirror.defineExtension('uncheckCheckbox', function(coord:any) { + ClickHandlers.toggleCheckbox(this, coord, '[ ]'); }); CodeMirror.defineExtension('refreshResource', function(resourceId:string) {