2017-11-03 02:09:34 +02:00
|
|
|
const fs = require('fs-extra');
|
2022-11-01 17:28:14 +02:00
|
|
|
const BaseCommand = require('./base-command').default;
|
2020-11-07 17:59:37 +02:00
|
|
|
const { splitCommandString } = require('@joplin/lib/string-utils.js');
|
|
|
|
const uuid = require('@joplin/lib/uuid').default;
|
2017-11-03 02:09:34 +02:00
|
|
|
const { app } = require('./app.js');
|
2020-11-07 17:59:37 +02:00
|
|
|
const { _ } = require('@joplin/lib/locale');
|
2021-01-22 19:41:11 +02:00
|
|
|
const Note = require('@joplin/lib/models/Note').default;
|
2020-11-07 17:59:37 +02:00
|
|
|
const Setting = require('@joplin/lib/models/Setting').default;
|
|
|
|
const BaseModel = require('@joplin/lib/BaseModel').default;
|
2017-07-10 22:03:46 +02:00
|
|
|
|
|
|
|
class Command extends BaseCommand {
|
|
|
|
usage() {
|
2017-08-04 19:51:01 +02:00
|
|
|
return 'edit <note>';
|
2017-07-10 22:03:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
description() {
|
2017-07-18 20:21:03 +02:00
|
|
|
return _('Edit note.');
|
2017-07-10 22:03:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async action(args) {
|
2017-10-14 20:03:23 +02:00
|
|
|
let tempFilePath = null;
|
2017-07-10 22:03:46 +02:00
|
|
|
|
2017-07-13 23:26:45 +02:00
|
|
|
const onFinishedEditing = async () => {
|
2017-10-14 20:03:23 +02:00
|
|
|
if (tempFilePath) fs.removeSync(tempFilePath);
|
2019-07-30 09:35:42 +02:00
|
|
|
};
|
2017-07-10 22:03:46 +02:00
|
|
|
|
|
|
|
const textEditorPath = () => {
|
|
|
|
if (Setting.value('editor')) return Setting.value('editor');
|
|
|
|
if (process.env.EDITOR) return process.env.EDITOR;
|
|
|
|
throw new Error(_('No text editor is defined. Please set it using `config editor <editor-path>`'));
|
2019-07-30 09:35:42 +02:00
|
|
|
};
|
2017-07-10 22:03:46 +02:00
|
|
|
|
2019-07-30 09:35:42 +02:00
|
|
|
try {
|
2017-10-14 20:03:23 +02:00
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
// Load note or create it if it doesn't exist
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
2020-03-14 01:46:14 +02:00
|
|
|
const title = args['note'];
|
2017-07-10 22:03:46 +02:00
|
|
|
|
|
|
|
if (!app().currentFolder()) throw new Error(_('No active notebook.'));
|
2017-07-10 22:47:01 +02:00
|
|
|
let note = await app().loadItem(BaseModel.TYPE_NOTE, title);
|
2017-07-10 22:03:46 +02:00
|
|
|
|
2017-12-26 12:38:53 +02:00
|
|
|
this.encryptionCheck(note);
|
|
|
|
|
2017-07-13 23:26:45 +02:00
|
|
|
if (!note) {
|
2017-10-08 19:50:43 +02:00
|
|
|
const ok = await this.prompt(_('Note does not exist: "%s". Create it?', title));
|
2017-07-27 19:25:42 +02:00
|
|
|
if (!ok) return;
|
2017-10-14 20:03:23 +02:00
|
|
|
note = await Note.save({ title: title, parent_id: app().currentFolder().id });
|
|
|
|
note = await Note.load(note.id);
|
2017-07-13 23:26:45 +02:00
|
|
|
}
|
2017-07-10 22:03:46 +02:00
|
|
|
|
2017-10-14 20:03:23 +02:00
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
// Create the file to be edited and prepare the editor program arguments
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
2017-07-10 22:03:46 +02:00
|
|
|
let editorPath = textEditorPath();
|
2019-11-02 00:42:05 +02:00
|
|
|
let editorArgs = splitCommandString(editorPath);
|
2017-07-10 22:03:46 +02:00
|
|
|
|
|
|
|
editorPath = editorArgs[0];
|
|
|
|
editorArgs = editorArgs.splice(1);
|
|
|
|
|
2017-10-14 20:03:23 +02:00
|
|
|
const originalContent = await Note.serializeForEdit(note);
|
2017-07-10 22:03:46 +02:00
|
|
|
|
2019-09-19 23:51:18 +02:00
|
|
|
tempFilePath = `${Setting.value('tempDir')}/${uuid.create()}.md`;
|
2017-07-10 22:03:46 +02:00
|
|
|
editorArgs.push(tempFilePath);
|
|
|
|
|
2017-10-14 20:03:23 +02:00
|
|
|
await fs.writeFile(tempFilePath, originalContent);
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
// Start editing the file
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
|
|
|
this.logger().info('Disabling fullscreen...');
|
2017-07-10 22:03:46 +02:00
|
|
|
|
2019-11-02 00:42:05 +02:00
|
|
|
app().gui().showModalOverlay(_('Starting to edit note. Close the editor to get back to the prompt.'));
|
|
|
|
await app().gui().forceRender();
|
|
|
|
const termState = app().gui().termSaveState();
|
2019-07-30 09:35:42 +02:00
|
|
|
|
|
|
|
const spawnSync = require('child_process').spawnSync;
|
2018-01-17 20:10:07 +02:00
|
|
|
const result = spawnSync(editorPath, editorArgs, { stdio: 'inherit' });
|
|
|
|
|
|
|
|
if (result.error) this.stdout(_('Error opening note in editor: %s', result.error.message));
|
2017-07-10 22:03:46 +02:00
|
|
|
|
2019-11-02 00:42:05 +02:00
|
|
|
app().gui().termRestoreState(termState);
|
|
|
|
app().gui().hideModalOverlay();
|
|
|
|
app().gui().forceRender();
|
2017-07-10 22:03:46 +02:00
|
|
|
|
2017-10-14 20:03:23 +02:00
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
// Save the note and clean up
|
|
|
|
// -------------------------------------------------------------------------
|
2017-07-10 22:03:46 +02:00
|
|
|
|
2017-10-14 20:03:23 +02:00
|
|
|
const updatedContent = await fs.readFile(tempFilePath, 'utf8');
|
|
|
|
if (updatedContent !== originalContent) {
|
2020-03-14 01:46:14 +02:00
|
|
|
const updatedNote = await Note.unserializeForEdit(updatedContent);
|
2017-10-14 20:03:23 +02:00
|
|
|
updatedNote.id = note.id;
|
|
|
|
await Note.save(updatedNote);
|
2017-10-17 23:56:22 +02:00
|
|
|
this.stdout(_('Note has been saved.'));
|
2017-10-14 20:03:23 +02:00
|
|
|
}
|
|
|
|
|
2017-10-14 23:44:50 +02:00
|
|
|
this.dispatch({
|
2017-11-08 23:22:24 +02:00
|
|
|
type: 'NOTE_SELECT',
|
|
|
|
id: note.id,
|
2017-10-14 23:44:50 +02:00
|
|
|
});
|
|
|
|
|
2017-10-14 20:03:23 +02:00
|
|
|
await onFinishedEditing();
|
2019-07-30 09:35:42 +02:00
|
|
|
} catch (error) {
|
2017-07-13 23:26:45 +02:00
|
|
|
await onFinishedEditing();
|
2017-07-10 22:03:46 +02:00
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-30 09:35:42 +02:00
|
|
|
module.exports = Command;
|