diff --git a/nb b/nb index 11e472f18..50b596485 100755 --- a/nb +++ b/nb @@ -5317,6 +5317,7 @@ HEREDOC _list() { local _error_on_empty=0 local _excerpt_length=3 + local _folders_first="${NB_LIST_FOLDERS_FIRST:-0}" local _force_line_wrap=0 local _limit= local _line_wrap=1 @@ -5364,6 +5365,9 @@ _list() { _list_filenames=1 _recursive_arguments+=("--filenames") ;; + --folders-first|--ff|-ff|--f|-f) + _folders_first=1 + ;; --limit|-n|--num|--number|--per*) if _option_value_is_present "${2:-}" then @@ -5796,7 +5800,25 @@ _list() { if ! ((_only_pinned)) then - _list_files "${_list_path}" "${_list_files_options[@]:-}" || : + if ((_folders_first)) + then + _list_files "${_list_path}" "${_list_files_options[@]:-}" --type folder || : + + { + _list_files "${_list_path}" "${_list_files_options[@]:-}" || : + } | { + local __line= + while read -r __line + do + if [[ ! -d "${_list_path}/${__line}" ]] + then + printf "%s\\n" "${__line}" + fi + done + } + else + _list_files "${_list_path}" "${_list_files_options[@]:-}" || : + fi fi fi } | { @@ -6743,6 +6765,7 @@ _ls() { local _delegate_arguments=() local _fast_exit=0 local _filter_patterns=() + local _folders_first="${NB_LIST_FOLDERS_FIRST:-0}" local _header_flags=() local _limit= local _maybe_type= @@ -6777,6 +6800,9 @@ _ls() { --*exit*) _fast_exit=1 ;; + --folders-first|--ff|-ff|--f|-f) + _folders_first=1 + ;; -g|--gui) _delegate_to_browse=1 _delegate_arguments+=("${1}") @@ -6931,6 +6957,11 @@ _ls() { _list_options+=("--with-pinned") fi + if ((_folders_first)) + then + _list_options+=("--folders-first") + fi + local _selector_relative_path="${_selector#*:}" if [[ -n "${_limit:-}" ]] diff --git a/test/list.bats b/test/list.bats index e1dd2f107..db7b3540b 100644 --- a/test/list.bats +++ b/test/list.bats @@ -2,6 +2,225 @@ load test_helper +# folders first ############################################################### + +@test "'list --folders-first' prints folders first while preserving pinning." { + { + "${_NB}" init + + "${_NB}" add "File One.md" --content "Example content one." + "${_NB}" folder add "Folder One" + "${_NB}" add "File Two.md" --content "Example content two." + "${_NB}" add "File Three.md" --content "Example content three." + "${_NB}" folder add "Folder Two" + "${_NB}" add "File Four.md" --content "Example content four." + "${_NB}" folder add "Folder Three" + + "${_NB}" pin "Folder Two" + "${_NB}" pin "File Three.md" + } + + run "${_NB}" list --with-pinned + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 7 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搶\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*4.*].*\ 馃搶\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[2]}" =~ \ +.*[.*7.*].*\ 馃搨\ Folder\ Three ]] + [[ "${lines[3]}" =~ \ +.*[.*6.*].*\ File\ Four\.md\ \路\ \"Example\ content\ four\.\" ]] + [[ "${lines[4]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + [[ "${lines[5]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[6]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] + + run "${_NB}" list --folders-first --with-pinned + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 7 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搶\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*4.*].*\ 馃搶\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[2]}" =~ \ +.*[.*7.*].*\ 馃搨\ Folder\ Three ]] + [[ "${lines[3]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[4]}" =~ \ +.*[.*6.*].*\ File\ Four\.md\ \路\ \"Example\ content\ four\.\" ]] + [[ "${lines[5]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + + [[ "${lines[6]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] +} + +@test "'list --folders-first' prints folders first." { + { + "${_NB}" init + + "${_NB}" add "File One.md" --content "Example content one." + "${_NB}" folder add "Folder One" + "${_NB}" add "File Two.md" --content "Example content two." + "${_NB}" add "File Three.md" --content "Example content three." + "${_NB}" folder add "Folder Two" + } + + run "${_NB}" list + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 5 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*4.*].*\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[2]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + [[ "${lines[3]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[4]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] + + run "${_NB}" list --folders-first + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 5 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[2]}" =~ \ +.*[.*4.*].*\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[3]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + + [[ "${lines[4]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] +} + +@test "'list --ff' prints folders first." { + { + "${_NB}" init + + "${_NB}" add "File One.md" --content "Example content one." + "${_NB}" folder add "Folder One" + "${_NB}" add "File Two.md" --content "Example content two." + "${_NB}" add "File Three.md" --content "Example content three." + "${_NB}" folder add "Folder Two" + } + + run "${_NB}" list + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 5 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*4.*].*\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[2]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + [[ "${lines[3]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[4]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] + + run "${_NB}" list --ff + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 5 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[2]}" =~ \ +.*[.*4.*].*\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[3]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + + [[ "${lines[4]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] +} + +@test "'NB_LIST_FOLDERS_FIRST=1 list' prints folders first." { + { + "${_NB}" init + + "${_NB}" add "File One.md" --content "Example content one." + "${_NB}" folder add "Folder One" + "${_NB}" add "File Two.md" --content "Example content two." + "${_NB}" add "File Three.md" --content "Example content three." + "${_NB}" folder add "Folder Two" + } + + run "${_NB}" list + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 5 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*4.*].*\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[2]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + [[ "${lines[3]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[4]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] + + NB_LIST_FOLDERS_FIRST=1 run "${_NB}" list + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 5 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[2]}" =~ \ +.*[.*4.*].*\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[3]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + + [[ "${lines[4]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] +} + # filename handling ########################################################### @test "'list' prints normally with uncommon filenames." { diff --git a/test/ls.bats b/test/ls.bats index 685e2a81a..eccbe9a13 100644 --- a/test/ls.bats +++ b/test/ls.bats @@ -25,6 +25,183 @@ line four HEREDOC } +# folders first ############################################################### + +@test "'ls --folders-first' prints folders first while preserving pinning." { + { + "${_NB}" init + + "${_NB}" add "File One.md" --content "Example content one." + "${_NB}" folder add "Folder One" + "${_NB}" add "File Two.md" --content "Example content two." + "${_NB}" add "File Three.md" --content "Example content three." + "${_NB}" folder add "Folder Two" + "${_NB}" add "File Four.md" --content "Example content four." + "${_NB}" folder add "Folder Three" + + "${_NB}" pin "Folder Two" + "${_NB}" pin "File Three.md" + + export NB_FOOTER=0 + export NB_HEADER=0 + } + + run "${_NB}" ls + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 7 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搶\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*4.*].*\ 馃搶\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[2]}" =~ \ +.*[.*7.*].*\ 馃搨\ Folder\ Three ]] + [[ "${lines[3]}" =~ \ +.*[.*6.*].*\ File\ Four\.md\ \路\ \"Example\ content\ four\.\" ]] + [[ "${lines[4]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + [[ "${lines[5]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[6]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] + + run "${_NB}" ls --folders-first + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 7 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搶\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*4.*].*\ 馃搶\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[2]}" =~ \ +.*[.*7.*].*\ 馃搨\ Folder\ Three ]] + [[ "${lines[3]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[4]}" =~ \ +.*[.*6.*].*\ File\ Four\.md\ \路\ \"Example\ content\ four\.\" ]] + [[ "${lines[5]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + + [[ "${lines[6]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] +} + +@test "'ls --folders-first' prints folders first." { + { + "${_NB}" init + + "${_NB}" add "File One.md" --content "Example content one." + "${_NB}" folder add "Folder One" + "${_NB}" add "File Two.md" --content "Example content two." + "${_NB}" add "File Three.md" --content "Example content three." + "${_NB}" folder add "Folder Two" + + export NB_FOOTER=0 + export NB_HEADER=0 + } + + run "${_NB}" ls + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 5 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*4.*].*\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[2]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + [[ "${lines[3]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[4]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] + + run "${_NB}" ls --folders-first + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 5 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[2]}" =~ \ +.*[.*4.*].*\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[3]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + + [[ "${lines[4]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] +} + +@test "'NB_LIST_FOLDERS_FIRST=1 ls' prints folders first." { + { + "${_NB}" init + + "${_NB}" add "File One.md" --content "Example content one." + "${_NB}" folder add "Folder One" + "${_NB}" add "File Two.md" --content "Example content two." + "${_NB}" add "File Three.md" --content "Example content three." + "${_NB}" folder add "Folder Two" + + export NB_FOOTER=0 + export NB_HEADER=0 + } + + run "${_NB}" ls + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 5 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*4.*].*\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[2]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + [[ "${lines[3]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[4]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] + + NB_LIST_FOLDERS_FIRST=1 run "${_NB}" ls + + printf "\${status}: '%s'\\n" "${status}" + printf "\${output}: '%s'\\n" "${output}" + + [[ "${status}" -eq 0 ]] + [[ "${#lines[@]}" -eq 5 ]] + + [[ "${lines[0]}" =~ \ +.*[.*5.*].*\ 馃搨\ Folder\ Two ]] + [[ "${lines[1]}" =~ \ +.*[.*2.*].*\ 馃搨\ Folder\ One ]] + [[ "${lines[2]}" =~ \ +.*[.*4.*].*\ File\ Three\.md\ \路\ \"Example\ content\ three\.\" ]] + [[ "${lines[3]}" =~ \ +.*[.*3.*].*\ File\ Two\.md\ \路\ \"Example\ content\ two\.\" ]] + + [[ "${lines[4]}" =~ \ +.*[.*1.*].*\ File\ One\.md\ \路\ \"Example\ content\ one\.\" ]] +} + # tags ######################################################################## @test "'--tags' exits with status 0 and prints tags in the current notebook." {