2023-12-20 21:08:07 +02:00
import BaseCommand from './base-command' ;
2024-01-20 16:29:21 +02:00
import app from './app' ;
2023-12-20 21:08:07 +02:00
import { _ } from '@joplin/lib/locale' ;
import BaseModel from '@joplin/lib/BaseModel' ;
import Folder from '@joplin/lib/models/Folder' ;
import Setting from '@joplin/lib/models/Setting' ;
import Note from '@joplin/lib/models/Note' ;
2017-11-03 02:09:34 +02:00
const { sprintf } = require ( 'sprintf-js' ) ;
2023-12-20 21:08:07 +02:00
import time from '@joplin/lib/time' ;
2024-03-02 16:25:27 +02:00
import { NoteEntity } from '@joplin/lib/services/database/types' ;
2017-11-03 02:09:34 +02:00
const { cliUtils } = require ( './cli-utils.js' ) ;
2017-07-10 22:03:46 +02:00
class Command extends BaseCommand {
2023-12-20 21:08:07 +02:00
public override usage() {
2017-08-04 18:02:43 +02:00
return 'ls [note-pattern]' ;
2017-07-10 22:03:46 +02:00
}
2023-12-20 21:08:07 +02:00
public override description() {
2017-08-04 18:02:43 +02:00
return _ ( 'Displays the notes in the current notebook. Use `ls /` to display the list of notebooks.' ) ;
2017-07-10 22:03:46 +02:00
}
2017-10-24 23:37:36 +02:00
2023-12-20 21:08:07 +02:00
public override enabled() {
2020-03-08 11:17:10 +02:00
return true ;
2017-10-24 23:37:36 +02:00
}
2018-09-04 06:42:22 +02:00
2023-12-20 21:08:07 +02:00
public override options() {
2020-03-08 11:17:10 +02:00
return [
[ '-n, --limit <num>' , _ ( 'Displays only the first top <num> notes.' ) ] ,
[ '-s, --sort <field>' , _ ( 'Sorts the item by <field> (eg. title, updated_time, created_time).' ) ] ,
[ '-r, --reverse' , _ ( 'Reverses the sorting order.' ) ] ,
2021-02-24 08:23:13 +02:00
[ '-t, --type <type>' , _ ( 'Displays only the items of the specific type(s). Can be `n` for notes, `t` for to-dos, or `nt` for notes and to-dos (eg. `-tt` would display only the to-dos, while `-tnt` would display notes and to-dos.' ) ] ,
2020-03-08 11:17:10 +02:00
[ '-f, --format <format>' , _ ( 'Either "text" or "json"' ) ] ,
[ '-l, --long' , _ ( 'Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, TODO_CHECKED (for to-dos), TITLE' ) ] ,
] ;
2017-07-10 22:03:46 +02:00
}
2023-12-20 21:08:07 +02:00
public override async action ( args : any ) {
2020-03-14 01:46:14 +02:00
const pattern = args [ 'note-pattern' ] ;
2017-07-10 22:03:46 +02:00
let items = [ ] ;
2020-03-14 01:46:14 +02:00
const options = args . options ;
2017-07-10 22:03:46 +02:00
2023-12-20 21:08:07 +02:00
const queryOptions : any = { } ;
2017-07-10 22:47:01 +02:00
if ( options . limit ) queryOptions . limit = options . limit ;
2017-07-10 22:03:46 +02:00
if ( options . sort ) {
queryOptions . orderBy = options . sort ;
queryOptions . orderByDir = 'ASC' ;
}
2022-07-23 09:31:32 +02:00
if ( options . reverse === true ) queryOptions . orderByDir = queryOptions . orderByDir === 'ASC' ? 'DESC' : 'ASC' ;
2017-07-10 22:03:46 +02:00
queryOptions . caseInsensitive = true ;
if ( options . type ) {
queryOptions . itemTypes = [ ] ;
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 ;
2017-07-31 21:47:58 +02:00
queryOptions . uncompletedTodosOnTop = Setting . value ( 'uncompletedTodosOnTop' ) ;
2017-07-10 22:03:46 +02:00
2017-07-12 22:39:47 +02:00
let modelType = null ;
2022-07-23 09:31:32 +02:00
if ( pattern === '/' || ! app ( ) . currentFolder ( ) ) {
2017-07-15 17:35:40 +02:00
queryOptions . includeConflictFolder = true ;
2017-07-10 22:03:46 +02:00
items = await Folder . all ( queryOptions ) ;
2017-07-12 22:39:47 +02:00
modelType = Folder . modelType ( ) ;
2017-07-10 22:03:46 +02:00
} else {
if ( ! app ( ) . currentFolder ( ) ) throw new Error ( _ ( 'Please select a notebook first.' ) ) ;
items = await Note . previews ( app ( ) . currentFolder ( ) . id , queryOptions ) ;
2017-07-12 22:39:47 +02:00
modelType = Note . modelType ( ) ;
2017-07-10 22:03:46 +02:00
}
2022-07-23 09:31:32 +02:00
if ( options . format && options . format === 'json' ) {
2017-10-07 18:30:27 +02:00
this . stdout ( JSON . stringify ( items ) ) ;
2017-07-10 22:03:46 +02:00
} else {
2017-07-12 22:39:47 +02:00
let hasTodos = false ;
for ( let i = 0 ; i < items . length ; i ++ ) {
2020-03-14 01:46:14 +02:00
const item = items [ i ] ;
2024-03-02 16:25:27 +02:00
if ( ( item as NoteEntity ) . is_todo ) {
2017-07-12 22:39:47 +02:00
hasTodos = true ;
break ;
}
}
2020-03-14 01:46:14 +02:00
const seenTitles = [ ] ;
const rows = [ ] ;
2017-07-17 20:46:09 +02:00
let shortIdShown = false ;
2017-07-10 22:03:46 +02:00
for ( let i = 0 ; i < items . length ; i ++ ) {
2020-03-14 01:46:14 +02:00
const item = items [ i ] ;
const row = [ ] ;
2017-07-12 22:39:47 +02:00
if ( options . long ) {
2017-07-17 20:46:09 +02:00
row . push ( BaseModel . shortId ( item . id ) ) ;
shortIdShown = true ;
2022-07-23 09:31:32 +02:00
if ( modelType === Folder . modelType ( ) ) {
2017-07-12 22:39:47 +02:00
row . push ( await Folder . noteCount ( item . id ) ) ;
}
2018-09-05 00:03:21 +02:00
row . push ( time . formatMsToLocal ( item . user_updated_time ) ) ;
2017-07-10 22:03:46 +02:00
}
2017-07-10 22:47:01 +02:00
2017-07-30 21:51:18 +02:00
let title = item . title ;
2017-07-17 20:46:09 +02:00
if ( ! shortIdShown && ( seenTitles . indexOf ( item . title ) >= 0 || ! item . title ) ) {
2019-09-19 23:51:18 +02:00
title += ` ( ${ BaseModel . shortId ( item . id ) } ) ` ;
2017-07-10 22:47:01 +02:00
} else {
seenTitles . push ( item . title ) ;
}
2017-07-12 22:39:47 +02:00
if ( hasTodos ) {
2024-03-02 16:25:27 +02:00
if ( ( item as NoteEntity ) . is_todo ) {
row . push ( sprintf ( '[%s]' , ( item as NoteEntity ) . todo_completed ? 'X' : ' ' ) ) ;
2017-07-12 22:39:47 +02:00
} else {
row . push ( ' ' ) ;
}
}
row . push ( title ) ;
rows . push ( row ) ;
2017-07-10 22:03:46 +02:00
}
2017-07-12 22:39:47 +02:00
2017-10-09 22:45:20 +02:00
cliUtils . printArray ( this . stdout . bind ( this ) , rows ) ;
2017-07-10 22:03:46 +02:00
}
}
}
2018-09-04 06:42:22 +02:00
module .exports = Command ;