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

Handle globbing pattern for rm and ls

This commit is contained in:
Laurent Cozic 2017-06-25 13:49:46 +01:00
parent 62cdc30fc2
commit ac4718ac92
5 changed files with 89 additions and 34 deletions

View File

@ -75,6 +75,13 @@ async function main() {
// return;
// let testglob = await Note.glob('title', 'La *', {
// fields: ['title', 'updated_time'],
// });
// console.info(testglob);
@ -340,26 +347,37 @@ async function main() {
});
commands.push({
usage: 'rm <item-title>',
usage: 'rm <pattern>',
description: 'Deletes the given item. For a notebook, all the notes within that notebook will be deleted. Use `rm ../<notebook-name>` to delete a notebook.',
action: async function(args, end) {
let title = args['item-title'];
let pattern = args['pattern'];
let itemType = null;
if (title.substr(0, 3) == '../') {
itemType = BaseModel.MODEL_TYPE_FOLDER;
title = title.substr(3);
} else {
itemType = BaseModel.MODEL_TYPE_NOTE;
}
if (pattern.indexOf('*') < 0) { // Handle it as a simple title
if (pattern.substr(0, 3) == '../') {
itemType = BaseModel.MODEL_TYPE_FOLDER;
pattern = pattern.substr(3);
} else {
itemType = BaseModel.MODEL_TYPE_NOTE;
}
let item = await BaseItem.loadItemByField(itemType, 'title', title);
if (!item) return cmdError(this, _('No item with title "%s" found.', title), end);
await BaseItem.deleteItem(itemType, item.id);
let item = await BaseItem.loadItemByField(itemType, 'title', pattern);
if (!item) return cmdError(this, _('No item with title "%s" found.', pattern), end);
await BaseItem.deleteItem(itemType, item.id);
if (currentFolder && currentFolder.id == item.id) {
let f = await Folder.defaultFolder();
switchCurrentFolder(f);
if (currentFolder && currentFolder.id == item.id) {
let f = await Folder.defaultFolder();
switchCurrentFolder(f);
}
} else { // Handle it as a glob pattern
let notes = await Note.previews(currentFolder.id, { titlePattern: pattern });
if (!notes.length) return cmdError(this, _('No note matches this pattern: "%s"', pattern), end);
let ok = await cmdPromptConfirm(this, _('%d notes match this pattern. Delete them?', notes.length));
if (ok) {
for (let i = 0; i < notes.length; i++) {
await Note.delete(notes[i].id);
}
}
}
end();
@ -368,7 +386,7 @@ async function main() {
});
commands.push({
usage: 'ls [notebook-title]',
usage: 'ls [pattern]',
description: 'Displays the notes in [notebook-title]. Use `ls ..` to display the list of notebooks.',
options: [
['-n, --lines <num>', 'Displays only the first top <num> lines.'],
@ -377,7 +395,7 @@ async function main() {
['-t, --type <type>', 'Displays only the items of the specific type(s). Can be `n` for notes, `t` for todos, or `nt` for notes and todos (eg. `-tt` would display only the todos, while `-ttd` would display notes and todos.'],
],
action: async function(args, end) {
let folderTitle = args['notebook-title'];
let pattern = args['pattern'];
let suffix = '';
let items = [];
let options = args.options;
@ -395,22 +413,13 @@ async function main() {
if (options.type.indexOf('n') >= 0) queryOptions.itemTypes.push('note');
if (options.type.indexOf('t') >= 0) queryOptions.itemTypes.push('todo');
}
if (pattern) queryOptions.titlePattern = pattern;
if (folderTitle == '..') {
if (pattern == '..') {
items = await Folder.all(queryOptions);
suffix = '/';
} else {
let folder = null;
if (folderTitle) {
folder = await Folder.loadByField('title', folderTitle);
} else if (currentFolder) {
folder = currentFolder;
}
if (!folder) return cmdError(this, _('Unknown notebook: "%s"', folderTitle), end);
items = await Note.previews(folder.id, queryOptions);
items = await Note.previews(currentFolder.id, queryOptions);
}
for (let i = 0; i < items.length; i++) {

View File

@ -133,6 +133,7 @@ class BaseModel {
if (options.orderByDir) sql += ' ' + options.orderByDir;
}
if (options.limit) sql += ' LIMIT ' + options.limit;
//if (options.fields && options.fields.length) sql = sql.replace('SELECT *', 'SELECT ' + this.db().escapeFields(options.fields).join(','));
return { sql: sql, params: params };
}

View File

@ -167,6 +167,18 @@ class Database {
});
}
escapeField(field) {
return '`' + field + '`';
}
escapeFields(fields) {
let output = [];
for (let i = 0; i < fields.length; i++) {
output.push(this.escapeField(fields[i]));
}
return output;
}
selectOne(sql, params = null) {
this.logQuery(sql, params);
return this.driver().selectOne(sql, params).catch((error) => {
@ -285,8 +297,10 @@ class Database {
logQuery(sql, params = null) {
if (!this.debugMode()) return;
//console.info(sql, params);
this.logger().debug(sql);
if (params !== null) this.logger().debug(JSON.stringify(params));
if (params !== null && params.length) this.logger().debug(JSON.stringify(params));
}
static insertQuery(tableName, data) {

View File

@ -6,6 +6,7 @@ class Logger {
constructor() {
this.targets_ = [];
this.level_ = Logger.LEVEL_ERROR;
this.fileAppendQueue_ = []
}
setLevel(level) {
@ -64,14 +65,32 @@ class Logger {
} else {
serializedObject = object;
}
fs.appendFile(t.path, line + serializedObject + "\n", (error) => {
if (error) throw error;
this.fileAppendQueue_.push({
path: t.path,
line: line + serializedObject + "\n",
});
this.scheduleFileAppendQueueProcessing_();
}
}
}
scheduleFileAppendQueueProcessing_() {
if (this.fileAppendQueueTID_) return;
this.fileAppendQueueTID_ = setTimeout(async () => {
this.fileAppendQueueTID_ = null;
let queue = this.fileAppendQueue_.slice(0);
for (let i = 0; i < queue.length; i++) {
let t = queue[i];
await fs.appendFile(t.path, t.line);
}
this.fileAppendQueue_.splice(0, queue.length);
}, 10);
}
error(object) { return this.log(Logger.LEVEL_ERROR, object); }
warn(object) { return this.log(Logger.LEVEL_WARN, object); }
info(object) { return this.log(Logger.LEVEL_INFO, object); }

View File

@ -39,8 +39,12 @@ class Note extends BaseItem {
return output;
}
static previewFields() {
return ['id', 'title', 'body', 'is_todo', 'todo_completed', 'parent_id', 'updated_time'];
}
static previewFieldsSql() {
return '`id`, `title`, `body`, `is_todo`, `todo_completed`, `parent_id`, `updated_time`'
return this.db().escapeFields(this.previewFields()).join(',');
}
static previews(parentId, options = null) {
@ -49,6 +53,7 @@ class Note extends BaseItem {
if (!options.orderByDir) options.orderByDir = 'DESC';
let sql = 'SELECT ' + this.previewFieldsSql() + ' FROM notes WHERE is_conflict = 0 AND parent_id = ?';
let params = [parentId];
if (options.itemTypes && options.itemTypes.length) {
if (options.itemTypes.indexOf('note') >= 0 && options.itemTypes.indexOf('todo') >= 0) {
// Fetch everything
@ -58,7 +63,14 @@ class Note extends BaseItem {
sql += ' AND is_todo = 1';
}
}
let query = this.applySqlOptions(options, sql, [parentId]);
if (options.titlePattern) {
let pattern = options.titlePattern.replace(/\*/g, '%');
sql += ' AND title LIKE ?';
params.push(pattern);
}
let query = this.applySqlOptions(options, sql, params);
return this.modelSelectAll(query.sql, query.params);
}