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

Changed console to status bar

This commit is contained in:
Laurent Cozic 2017-10-15 17:57:09 +01:00
parent 03facc93f5
commit 7e2b4f7da5
8 changed files with 232 additions and 85 deletions

View File

@ -13,7 +13,6 @@ const Renderer = require('tkwidgets/framework/Renderer.js');
const BaseWidget = require('tkwidgets/BaseWidget.js');
const ListWidget = require('tkwidgets/ListWidget.js');
const TextWidget = require('tkwidgets/TextWidget.js');
const ConsoleWidget = require('tkwidgets/ConsoleWidget.js');
const HLayoutWidget = require('tkwidgets/HLayoutWidget.js');
const VLayoutWidget = require('tkwidgets/VLayoutWidget.js');
const ReduxRootWidget = require('tkwidgets/ReduxRootWidget.js');
@ -23,6 +22,8 @@ const WindowWidget = require('tkwidgets/WindowWidget.js');
const NoteWidget = require('./gui/NoteWidget.js');
const FolderListWidget = require('./gui/FolderListWidget.js');
const NoteListWidget = require('./gui/NoteListWidget.js');
const StatusBarWidget = require('./gui/StatusBarWidget.js');
const ConsoleWidget = require('./gui/ConsoleWidget.js');
class AppGui {
@ -41,7 +42,7 @@ class AppGui {
this.renderer_ = new Renderer(this.term(), this.rootWidget_);
this.renderer_.on('renderDone', async (event) => {
if (this.widget('console').hasFocus) this.widget('console').resetCursor();
//if (this.widget('console').hasFocus) this.widget('console').resetCursor();
});
this.app_.on('modelAction', async (event) => {
@ -58,9 +59,11 @@ class AppGui {
this.lastShortcutKeyTime_ = 0;
cliUtils.setStdout((...object) => {
for (let i = 0; i < object.length; i++) {
this.widget('console').bufferPush(object[i]);
}
return this.stdout(...object);
// for (let i = 0; i < object.length; i++) {
// this.widget('console').bufferPush(object[i]);
// }
});
}
@ -127,24 +130,21 @@ class AppGui {
const consoleWidget = new ConsoleWidget();
consoleWidget.hStretch = true;
consoleWidget.name = 'console';
consoleWidget.prompt = chalk.cyan('Joplin >') + ' ';
consoleWidget.on('accept', async (event) => {
consoleWidget.promptVisible = false;
await this.processCommand(event.input, 'console');
consoleWidget.promptVisible = true;
});
const statusBar = new StatusBarWidget();
statusBar.hStretch = true;
const hLayout = new HLayoutWidget();
hLayout.name = 'hLayout';
hLayout.addChild(folderList, { type: 'stretch', factor: 1 });
hLayout.addChild(noteList, { type: 'stretch', factor: 1 });
hLayout.addChild(noteText, { type: 'stretch', factor: 1 });
hLayout.addChild(noteText, { type: 'stretch', factor: 2 });
const vLayout = new VLayoutWidget();
vLayout.name = 'vLayout';
vLayout.addChild(hLayout, { type: 'stretch', factor: 1 });
vLayout.addChild(consoleWidget, { type: 'fixed', factor: 6 });
vLayout.addChild(consoleWidget, { type: 'fixed', factor: 3 });
vLayout.addChild(statusBar, { type: 'fixed', factor: 1 });
const win1 = new WindowWidget();
win1.addChild(vLayout);
@ -156,8 +156,6 @@ class AppGui {
setupShortcuts() {
const shortcuts = {};
const consoleWidget = this.widget('console');
shortcuts['DELETE'] = {
description: _('Delete a note'),
action: 'rm $n',
@ -169,9 +167,9 @@ class AppGui {
action: 'todo toggle $n',
}
shortcuts['c'] = {
shortcuts[':'] = {
description: _('Enter the console'),
action: () => { consoleWidget.focus(); }
isDocOnly: true,
};
shortcuts['ESC'] = {
@ -191,24 +189,19 @@ class AppGui {
},
}
shortcuts['nt'] = {
description: _('Create a new todo'),
action: () => { consoleWidget.focus('mktodo '); },
}
shortcuts['nn'] = {
description: _('Create a new note'),
action: () => { consoleWidget.focus('mknote '); },
action: { type: 'prompt', initialText: 'mknote ' },
}
shortcuts['nt'] = {
description: _('Create a new todo'),
action: () => { consoleWidget.focus('mktodo '); },
action: { type: 'prompt', initialText: 'mktodo ' },
}
shortcuts['nb'] = {
description: _('Create a new notebook'),
action: () => { consoleWidget.focus('mkbook '); },
action: { type: 'prompt', initialText: 'mkbook ' },
}
shortcuts['CTRL_JCTRL_Z'] = {
@ -225,30 +218,32 @@ class AppGui {
}
maximizeConsole(doMaximize = true) {
const consoleWidget = this.widget('console');
// const consoleWidget = this.widget('console');
if (consoleWidget.isMaximized__ === undefined) {
consoleWidget.isMaximized__ = false;
}
// if (consoleWidget.isMaximized__ === undefined) {
// consoleWidget.isMaximized__ = false;
// }
if (consoleWidget.isMaximized__ === doMaximize) return;
// if (consoleWidget.isMaximized__ === doMaximize) return;
let constraints = {
type: 'fixed',
factor: !doMaximize ? 5 : this.widget('vLayout').height - 4,
};
// let constraints = {
// type: 'fixed',
// factor: !doMaximize ? 5 : this.widget('vLayout').height - 4,
// };
consoleWidget.isMaximized__ = doMaximize;
// consoleWidget.isMaximized__ = doMaximize;
this.widget('vLayout').setWidgetConstraints(consoleWidget, constraints);
// this.widget('vLayout').setWidgetConstraints(consoleWidget, constraints);
}
minimizeConsole() {
this.maximizeConsole(false);
//this.maximizeConsole(false);
}
consoleIsMaximized() {
return this.widget('console').isMaximized__ === true;
return false;
//return this.widget('console').isMaximized__ === true;
}
widget(name) {
@ -323,7 +318,7 @@ class AppGui {
try {
await this.app().execCommand(args);
} catch (error) {
this.widget('console').bufferPush(error.message);
this.stdout(error.message);
}
}
@ -346,7 +341,7 @@ class AppGui {
// Any key after which a shortcut is not possible.
isSpecialKey(name) {
return ['ENTER', 'DOWN', 'UP', 'LEFT', 'RIGHT', 'DELETE', 'BACKSPACE', 'ESCAPE', 'TAB', 'SHIFT_TAB', 'PAGE_UP', 'PAGE_DOWN'].indexOf(name) >= 0;
return [':', 'ENTER', 'DOWN', 'UP', 'LEFT', 'RIGHT', 'DELETE', 'BACKSPACE', 'ESCAPE', 'TAB', 'SHIFT_TAB', 'PAGE_UP', 'PAGE_DOWN'].indexOf(name) >= 0;
}
fullScreen(enable = true) {
@ -360,6 +355,15 @@ class AppGui {
}
}
stdout(...object) {
for (let i = 0; i < object.length; i++) {
const v = typeof object[i] === 'object' ? JSON.stringify(object[i]) : object[i];
this.widget('console').addItem(v);
}
if (object.length) this.widget('statusBar').setItemAt(0, object[object.length-1]);
}
async start() {
const term = this.term();
@ -368,7 +372,7 @@ class AppGui {
try {
this.renderer_.start();
const consoleWidget = this.widget('console');
const statusBar = this.widget('statusBar');
term.grabInput();
@ -390,7 +394,7 @@ class AppGui {
if (name === 'CTRL_C' ) {
const cmd = this.app().currentCommand();
if (!cmd || !cmd.cancellable() || this.commandCancelCalled_) {
consoleWidget.bufferPush(_('Press Ctrl+D or type "exit" to exit the application'));
this.stdout(_('Press Ctrl+D or type "exit" to exit the application'));
} else {
this.commandCancelCalled_ = true;
await cmd.cancel();
@ -415,21 +419,34 @@ class AppGui {
this.lastShortcutKeyTime_ = now;
// Don't process shortcut keys if the console is active, except if the shortcut
// starts with CTRL (eg. CTRL+J CTRL+Z to maximize the console window).
if (!consoleWidget.hasFocus || (this.currentShortcutKeys_.length && this.currentShortcutKeys_[0].indexOf('CTRL') === 0)) {
this.logger().debug('Now: ' + name + ', Keys: ', this.currentShortcutKeys_);
if (name === ':' && !statusBar.promptActive) {
const cmd = await statusBar.prompt();
await this.processCommand(cmd);
} else {
// Don't process shortcut keys if the console is active, except if the shortcut
// starts with CTRL (eg. CTRL+J CTRL+Z to maximize the console window).
if (!statusBar.promptActive || (this.currentShortcutKeys_.length && this.currentShortcutKeys_[0].indexOf('CTRL') === 0)) {
this.logger().debug('Now: ' + name + ', Keys: ', this.currentShortcutKeys_);
const shortcutKey = this.currentShortcutKeys_.join('');
if (shortcutKey in this.shortcuts_) {
const cmd = this.shortcuts_[shortcutKey].action;
if (!cmd.isDocOnly) {
this.currentShortcutKeys_ = [];
if (typeof cmd === 'function') {
cmd();
} else {
consoleWidget.bufferPush(cmd);
await this.processCommand(cmd);
const shortcutKey = this.currentShortcutKeys_.join('');
if (shortcutKey in this.shortcuts_) {
const cmd = this.shortcuts_[shortcutKey].action;
if (!cmd.isDocOnly) {
this.currentShortcutKeys_ = [];
if (typeof cmd === 'function') {
await cmd();
} else if (typeof cmd === 'object') {
if (cmd.type === 'prompt') {
const commandString = await statusBar.prompt(cmd.initialText ? cmd.initialText : '');
this.stdout(commandString);
await this.processCommand(commandString);
} else {
throw new Error('Unknown command: ' + JSON.stringify(cmd));
}
} else {
this.stdout(cmd);
await this.processCommand(cmd);
}
}
}
}

View File

@ -270,12 +270,8 @@ class Application {
}
setupCommand(cmd) {
const consoleWidget = this.gui_.widget('console');
cmd.setStdout((...object) => {
for (let i = 0; i < object.length; i++) {
consoleWidget.bufferPush(object[i]);
}
this.gui().stdout(...object);
});
cmd.setDispatcher((action) => {
@ -283,15 +279,13 @@ class Application {
});
cmd.setPrompt(async (message, options) => {
consoleWidget.focus();
if (options.type == 'boolean') {
message += ' (' + options.answers.join('/') + ')';
}
var answer = await consoleWidget.waitForResult(message + ' ');
if (options.type == 'boolean') {
const answer = await this.gui().widget('statusBar').prompt('', message + ' ');
if (options.type === 'boolean') {
if (answer === null) return false;
return answer === '' || answer.toLowerCase() == options.answers[0].toLowerCase();
}

View File

@ -43,7 +43,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 this.prompt(_('%d notes match this pattern. Delete them?', notes.length));
const ok = force ? true : await this.prompt(notes.length > 1 ? _('%d notes match this pattern. Delete them?', notes.length) : _('Delete note?'));
if (!ok) return;
let ids = notes.map((n) => n.id);
await Note.batchDelete(ids);

View File

@ -0,0 +1,20 @@
const ListWidget = require('tkwidgets/ListWidget.js');
class ConsoleWidget extends ListWidget {
constructor() {
super();
}
get name() {
return 'console';
}
addItem(v) {
super.addItem(v);
this.currentIndex = this.items.length - 1;
}
}
module.exports = ConsoleWidget;

View File

@ -0,0 +1,112 @@
const BaseWidget = require('tkwidgets/BaseWidget.js');
const chalk = require('chalk');
class StatusBarWidget extends BaseWidget {
constructor() {
super();
this.promptState_ = null;
this.inputEventEmitter_ = null;
this.history_ = [];
this.items_ = [];
}
get name() {
return 'statusBar';
}
setItemAt(index, text) {
this.items_[index] = text;
this.invalidate();
}
async prompt(initialText = '', promptString = ':') {
if (this.promptState_) throw new Error('Another prompt already active');
this.root.globalDisableKeyboard(this);
this.promptState_ = {
promise: null,
initialText: initialText,
promptString: promptString,
};
this.promptState_.promise = new Promise((resolve, reject) => {
this.promptState_.resolve = resolve;
this.promptState_.reject = reject;
});
this.invalidate();
return this.promptState_.promise;
}
get promptActive() {
return !!this.promptState_;
}
get history() {
return this.history_;
}
render() {
super.render();
this.innerClear();
const textStyle = chalk.bgBlueBright.white;
this.term.drawHLine(this.absoluteInnerX, this.absoluteInnerY, this.innerWidth, textStyle(' '));
this.term.moveTo(this.absoluteInnerX, this.absoluteInnerY);
if (this.promptActive) {
this.term.write(textStyle(this.promptState_.promptString));
this.term.showCursor(true);
let options = {
cancelable: true,
history: this.history,
default: this.promptState_.initialText,
style: this.term.innerStyle.bgBrightBlue.white, // NOTE: Need to use TK style for this as inputField is not compatible with chalk
};
this.inputEventEmitter_ = this.term.inputField(options, (error, input) => {
let resolveResult = null;
const resolveFn = this.promptState_.resolve;
if (error) {
this.logger().error('StatusBar: inputField error:', error);
} else {
if (input === undefined) {
// User cancel
} else {
resolveResult = input;
if (input && input.trim() != '') this.history_.push(input);
}
}
this.inputEventEmitter_ = null;
this.term.showCursor(false);
this.promptState_ = null;
this.root.globalEnableKeyboard(this);
this.invalidate();
// Only callback once everything has been cleaned up and reset
resolveFn(resolveResult);
});
} else {
for (let i = 0; i < this.items_.length; i++) {
this.term.write(textStyle(this.items_[i]));
}
}
}
}
module.exports = StatusBarWidget;

View File

@ -27,10 +27,10 @@ msgstr ""
msgid "Exit the console"
msgstr ""
msgid "Create a new todo"
msgid "Create a new note"
msgstr ""
msgid "Create a new note"
msgid "Create a new todo"
msgstr ""
msgid "Create a new notebook"
@ -321,6 +321,9 @@ msgstr ""
msgid "%d notes match this pattern. Delete them?"
msgstr ""
msgid "Delete note?"
msgstr ""
msgid "Searches for the given <pattern> in all the notes."
msgstr ""
@ -630,9 +633,6 @@ msgstr ""
msgid "Cancel"
msgstr ""
msgid "Delete note?"
msgstr ""
msgid "Attach file"
msgstr ""

View File

@ -30,14 +30,14 @@ msgstr ""
msgid "Exit the console"
msgstr "Quitter le logiciel."
#, fuzzy
msgid "Create a new todo"
msgstr "Créer une nouvelle tâche."
#, fuzzy
msgid "Create a new note"
msgstr "Créer une note."
#, fuzzy
msgid "Create a new todo"
msgstr "Créer une nouvelle tâche."
#, fuzzy
msgid "Create a new notebook"
msgstr "Créer un carnet."
@ -359,6 +359,9 @@ msgstr "Supprime les objets sans demander la confirmation."
msgid "%d notes match this pattern. Delete them?"
msgstr "%d notes correspondent à ce motif. Les supprimer ?"
msgid "Delete note?"
msgstr "Supprimer la note ?"
msgid "Searches for the given <pattern> in all the notes."
msgstr "Chercher le motif <pattern> dans toutes les notes."
@ -690,9 +693,6 @@ msgstr ""
msgid "Cancel"
msgstr "Annulation..."
msgid "Delete note?"
msgstr "Supprimer la note ?"
msgid "Attach file"
msgstr "Attacher un fichier"
@ -744,6 +744,10 @@ msgstr ""
msgid "Welcome"
msgstr "Bienvenue"
#, fuzzy
#~ msgid "Last command: %s"
#~ msgstr "Commande invalide : \"%s\""
#~ msgid "Done editing."
#~ msgstr "Edition terminée."

View File

@ -27,10 +27,10 @@ msgstr ""
msgid "Exit the console"
msgstr ""
msgid "Create a new todo"
msgid "Create a new note"
msgstr ""
msgid "Create a new note"
msgid "Create a new todo"
msgstr ""
msgid "Create a new notebook"
@ -321,6 +321,9 @@ msgstr ""
msgid "%d notes match this pattern. Delete them?"
msgstr ""
msgid "Delete note?"
msgstr ""
msgid "Searches for the given <pattern> in all the notes."
msgstr ""
@ -630,9 +633,6 @@ msgstr ""
msgid "Cancel"
msgstr ""
msgid "Delete note?"
msgstr ""
msgid "Attach file"
msgstr ""