1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Merge branch 'dev' of github.com:laurent22/joplin into dev

This commit is contained in:
Laurent Cozic 2020-12-19 22:17:48 +00:00
commit 1aebcbb27c
10 changed files with 232 additions and 64 deletions

View File

@ -152,7 +152,7 @@ describe('services_KeymapService', () => {
{ command: 'newNote', accelerator: 'Ctrl+Alt+Shift+N' },
{ command: 'synchronize', accelerator: 'F15' },
{ command: 'textBold', accelerator: 'Shift+F5' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' },
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
{ command: 'print', accelerator: null /* Disabled */ },
{ command: 'focusElementNoteTitle', accelerator: 'Ctrl+Alt+Shift+T' },
@ -174,7 +174,7 @@ describe('services_KeymapService', () => {
{ command: 'newNote', accelerator: 'Ctrl+Alt+Shift+N' },
{ command: 'synchronize', accelerator: null /* Disabled */ },
{ command: 'textBold', accelerator: 'Shift+F5' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' },
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
{ command: 'print', accelerator: 'Alt+P' },
{ command: 'focusElementNoteTitle', accelerator: 'Ctrl+Alt+Shift+T' },
@ -222,7 +222,7 @@ describe('services_KeymapService', () => {
{ command: 'newNote', accelerator: 'Ctrl+Alt+Shift+N' },
{ command: 'synchronize', accelerator: 'Ctrl+F11' },
{ command: 'textBold', accelerator: 'Shift+F5' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' },
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
{ command: 'print', accelerator: 'Alt+P' },
{ command: 'help', accelerator: null /* Disabled */ },
@ -243,7 +243,7 @@ describe('services_KeymapService', () => {
const customKeymaps = [
[
{ commmmmand: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' },
{ command: 'print', accelerator: 'Alt+P' },
],
[
@ -252,13 +252,13 @@ describe('services_KeymapService', () => {
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
],
[
{ command: 'showLocalSearch', accel: 'Ctrl+Alt+S' },
{ command: 'showLocalSearch', accel: 'Ctrl+Alt+L' },
{ command: 'print', accelerator: 'Alt+P' },
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
],
[
{ command: 'print' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' },
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
],
];
@ -311,12 +311,12 @@ describe('services_KeymapService', () => {
const customKeymaps_Linux = [
[
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' /* Duplicate */ },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' /* Duplicate */ },
{ command: 'print', accelerator: 'Alt+P' },
{ command: 'gotoAnything', accelerator: 'Ctrl+Alt+S' /* Duplicate */ },
{ command: 'gotoAnything', accelerator: 'Ctrl+Alt+L' /* Duplicate */ },
],
[
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' },
{ command: 'print', accelerator: 'Ctrl+P' /* Default of gotoAnything */ },
{ command: 'focusElementNoteTitle', accelerator: 'Ctrl+Alt+Shift+J' },
],

View File

@ -4,12 +4,11 @@
function plugin(CodeMirror) {
// This is a dummy command that is registered with codemirror.
// Once created here it can be called by any other codemirror command
// using cm.execCommand(stringName) or by binding the command to a key in the keymap
// using cm.execCommand(stringName) or register a joplin command called 'editor.printSomething'
// through the joplin.commands api
CodeMirror.commands.printSomething = function(cm) {
console.log("Something");
}
// Here we manually bind the keys using the codemirror keymap
CodeMirror.keyMap.basic["Ctrl-U"] = "printSomething"
}
module.exports = {

View File

@ -509,6 +509,9 @@ function useMenu(props: Props) {
menuItemDic.textPaste,
menuItemDic.textSelectAll,
separator(),
menuItemDic['editor.undo'],
menuItemDic['editor.redo'],
separator(),
menuItemDic.textBold,
menuItemDic.textItalic,
menuItemDic.textLink,
@ -517,6 +520,14 @@ function useMenu(props: Props) {
menuItemDic.insertDateTime,
menuItemDic.attachFile,
separator(),
menuItemDic['editor.deleteLine'],
menuItemDic['editor.toggleComment'],
menuItemDic['editor.sortSelectedLines'],
menuItemDic['editor.indentLess'],
menuItemDic['editor.indentMore'],
menuItemDic['editor.swapLineDown'],
menuItemDic['editor.swapLineUp'],
separator(),
menuItemDic.focusSearch,
menuItemDic.showLocalSearch,
],

View File

@ -164,6 +164,18 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
replaceSelection: (value: any) => {
return editorRef.current.replaceSelection(value);
},
textCopy: () => {
editorCopyText();
},
textCut: () => {
editorCutText();
},
textPaste: () => {
editorPaste();
},
textSelectAll: () => {
return editorRef.current.execCommand('selectAll');
},
textBold: () => wrapSelectionWithStrings('**', '**', _('strong text')),
textItalic: () => wrapSelectionWithStrings('*', '*', _('emphasised text')),
textLink: async () => {
@ -210,6 +222,8 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
if (commands[cmd.name]) {
commandOutput = commands[cmd.name](cmd.value);
} else if (editorRef.current.supportsCommand(cmd)) {
commandOutput = editorRef.current.execCommandFromJoplinCommand(cmd);
} else {
reg.logger().warn('CodeMirror: unsupported Joplin command: ', cmd);
}
@ -255,6 +269,17 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
}
}, []);
const editorPaste = useCallback(() => {
const clipboardText = clipboard.readText();
if (clipboardText) {
editorPasteText();
} else {
// To handle pasting images
void onEditorPaste();
}
}, [editorPasteText, onEditorPaste]);
const loadScript = async (script: any) => {
return new Promise((resolve) => {
let element: any = document.createElement('script');
@ -598,7 +623,6 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
const menu = new Menu();
const hasSelectedText = editorRef.current && !!editorRef.current.getSelection() ;
const clipboardText = clipboard.readText();
menu.append(
new MenuItem({
@ -625,12 +649,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
label: _('Paste'),
enabled: true,
click: async () => {
if (clipboardText) {
editorPasteText();
} else {
// To handle pasting images
void onEditorPaste();
}
editorPaste();
},
})
);

View File

@ -105,8 +105,8 @@ function Editor(props: EditorProps, ref: any) {
useLineSorting(CodeMirror);
useEditorSearch(CodeMirror);
useJoplinMode(CodeMirror);
useKeymap(CodeMirror);
const pluginOptions: any = useExternalPlugins(CodeMirror, props.plugins);
useKeymap(CodeMirror);
useImperativeHandle(ref, () => {
return editor;

View File

@ -1,6 +1,9 @@
import { useEffect } from 'react';
import CommandService from '@joplin/lib/services/CommandService';
import KeymapService, { KeymapItem } from '@joplin/lib/services/KeymapService';
import { EditorCommand } from '../../../utils/types';
import shim from '@joplin/lib/shim';
const { reg } = require('@joplin/lib/registry.js');
export default function useKeymap(CodeMirror: any) {
@ -23,6 +26,77 @@ export default function useKeymap(CodeMirror: any) {
CodeMirror.Vim.mapCommand('o', 'action', 'insertListElement', { after: true }, { context: 'normal', isEdit: true, interlaceInsertRepeat: true });
}
function isEditorCommand(command: string) {
return command.startsWith('editor.');
}
// Converts a command of the form editor.command to just command
function editorCommandToCodeMirror(command: String) {
return command.slice(7); // 7 is the length of editor.
}
// CodeMirror and Electron register accelerators slightly different
// CodeMirror requires a - between keys while Electron want's a +
// CodeMirror doesn't recognize Option (it uses Alt instead)
// This function uses simple regex to translate the Electron
// accelerator to a CodeMirror accelerator
function normalizeAccelerator(accelerator: String) {
return accelerator.replace(/\+/g, '-').replace('Option', 'Alt');
}
// Because there is sometimes a clash between these keybindings and the Joplin window ones
// (This specifically can happen with the Ctrl-B and Ctrl-I keybindings when
// codemirror is in contenteditable mode)
// we will register all keypresses with the codemirror editor to guarentee they
// work no matter where the focus is
function registerJoplinCommand(key: KeymapItem) {
if (!key.command || !key.accelerator) return;
let command = '';
if (isEditorCommand(key.command)) {
command = editorCommandToCodeMirror(key.command);
} else {
// We need to register Joplin commands with codemirror
command = `joplin${key.command}`;
// Not all commands are registered with the command service
// (for example, the Quit command)
// This check will ensure that codemirror only takesover the commands that are
// see gui/KeymapConfig/getLabel.ts for more information
const commandNames = CommandService.instance().commandNames();
if (commandNames.includes(key.command)) {
CodeMirror.commands[command] = () => {
void CommandService.instance().execute(key.command);
};
}
}
// CodeMirror and Electron have slightly different formats for defining accelerators
const acc = normalizeAccelerator(key.accelerator);
CodeMirror.keyMap.default[acc] = command;
}
// Called on initialization, and whenever the keymap changes
function registerKeymap() {
const keymapItems = KeymapService.instance().getKeymapItems();
// Register all commands with the codemirror editor
keymapItems.forEach((key) => { registerJoplinCommand(key); });
}
CodeMirror.defineExtension('supportsCommand', function(cmd: EditorCommand) {
return isEditorCommand(cmd.name) && editorCommandToCodeMirror(cmd.name) in CodeMirror.commands;
});
// Used when an editor command is executed using the CommandService.instance().execute
// function (rather than being initiated by a keypress in the editor)
CodeMirror.defineExtension('execCommandFromJoplin', function(cmd: EditorCommand) {
if (cmd.value) {
reg.logger().warn('CodeMirror commands cannot accept a value:', cmd);
}
return this.execCommand(editorCommandToCodeMirror(cmd.name));
});
useEffect(() => {
// This enables the special modes (emacs and vim) to initiate sync by the save action
CodeMirror.commands.save = save;
@ -46,61 +120,57 @@ export default function useKeymap(CodeMirror: any) {
'Esc': 'singleSelection',
};
// Some keybindings are added here and not to the global registry because users
// often expect multiple keys to bind to the same command for example, redo is mapped to
// both Ctrl+Shift+Z AND Ctrl+Y
// Doing this mapping here will make those commands available but will allow users to
// override them using the KeymapService
CodeMirror.keyMap.default = {
// Windows / Linux
'Ctrl-Z': 'undo',
'Shift-Ctrl-Z': 'redo',
'Ctrl-Y': 'redo',
'Ctrl-Up': 'goLineUp',
'Ctrl-Down': 'go,ineDown',
'Ctrl+Home': 'goDocStart',
'Ctrl+End': 'goDocEnd',
'Ctrl+Left': 'goGroupLeft',
'Ctrl+Right': 'goGroupRight',
'Alt+Left': 'goLineStart',
'Alt+Right': 'goLineEnd',
'Ctrl+Backspace': 'delGroupBefore',
'Ctrl+Delete': 'delGroupAfter',
'fallthrough': 'basic',
};
if (shim.isMac()) {
CodeMirror.keyMap.default = {
// MacOS
'Cmd-A': 'selectAll',
'Cmd-D': 'deleteLine',
'Cmd-Z': 'undo',
'Shift-Cmd-Z': 'redo',
'Cmd-Y': 'redo',
'Cmd-Home': 'goDocStart',
'Cmd-Up': 'goDocStart',
'Cmd-End': 'goDocEnd',
'Cmd-Down': 'goDocEnd',
'Cmd-Left': 'goLineLeft',
'Cmd-Right': 'goLineRight',
'Alt-Left': 'goGroupLeft',
'Alt-Right': 'goGroupRight',
'Alt-Backspace': 'delGroupBefore',
'Alt-Delete': 'delGroupAfter',
'Cmd-[': 'indentLess',
'Cmd-]': 'indentMore',
'Cmd-/': 'toggleComment',
'Cmd-Opt-S': 'sortSelectedLines',
'Opt-Up': 'swapLineUp',
'Opt-Down': 'swapLineDown',
'fallthrough': 'basic',
};
} else {
CodeMirror.keyMap.default = {
// Windows/linux
'Ctrl-A': 'selectAll',
'Ctrl-D': 'deleteLine',
'Ctrl-Z': 'undo',
'Shift-Ctrl-Z': 'redo',
'Ctrl-Y': 'redo',
'Ctrl-Home': 'goDocStart',
'Ctrl-End': 'goDocEnd',
'Ctrl-Up': 'goLineUp',
'Ctrl-Down': 'goLineDown',
'Ctrl-Left': 'goGroupLeft',
'Ctrl-Right': 'goGroupRight',
'Alt-Left': 'goLineStart',
'Alt-Right': 'goLineEnd',
'Ctrl-Backspace': 'delGroupBefore',
'Ctrl-Delete': 'delGroupAfter',
'Ctrl-[': 'indentLess',
'Ctrl-]': 'indentMore',
'Ctrl-/': 'toggleComment',
'Ctrl-Alt-S': 'sortSelectedLines',
'Alt-Up': 'swapLineUp',
'Alt-Down': 'swapLineDown',
'Cmd-Home': 'goDocStart',
'Cmd-Up': 'goDocStart',
'Ctrl-D': 'delCharAfter',
'Cmd+Home': 'goDocStart',
'Cmd+End': 'goDocEnd',
'Cmd+Left': 'goGroupLeft',
'Cmd+Right': 'goGroupRight',
'Ctrl+A': 'goLineStart',
'Ctrl+E': 'goLineEnd',
'Alt+Backspace': 'delGroupBefore',
'Alt+Delete': 'delGroupAfter',
'fallthrough': 'basic',
};
}
const keymapService = KeymapService.instance();
registerKeymap();
keymapService.on('keymapChange', registerKeymap);
setupEmacs();
setupVim();
}, []);

View File

@ -83,6 +83,42 @@ const declarations: CommandDeclaration[] = [
label: () => _('Insert Date Time'),
iconName: 'icon-add-date',
},
{
name: 'editor.deleteLine',
label: _('Delete line'),
},
{
name: 'editor.undo',
label: _('Undo'),
},
{
name: 'editor.redo',
label: _('Redo'),
},
{
name: 'editor.indentLess',
label: _('Indent less'),
},
{
name: 'editor.indentMore',
label: _('Indent more'),
},
{
name: 'editor.toggleComment',
label: _('Toggle comment'),
},
{
name: 'editor.sortSelectedLines',
label: _('Sort selected lines'),
},
{
name: 'editor.swapLineUp',
label: _('Swap line up'),
},
{
name: 'editor.swapLineDown',
label: _('Swap line down'),
},
{
name: 'selectedText',
},

View File

@ -34,5 +34,14 @@ export default function() {
'toggleNoteList',
'toggleSideBar',
'toggleVisiblePanes',
'editor.deleteLine',
'editor.undo',
'editor.redo',
'editor.indentLess',
'editor.indentMore',
'editor.toggleComment',
'editor.sortSelectedLines',
'editor.swapLineUp',
'editor.swapLineDown',
];
}

View File

@ -45,6 +45,15 @@ const defaultKeymapItems = {
{ accelerator: 'Cmd+P', command: 'gotoAnything' },
{ accelerator: 'Shift+Cmd+P', command: 'commandPalette' },
{ accelerator: 'F1', command: 'help' },
{ accelerator: 'Cmd+D', command: 'editor.deleteLine' },
{ accelerator: 'Cmd+Z', command: 'editor.undo' },
{ accelerator: 'Cmd+Y', command: 'editor.redo' },
{ accelerator: 'Cmd+[', command: 'editor.indentLess' },
{ accelerator: 'Cmd+]', command: 'editor.indentMore' },
{ accelerator: 'Cmd+/', command: 'editor.toggleComment' },
{ accelerator: 'Option+Cmd+A', command: 'editor.sortSelectedLines' },
{ accelerator: 'Option+Up', command: 'editor.swapLineUp' },
{ accelerator: 'Option+Down', command: 'editor.swapLineDown' },
],
default: [
{ accelerator: 'Ctrl+N', command: 'newNote' },
@ -77,6 +86,15 @@ const defaultKeymapItems = {
{ accelerator: 'Ctrl+P', command: 'gotoAnything' },
{ accelerator: 'Ctrl+Shift+P', command: 'commandPalette' },
{ accelerator: 'F1', command: 'help' },
{ accelerator: 'Ctrl+D', command: 'editor.deleteLine' },
{ accelerator: 'Ctrl+Z', command: 'editor.undo' },
{ accelerator: 'Ctrl+Y', command: 'editor.redo' },
{ accelerator: 'Ctrl+[', command: 'editor.indentLess' },
{ accelerator: 'Ctrl+]', command: 'editor.indentMore' },
{ accelerator: 'Ctrl+/', command: 'editor.toggleComment' },
{ accelerator: 'Ctrl+Alt+S', command: 'editor.sortSelectedLines' },
{ accelerator: 'Alt+Up', command: 'editor.swapLineUp' },
{ accelerator: 'Alt+Down', command: 'editor.swapLineDown' },
],
};

View File

@ -14,6 +14,12 @@ Now try to install again and it should work.
More info there: https://github.com/electron-userland/electron-builder/issues/4057
## How can I pass arguments to the Linux installation script?
You can pass [arguments](https://github.com/laurent22/joplin/blob/dev/Joplin_install_and_update.sh#L37) to the installation script by using this command.
`wget -O - https://raw.githubusercontent.com/laurent22/joplin/dev/Joplin_install_and_update.sh \| bash -s -- --argument1 --argument2`
## How can I edit my note in an external text editor?
The editor command (may include arguments) defines which editor will be used to open a note. If none is provided it will try to auto-detect the default editor. If this does nothing or you want to change it for Joplin, you need to configure it in the Preferences -> Text editor command.