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

Electron: Resolves #647: Allow specifying text editor path and arguments in setting

This commit is contained in:
Laurent Cozic 2018-06-27 21:34:41 +01:00
parent 424c8a2723
commit 7d7e1e1637
3 changed files with 50 additions and 3 deletions

View File

@ -846,7 +846,11 @@ class NoteTextComponent extends React.Component {
}
async commandStartExternalEditing() {
this.externalEditWatcher().openAndWatch(this.state.note);
try {
await this.externalEditWatcher().openAndWatch(this.state.note);
} catch (error) {
bridge().showErrorMessageBox(_('Error opening note in editor: %s', error.message));
}
}
async commandStopExternalEditing() {

View File

@ -32,7 +32,6 @@ class Setting extends BaseModel {
this.metadata_ = {
'activeFolderId': { value: '', type: Setting.TYPE_STRING, public: false },
'firstStart': { value: true, type: Setting.TYPE_BOOL, public: false },
'editor': { value: '', type: Setting.TYPE_STRING, public: true, appTypes: ['cli'], label: () => _('Text editor'), description: () => _('The editor that will be used to open a note. If none is provided it will try to auto-detect the default editor.') },
'locale': { value: defaultLocale(), type: Setting.TYPE_STRING, isEnum: true, public: true, label: () => _('Language'), options: () => {
return ObjectUtils.sortByValue(supportedLocalesToLanguages());
}},
@ -116,6 +115,7 @@ class Setting extends BaseModel {
}},
'noteVisiblePanes': { value: ['editor', 'viewer'], type: Setting.TYPE_ARRAY, public: false, appTypes: ['desktop'] },
'sidebarVisibility': { value: true, type: Setting.TYPE_BOOL, public: false, appTypes: ['desktop'] },
'editor': { value: '', type: Setting.TYPE_STRING, public: true, appTypes: ['cli', 'desktop'], label: () => _('Text editor command'), description: () => _('The editor command (may include arguments) that will be used to open a note. If none is provided it will try to auto-detect the default editor.') },
'showAdvancedOptions': { value: false, type: Setting.TYPE_BOOL, public: true, appTypes: ['mobile' ], label: () => _('Show advanced options') },
'sync.target': { value: SyncTargetRegistry.nameToId('dropbox'), type: Setting.TYPE_INT, isEnum: true, public: true, label: () => _('Synchronisation target'), description: (appType) => { return appType !== 'cli' ? null : _('The target to synchonise to. Each sync target may have additional parameters which are named as `sync.NUM.NAME` (all documented below).') }, options: () => {
return SyncTargetRegistry.idAndLabelPlainObject();

View File

@ -4,6 +4,8 @@ const Setting = require('lib/models/Setting');
const { shim } = require('lib/shim');
const chokidar = require('chokidar');
const EventEmitter = require('events');
const { splitCommandString } = require('lib/string-utils');
const spawn = require('child_process').spawn;
class ExternalEditWatcher {
@ -115,6 +117,40 @@ class ExternalEditWatcher {
return false;
}
textEditorCommand() {
const editorCommand = Setting.value('editor');
if (!editorCommand) return null;
const s = splitCommandString(editorCommand);
const path = s.splice(0, 1);
if (!path.length) throw new Error('Invalid editor command: ' + editorCommand);
return {
path: path[0],
args: s,
};
}
async spawnCommand(path, args, options) {
return new Promise((resolve, reject) => {
const subProcess = spawn(path, args, options);
const iid = setInterval(() => {
if (subProcess && subProcess.pid) {
this.logger().debug('Started editor with PID ' + subProcess.pid);
clearInterval(iid);
resolve();
}
}, 100);
subProcess.on('error', (error) => {
clearInterval(iid);
reject(error);
});
});
}
async openAndWatch(note) {
if (!note || !note.id) {
this.logger().warn('ExternalEditWatcher: Cannot open note: ', note);
@ -123,7 +159,14 @@ class ExternalEditWatcher {
const filePath = await this.writeNoteToFile_(note);
this.watch(filePath);
bridge().openExternal('file://' + filePath);
const cmd = this.textEditorCommand();
if (!cmd) {
bridge().openExternal('file://' + filePath);
} else {
cmd.args.push(filePath);
await this.spawnCommand(cmd.path, cmd.args, { detached: true });
}
this.dispatch({
type: 'NOTE_FILE_WATCHER_ADD',