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

Handle ctrl+c

This commit is contained in:
Laurent Cozic 2017-08-04 18:50:12 +02:00
parent 2868a28422
commit 1f91d0dfdb
11 changed files with 256 additions and 98 deletions

View File

@ -26,6 +26,7 @@ class Application {
this.autocompletion_ = { active: false };
this.commands_ = {};
this.commandMetadata_ = null;
this.activeCommand_ = null;
}
currentFolder() {
@ -235,7 +236,7 @@ class Application {
case 'FOLDERS_UPDATE_ONE':
case 'FOLDER_DELETE':
reg.scheduleSync();
//reg.scheduleSync();
break;
}
@ -303,9 +304,13 @@ class Application {
async execCommand(argv) {
if (!argv.length) throw new Error('Empty command');
const commandName = argv[0];
const command = this.findCommandByName(commandName);
const cmdArgs = cliUtils.makeCommandArgs(command, argv);
await command.action(cmdArgs);
this.activeCommand_ = this.findCommandByName(commandName);
const cmdArgs = cliUtils.makeCommandArgs(this.activeCommand_, argv);
await this.activeCommand_.action(cmdArgs);
}
async cancelCurrentCommand() {
await this.activeCommand_.cancel();
}
async start() {
@ -388,14 +393,17 @@ class Application {
for (let i = 0; i < items.length; i++) {
items[i] = items[i].replace(/ /g, '\\ ');
}
//console.info(items);
console.info(items.join("\n"));
}
return;
}
this.execCommand(argv);
try {
await this.execCommand(argv);
} catch (error) {
console.info(error);
}
}
}

View File

@ -1,4 +1,6 @@
import yargParser from 'yargs-parser';
import { _ } from 'lib/locale.js';
import { time } from 'lib/time-utils.js';
const stringPadding = require('string-padding');
const cliUtils = {};
@ -104,7 +106,7 @@ cliUtils.makeCommandArgs = function(cmd, argv) {
for (let i = 1; i < cmdUsage['_'].length; i++) {
const a = cliUtils.parseCommandArg(cmdUsage['_'][i]);
if (a.required && !args['_'][i]) throw new Error('Missing required arg: ' + a.name);
if (a.required && !args['_'][i]) throw new Error(_('Missing required argument: %s', a.name));
if (i >= a.length) {
output[a.name] = null;
} else {
@ -124,4 +126,53 @@ cliUtils.makeCommandArgs = function(cmd, argv) {
return output;
}
cliUtils.promptConfirm = function(message, answers = null) {
if (!answers) answers = [_('Y'), _('n')];
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
message += ' (' + answers.join('/') + ')';
return new Promise((resolve, reject) => {
rl.question(message + ' ', (answer) => {
const ok = !answer || answer.toLowerCase() == answers[0].toLowerCase();
rl.close();
resolve(ok);
});
});
}
let redrawStarted_ = false;
let redrawLastLog_ = null;
let redrawLastUpdateTime_ = 0;
cliUtils.redraw = function(s) {
const now = time.unixMs();
if (now - redrawLastUpdateTime_ > 4000) {
console.info(s);
redrawLastUpdateTime_ = now;
redrawLastLog_ = null;
} else {
redrawLastLog_ = s;
}
redrawStarted_ = true;
}
cliUtils.redrawDone = function() {
if (!redrawStarted_) return;
if (redrawLastLog_) {
console.info(redrawLastLog_);
}
redrawLastLog_ = null;
redrawStarted_ = false;
}
export { cliUtils };

View File

@ -7,6 +7,7 @@ import { Note } from 'lib/models/note.js';
import { Setting } from 'lib/models/setting.js';
import { BaseModel } from 'lib/base-model.js';
import { autocompleteItems } from './autocomplete.js';
import { cliUtils } from './cli-utils.js';
class Command extends BaseCommand {
@ -46,10 +47,7 @@ class Command extends BaseCommand {
let note = await app().loadItem(BaseModel.TYPE_NOTE, title);
if (!note) {
// TODO
throw new Error(_('Note does not exist.'));
let ok = await vorpalUtils.cmdPromptConfirm(this, _('Note does not exist: "%s". Create it?', title))
const ok = await cliUtils.promptConfirm(_('Note does not exist: "%s". Create it?', title));
if (!ok) return;
newNote = await Note.save({ title: title, parent_id: app().currentFolder().id });
note = await Note.load(newNote.id);

View File

@ -4,6 +4,7 @@ import { _ } from 'lib/locale.js';
import { Folder } from 'lib/models/folder.js';
import { importEnex } from 'import-enex';
import { filename, basename } from 'lib/path-utils.js';
import { cliUtils } from './cli-utils.js';
class Command extends BaseCommand {
@ -28,16 +29,10 @@ class Command extends BaseCommand {
let folderTitle = args['notebook'];
let force = args.options.force === true;
force = true; // TODO
if (!folderTitle) folderTitle = filename(filePath);
folder = await Folder.loadByField('title', folderTitle);
const msg = folder ? _('File "%s" will be imported into existing notebook "%s". Continue?', basename(filePath), folderTitle) : _('New notebook "%s" will be created and file "%s" will be imported into it. Continue?', folderTitle, basename(filePath));
const ok = force ? true : await vorpalUtils.cmdPromptConfirm(this, msg);
const ok = force ? true : await cliUtils.promptConfirm(msg);
if (!ok) return;
let options = {
@ -50,8 +45,7 @@ class Command extends BaseCommand {
if (progressState.skipped) line.push(_('Skipped: %d.', progressState.skipped));
if (progressState.resourcesCreated) line.push(_('Resources: %d.', progressState.resourcesCreated));
if (progressState.notesTagged) line.push(_('Tagged: %d.', progressState.notesTagged));
this.log(line.join(' ')); // TODO
//vorpalUtils.redraw(line.join(' '));
cliUtils.redraw(line.join(' '));
},
onError: (error) => {
let s = error.trace ? error.trace : error.toString();
@ -62,6 +56,7 @@ class Command extends BaseCommand {
folder = !folder ? await Folder.save({ title: folderTitle }) : folder;
this.log(_('Importing notes...'));
await importEnex(folder.id, filePath, options);
cliUtils.redrawDone();
}
}

View File

@ -6,6 +6,7 @@ import { Folder } from 'lib/models/folder.js';
import { Note } from 'lib/models/note.js';
import { BaseModel } from 'lib/base-model.js';
import { autocompleteItems } from './autocomplete.js';
import { cliUtils } from './cli-utils.js';
class Command extends BaseCommand {
@ -30,7 +31,7 @@ class Command extends BaseCommand {
async action(args) {
const pattern = args['note-pattern'];
const recursive = args.options && args.options.recursive === true;
const force = true || args.options && args.options.force === true; // TODO
const force = args.options && args.options.force === true;
// if (recursive) {
// const folder = await app().loadItem(BaseModel.TYPE_FOLDER, pattern);
@ -43,7 +44,7 @@ class Command extends BaseCommand {
const notes = await app().loadItems(BaseModel.TYPE_NOTE, pattern);
if (!notes.length) throw new Error(_('Cannot find "%s".', pattern));
const ok = force ? true : await vorpalUtils.cmdPromptConfirm(this, _('%d notes match this pattern. Delete them?', notes.length));
const ok = force ? true : await cliUtils.promptConfirm(_('%d notes match this pattern. Delete them?', notes.length));
if (!ok) return;
let ids = notes.map((n) => n.id);
await Note.batchDelete(ids);

View File

@ -6,6 +6,7 @@ import { Setting } from 'lib/models/setting.js';
import { BaseItem } from 'lib/models/base-item.js';
import { Synchronizer } from 'lib/synchronizer.js';
import { reg } from 'lib/registry.js';
import { cliUtils } from './cli-utils.js';
import md5 from 'md5';
const locker = require('proper-lockfile');
const fs = require('fs-extra');
@ -67,9 +68,18 @@ class Command extends BaseCommand {
const lockFilePath = osTmpdir() + '/synclock_' + md5(Setting.value('profileDir'));
if (!await fs.pathExists(lockFilePath)) await fs.writeFile(lockFilePath, 'synclock');
if (await Command.isLocked(lockFilePath)) throw new Error(_('Synchronisation is already in progress.'));
try {
if (await Command.isLocked(lockFilePath)) throw new Error(_('Synchronisation is already in progress.'));
this.releaseLockFn_ = await Command.lockFile(lockFilePath);
this.releaseLockFn_ = await Command.lockFile(lockFilePath);
} catch (error) {
if (error.code == 'ELOCKED') {
const msg = _('Lock file is already being hold. If you know that no synchronisation is taking place, you may delete the lock file at "%s" and resume the operation.', error.file);
this.log(msg);
return;
}
throw error;
}
try {
this.syncTarget_ = Setting.value('sync.target');
@ -87,11 +97,10 @@ class Command extends BaseCommand {
let options = {
onProgress: (report) => {
let lines = Synchronizer.reportToLines(report);
//if (lines.length) vorpalUtils.redraw(lines.join(' '));
if (lines.length) this.log(lines.join(' ')); // TODO
if (lines.length) cliUtils.redraw(lines.join(' '));
},
onMessage: (msg) => {
vorpalUtils.redrawDone();
cliUtils.redrawDone();
this.log(msg);
},
randomFailures: args.options['random-failures'] === true,
@ -122,11 +131,13 @@ class Command extends BaseCommand {
this.log(_('Done.'));
} catch (error) {
cliUtils.redrawDone();
this.releaseLockFn_();
this.releaseLockFn_ = null;
throw error;
}
cliUtils.redrawDone();
this.releaseLockFn_();
this.releaseLockFn_ = null;
}
@ -134,7 +145,9 @@ class Command extends BaseCommand {
async cancel() {
const target = this.syncTarget_ ? this.syncTarget_ : Setting.value('sync.target');
this.log(_('Cancelling...'));
cliUtils.redrawDone();
this.log(_('Cancelling... Please wait.'));
if (reg.syncHasAuth(target)) {
let sync = await reg.synchronizer(target);

View File

@ -40,7 +40,25 @@ Setting.setConstant('appType', 'cli');
shimInit();
app().start().catch((error) => {
const application = app();
if (process.platform === "win32") {
var rl = require("readline").createInterface({
input: process.stdin,
output: process.stdout
});
rl.on("SIGINT", function () {
process.emit("SIGINT");
});
}
process.on("SIGINT", async function() {
console.info(_('Received %s', 'SIGINT'));
await application.cancelCurrentCommand();
});
application.start().catch((error) => {
console.error(_('Fatal error:'));
console.error(error);
});

View File

@ -0,0 +1,3 @@
#/bin/bash
CLIENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
NODE_PATH="$CLIENT_DIR/build" node "$CLIENT_DIR/build/build-translation.js" --silent

View File

@ -41,6 +41,33 @@ msgstr ""
msgid "Exits the application."
msgstr ""
msgid "Only Bash is currently supported for autocompletion."
msgstr ""
#, javascript-format
msgid "Adding autocompletion script to: \"%s\""
msgstr ""
msgid "Autocompletion script is already installed."
msgstr ""
msgid "Autocompletion has been installed."
msgstr ""
#, javascript-format
msgid "Sourcing \"%s\"..."
msgstr ""
#, javascript-format
msgid "Missing required argument: %s"
msgstr ""
msgid "Y"
msgstr ""
msgid "n"
msgstr ""
msgid "Displays the given note."
msgstr ""
@ -69,7 +96,7 @@ msgid "%s = %s"
msgstr ""
msgid ""
"Duplicates the notes matching <pattern> to [notebook]. If no notebook is "
"Duplicates the notes matching <note> to [notebook]. If no notebook is "
"specified the note is duplicated in the current notebook."
msgstr ""
@ -86,9 +113,6 @@ msgstr ""
msgid "No active notebook."
msgstr ""
msgid "Note does not exist."
msgstr ""
#, javascript-format
msgid "Note does not exist: \"%s\". Create it?"
msgstr ""
@ -143,8 +167,8 @@ msgid "Importing notes..."
msgstr ""
msgid ""
"Displays the notes in [notebook]. Use `ls /` to display the list of "
"notebooks."
"Displays the notes in the current notebook. Use `ls /` to display the list "
"of notebooks."
msgstr ""
msgid "Displays only the first top <num> notes."
@ -185,21 +209,15 @@ msgstr ""
msgid "Creates a new todo."
msgstr ""
msgid ""
"Moves the notes matching <pattern> to <destination>. If <pattern> is a note, "
"it will be moved to the notebook <destination>. If <pattern> is a notebook, "
"it will be renamed to <destination>."
msgid "Moves the notes matching <note-pattern> to [notebook]."
msgstr ""
msgid "Deletes the items matching <pattern>."
msgid "Deletes the notes matching <note-pattern>."
msgstr ""
msgid "Deletes the items without asking for confirmation."
msgstr ""
msgid "Deletes a notebook."
msgstr ""
#, javascript-format
msgid "%d notes match this pattern. Delete them?"
msgstr ""
@ -239,9 +257,9 @@ msgid "Cancelling..."
msgstr ""
msgid ""
"<command> can be \"add\", \"remove\" or \"list\" to assign or remove [tag] "
"from [note], or to list the notes associated with [tag]. The command `tag "
"list` can be used to list all the tags."
"<tag-command> can be \"add\", \"remove\" or \"list\" to assign or remove "
"[tag] from [note], or to list the notes associated with [tag]. The command "
"`tag list` can be used to list all the tags."
msgstr ""
#, javascript-format
@ -249,10 +267,10 @@ msgid "Invalid command: \"%s\""
msgstr ""
msgid ""
"<action> can either be \"toggle\" or \"clear\". Use \"toggle\" to toggle the "
"given todo between completed and uncompleted state (If the target is a "
"regular note it will be converted to a todo). Use \"clear\" to convert the "
"todo back to a regular note."
"<todo-command> can either be \"toggle\" or \"clear\". Use \"toggle\" to "
"toggle the given todo between completed and uncompleted state (If the target "
"is a regular note it will be converted to a todo). Use \"clear\" to convert "
"the todo back to a regular note."
msgstr ""
msgid ""

View File

@ -43,6 +43,33 @@ msgstr "Affiche l'aide pour la commande donnée."
msgid "Exits the application."
msgstr "Quitter le logiciel."
msgid "Only Bash is currently supported for autocompletion."
msgstr ""
#, javascript-format
msgid "Adding autocompletion script to: \"%s\""
msgstr ""
msgid "Autocompletion script is already installed."
msgstr ""
msgid "Autocompletion has been installed."
msgstr ""
#, javascript-format
msgid "Sourcing \"%s\"..."
msgstr ""
#, javascript-format
msgid "Missing required argument: %s"
msgstr ""
msgid "Y"
msgstr ""
msgid "n"
msgstr ""
msgid "Displays the given note."
msgstr "Affiche la note."
@ -73,8 +100,9 @@ msgstr "%s = %s (%s)"
msgid "%s = %s"
msgstr "%s = %s"
#, fuzzy
msgid ""
"Duplicates the notes matching <pattern> to [notebook]. If no notebook is "
"Duplicates the notes matching <note> to [notebook]. If no notebook is "
"specified the note is duplicated in the current notebook."
msgstr ""
"Copie les notes correspondant à [nom] vers [carnet]. Si aucun carnet n'est "
@ -95,13 +123,9 @@ msgstr ""
msgid "No active notebook."
msgstr "Aucun carnet actif."
#, fuzzy
msgid "Note does not exist."
msgstr "Ce carnet n'existe pas : \"%s\". Le créer ?"
#, javascript-format
msgid "Note does not exist: \"%s\". Create it?"
msgstr "Ce carnet n'existe pas : \"%s\". Le créer ?"
msgstr "Cette note n'existe pas : \"%s\". La créer ?"
msgid "Starting to edit note. Close the editor to get back to the prompt."
msgstr ""
@ -157,9 +181,10 @@ msgstr "Etiquettes : %d."
msgid "Importing notes..."
msgstr "Importation des notes..."
#, fuzzy
msgid ""
"Displays the notes in [notebook]. Use `ls /` to display the list of "
"notebooks."
"Displays the notes in the current notebook. Use `ls /` to display the list "
"of notebooks."
msgstr ""
"Affiche les notes dans le carnet. Utilisez `ls /` pour afficher la liste des "
"carnets."
@ -208,24 +233,17 @@ msgstr "Les notes ne peuvent être créées que dans un carnet."
msgid "Creates a new todo."
msgstr "Créer une nouvelle tâche."
msgid ""
"Moves the notes matching <pattern> to <destination>. If <pattern> is a note, "
"it will be moved to the notebook <destination>. If <pattern> is a notebook, "
"it will be renamed to <destination>."
msgstr ""
"Déplacer les notes correspondantes à <motif> vers <destination>. Si <motif> "
"est une note, elle sera déplacée vers le carnet <destination>. Si <motif> "
"est un carnet, il sera renommé <destination>."
#, fuzzy
msgid "Moves the notes matching <note-pattern> to [notebook]."
msgstr "Supprime les objets correspondants à <motif>."
msgid "Deletes the items matching <pattern>."
#, fuzzy
msgid "Deletes the notes matching <note-pattern>."
msgstr "Supprime les objets correspondants à <motif>."
msgid "Deletes the items without asking for confirmation."
msgstr "Supprime les objets sans demander la confirmation."
msgid "Deletes a notebook."
msgstr "Supprime le carnet."
#, javascript-format
msgid "%d notes match this pattern. Delete them?"
msgstr "%d notes correspondent à ce motif. Les supprimer ?"
@ -266,10 +284,11 @@ msgstr "Terminé."
msgid "Cancelling..."
msgstr "Annulation..."
#, fuzzy
msgid ""
"<command> can be \"add\", \"remove\" or \"list\" to assign or remove [tag] "
"from [note], or to list the notes associated with [tag]. The command `tag "
"list` can be used to list all the tags."
"<tag-command> can be \"add\", \"remove\" or \"list\" to assign or remove "
"[tag] from [note], or to list the notes associated with [tag]. The command "
"`tag list` can be used to list all the tags."
msgstr ""
"<command> peut être \"add\", \"remove\" ou \"list\" pour assigner ou enlever "
"l'étiquette [tag] de la [note], our pour lister les notes associées avec "
@ -280,11 +299,12 @@ msgstr ""
msgid "Invalid command: \"%s\""
msgstr "Commande invalide : \"%s\""
#, fuzzy
msgid ""
"<action> can either be \"toggle\" or \"clear\". Use \"toggle\" to toggle the "
"given todo between completed and uncompleted state (If the target is a "
"regular note it will be converted to a todo). Use \"clear\" to convert the "
"todo back to a regular note."
"<todo-command> can either be \"toggle\" or \"clear\". Use \"toggle\" to "
"toggle the given todo between completed and uncompleted state (If the target "
"is a regular note it will be converted to a todo). Use \"clear\" to convert "
"the todo back to a regular note."
msgstr ""
"Gère le status des tâches. <action> peut être \"toggle\" ou \"clear\". "
"Utilisez \"toggle\" pour basculer la tâche entre le status terminé et non-"
@ -579,6 +599,21 @@ msgstr ""
msgid "Welcome"
msgstr "Bienvenue"
#~ msgid "Note does not exist."
#~ msgstr "Cette note n'existe pas."
#~ msgid ""
#~ "Moves the notes matching <pattern> to <destination>. If <pattern> is a "
#~ "note, it will be moved to the notebook <destination>. If <pattern> is a "
#~ "notebook, it will be renamed to <destination>."
#~ msgstr ""
#~ "Déplacer les notes correspondantes à <motif> vers <destination>. Si "
#~ "<motif> est une note, elle sera déplacée vers le carnet <destination>. Si "
#~ "<motif> est un carnet, il sera renommé <destination>."
#~ msgid "Deletes a notebook."
#~ msgstr "Supprime le carnet."
#~ msgid "Delete notebook \"%s\"?"
#~ msgstr "Supprimer le carnet \"%s\" ?"

View File

@ -41,6 +41,33 @@ msgstr ""
msgid "Exits the application."
msgstr ""
msgid "Only Bash is currently supported for autocompletion."
msgstr ""
#, javascript-format
msgid "Adding autocompletion script to: \"%s\""
msgstr ""
msgid "Autocompletion script is already installed."
msgstr ""
msgid "Autocompletion has been installed."
msgstr ""
#, javascript-format
msgid "Sourcing \"%s\"..."
msgstr ""
#, javascript-format
msgid "Missing required argument: %s"
msgstr ""
msgid "Y"
msgstr ""
msgid "n"
msgstr ""
msgid "Displays the given note."
msgstr ""
@ -69,7 +96,7 @@ msgid "%s = %s"
msgstr ""
msgid ""
"Duplicates the notes matching <pattern> to [notebook]. If no notebook is "
"Duplicates the notes matching <note> to [notebook]. If no notebook is "
"specified the note is duplicated in the current notebook."
msgstr ""
@ -86,9 +113,6 @@ msgstr ""
msgid "No active notebook."
msgstr ""
msgid "Note does not exist."
msgstr ""
#, javascript-format
msgid "Note does not exist: \"%s\". Create it?"
msgstr ""
@ -143,8 +167,8 @@ msgid "Importing notes..."
msgstr ""
msgid ""
"Displays the notes in [notebook]. Use `ls /` to display the list of "
"notebooks."
"Displays the notes in the current notebook. Use `ls /` to display the list "
"of notebooks."
msgstr ""
msgid "Displays only the first top <num> notes."
@ -185,21 +209,15 @@ msgstr ""
msgid "Creates a new todo."
msgstr ""
msgid ""
"Moves the notes matching <pattern> to <destination>. If <pattern> is a note, "
"it will be moved to the notebook <destination>. If <pattern> is a notebook, "
"it will be renamed to <destination>."
msgid "Moves the notes matching <note-pattern> to [notebook]."
msgstr ""
msgid "Deletes the items matching <pattern>."
msgid "Deletes the notes matching <note-pattern>."
msgstr ""
msgid "Deletes the items without asking for confirmation."
msgstr ""
msgid "Deletes a notebook."
msgstr ""
#, javascript-format
msgid "%d notes match this pattern. Delete them?"
msgstr ""
@ -239,9 +257,9 @@ msgid "Cancelling..."
msgstr ""
msgid ""
"<command> can be \"add\", \"remove\" or \"list\" to assign or remove [tag] "
"from [note], or to list the notes associated with [tag]. The command `tag "
"list` can be used to list all the tags."
"<tag-command> can be \"add\", \"remove\" or \"list\" to assign or remove "
"[tag] from [note], or to list the notes associated with [tag]. The command "
"`tag list` can be used to list all the tags."
msgstr ""
#, javascript-format
@ -249,10 +267,10 @@ msgid "Invalid command: \"%s\""
msgstr ""
msgid ""
"<action> can either be \"toggle\" or \"clear\". Use \"toggle\" to toggle the "
"given todo between completed and uncompleted state (If the target is a "
"regular note it will be converted to a todo). Use \"clear\" to convert the "
"todo back to a regular note."
"<todo-command> can either be \"toggle\" or \"clear\". Use \"toggle\" to "
"toggle the given todo between completed and uncompleted state (If the target "
"is a regular note it will be converted to a todo). Use \"clear\" to convert "
"the todo back to a regular note."
msgstr ""
msgid ""