#!/usr/bin/env bash
###############################################################################
# __          _
# \ \   _ __ | |__
#  \ \ | '_ \| '_ \
#  / / | | | | |_) |
# /_/  |_| |_|_.__/
#
# [nb] Command line and local web note-taking, bookmarking, and archiving with
# plain text data storage, encryption, filtering and search, pinning, #tagging,
# Git-backed versioning and syncing, Pandoc-backed conversion, global and local
# notebooks, customizable color themes, [[wiki-style linking]], plugins, and
# more in a single portable, user-friendly script.
#
# ❯ https://github.com/xwmx/nb
# ❯ https://xwmx.github.io/nb
#
# Based on Bash Boilerplate: https://github.com/xwmx/bash-boilerplate
#
# Copyright (c) 2015-present William Melody ┯ hi@williammelody.com
#                                           ┕ https://www.williammelody.com
#
# Overview
# ========
#
# - Configuration and Setup
# - Helpers: Group 1 (alphabetical order)
# - Subcommands: Group 1 (alphabetical order)
# - Plugins
# - Option Parsing
# - _main() / Dispatch
# - Configuration: Group 2
# - Helpers: Group 2 (alphabetical order)
# - Subcommands: Group 2 (alphabetical order)
# - Subcommands: Group 3 (alphabetical order)
#
# Target Bash Version:              5   (target,   recommended)
# Minimum Recommended Bash Version: 4   (fallback, recommended)
# Minimum Tested Bash Version:      3.2 (fallback, deprecated)
#
# AGPLv3
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
###############################################################################

###############################################################################
# Shell Options & Strict Mode
#
# More Information:
#   https://github.com/xwmx/bash-boilerplate#bash-strict-mode
#   https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
#   https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html
#   https://tldp.org/LDP/abs/html/options.html
###############################################################################

set -o errexit
set -o noglob
set -o nounset
set -o pipefail

set +o noclobber

shopt -s extglob

IFS=$'\n\t'

###############################################################################
# Environment
###############################################################################

# $_VERSION
#
# The most recent program version.
_VERSION="7.25.1"

# $_ME
#
# This program's basename.
_ME="$(basename "${0}")"

# $_MY_DIR
#
# The directory containing $_ME.
_MY_DIR="$(cd "$(dirname "${0}")"; pwd)"

# $_MY_PATH
#
# This program's full path.
_MY_PATH="${_MY_DIR}/${_ME}"

# $_CURRENT_WORKING_DIR
#
# The current working directory in which the program was invoked.
_CURRENT_WORKING_DIR="${PWD}"

# $_REPO
#
# The <user>/<repo> identifier for this project's git repository.
_REPO="xwmx/nb"

# $_REPO_MAIN_BRANCH
#
# The name of the main branch in this project's git repository.
_REPO_MAIN_BRANCH="master"

# $_REPO_RAW_URL
#
# The base URL for raw files.
_REPO_RAW_URL="https://raw.githubusercontent.com/${_REPO}/${_REPO_MAIN_BRANCH}"

###############################################################################
# Utilities
###############################################################################

# _command_exists()
#
# Usage:
#   _command_exists <name>
#
# Exit / Error / Return Status:
#   0 (success, true) If a command <name> is defined in the current environment.
#   1 (error,  false) If not.
#
# More Information:
#   http://stackoverflow.com/a/677212
_command_exists() {
  if [[ "${1:-}" == "w3m" ]]
  then # Detect WSL 1 (https://stackoverflow.com/a/38859331), where w3m errors.
    [[ -f /proc/version ]] && grep -q Micro /proc/version && return 1
  fi

  hash "${1}" 2>/dev/null
}

# _contains()
#
# Usage:
#   _contains <query> <list-item>...
#
# Exit / Error / Return Status:
#   0 (success, true)  If the item is included in the list.
#   1 (error,  false)  If not.
#
# Example:
#   _contains "${_query}" "${_list[@]}"
_contains() {
  local _query="${1:-}"

  shift

  if [[ -z "${_query}"  ]] ||
     [[ -z "${*:-}"     ]]
  then
    return 1
  fi

  local __element=
  for   __element in "${@}"
  do
    [[ "${__element}" == "${_query}" ]] && return 0
  done

  return 1
}

# _resolve_symlink()
#
# Usage:
#   _resolve_symlink <path>
#
# Description:
#   Resolve the real path or target for a symbolic link.
_resolve_symlink() {
  if hash "realpath" 2>/dev/null
  then
    realpath "${@:-}"
  else
    readlink "${@:-}"
  fi
}

# _sed_i()
#
# Usage:
#   _sed_i <sed-argument>...
#
# Description:
#   `sed -i` takes an extension on macOS, but that extension can cause errors
#   in GNU `sed`. Detect which `sed` is available and call it with the
#   appropriate arguments.
#
# More Information:
#   https://stackoverflow.com/q/43171648
#   https://stackoverflow.com/a/16746032
_sed_i() {
  local _usage=

  if _usage="$(sed --help 2>&1 || false)"
  then # GNU
    sed -i      "${@}"
  else # BSD
    if [[ "${_usage:-}" =~ unknown\ option ]]
    then # OpenBSD
      sed -i''  "${@}"
    else # FreeBSD, macOS
      sed -i '' "${@}"
    fi
  fi
}

# _tput()
#
# Usage:
#   _tput <tput options>...
#
# Description:
#   Run `tput` commands, with fallbacks to termcap names for FreeBSD and
#   `stty` and escape sequences when `tput` is not found.
_tput() {
  if _command_exists "tput"
  then
    # More info: https://stackoverflow.com/a/64214019
    case "${1:-}" in
      cols)
        if tput cols  &>/dev/null
        then
          tput cols
        elif tput co  &>/dev/null
        then
          tput co
        else
          printf "80\\n"
        fi

        return 0
        ;;
      lines)
        if tput lines &>/dev/null
        then
          tput lines
        elif tput li  &>/dev/null
        then
          tput li
        else
          printf "20\\n"
        fi

        return 0
        ;;
      setaf|smul)
        ((${_COLOR_ENABLED:-1}))  || return 0
        ;;
    esac

    tput "${@:-}" 2>/dev/null     || {
      case "${1:-}" in
        sgr0)
          tput me
          ;;
        smul)
          tput us
          ;;
        setaf)
          tput AF "${@:2}"
          ;;
      esac
    } 2>/dev/null || printf ""
  else
    case "${1:-}" in
      cols|lines)
        {
          stty size 2>/dev/null   || printf "20 80\\n"
        } | if [[ "${1:-}" == "cols" ]]
            then
              cut -d " " -f 2
            else
              cut -d " " -f 1
            fi
        ;;
      setaf)
        printf '\033[38;5;%sm'  "${2:-}"
        ;;
      sgr0)
        printf '\033[m'
        ;;
      smul)
        printf '\033[4m'
        ;;
    esac
  fi
}

###############################################################################
# Debug
###############################################################################

# _debug()
#
# Usage:
#   _debug <command> <options>...
#
# Description:
#   Execute a command and print to standard error. The command is expected to
#   print a message and should typically be either `echo`, `printf`, or `cat`.
#
# Example:
#   _debug printf "Debug info. Variable: %s\\n" "$0"
__DEBUG_COUNTER=0
__DEBUG_START_TIME=
_debug() {
  # Usage: __debug_get_timestamp
  __debug_get_timestamp() {
    if hash "gdate" 2>/dev/null
    then
      gdate +%s%3N
    elif date --version >/dev/null 2>&1
    then
      date +%s%3N
    else
      return 1
    fi
  }

  if ((${_USE_DEBUG:-0}))
  then
    __DEBUG_COUNTER=$((__DEBUG_COUNTER+1))
    printf "🐛  %s" "${__DEBUG_COUNTER} "

    "${@}"

    if [[ -n "${__DEBUG_START_TIME:-}" ]]
    then
      printf "⏱  %s\\n" "$(($(__debug_get_timestamp)-__DEBUG_START_TIME))"
    elif __DEBUG_START_TIME="$(__debug_get_timestamp)"
    then
      printf "⏱  0\\n"
    fi

    printf "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――\\n"
  fi 1>&2
}

###############################################################################
# Error Messages
###############################################################################

# _exit_1()
#
# Usage:
#   _exit_1 <command>
#
# Description:
#   Exit with status 1 after executing the specified command with output
#   redirected to standard error. The command is expected to print a message
#   and should typically be either `echo`, `printf`, or `cat`.
_exit_1() {
  {
    [[ "${1:-}" == "_help" ]] || printf "%s " "$(_tput setaf 1)!$(_tput sgr0)"

    "${@}"
  } 1>&2

  exit 1
}

# _warn()
#
# Usage:
#   _warn <command>
#
# Description:
#   Print the specified command with output redirected to standard error.
#   The command is expected to print a message and should typically be either
#   `echo`, `printf`, or `cat`.
_warn() {
  {
    printf "%s " "$(_tput setaf 1)!$(_tput sgr0)"

    "${@}"
  } 1>&2
}

###############################################################################
# Option Helpers
###############################################################################

# _option_get_value()
#
# Usage:
#   _option_get_value <option> <value>
#
# Description:
#   Given a flag (e.g., -e | --example) return the value or exit 1 if value
#   is blank or appears to be another option.
_option_get_value() {
  local _option="${1:-}"
  local _value="${2:-}"

  if [[ -n "${_value:-}" ]] && [[ ! "${_value:-}" =~ ^- ]]
  then
    {
      printf "%s\\n" "${_value}"
    } | {
      if _command_exists "iconv"
      then
        iconv -c -t utf-8
      else
        cat
      fi
    }
  else
    _exit_1 printf                          \
      "%s requires a valid argument.\\n"    \
      "$(_color_primary "${_option}")"
  fi
}

# _option_value_is_present()
#
# Usage:
#   _option_value_is_present <value>
#
# Exit / Error / Return Status:
#   0 (success, true)  The argument is present and does not match as an option
#                      flag.
#   1 (error,  false)  The argument is blank or matches as an option flag.
_option_value_is_present() {
  [[ -n "${1:-}" ]] && [[ ! "${1:-}" =~ ^-  ]]
}

###############################################################################
# Configuration
###############################################################################

# Configuration File ####################################### Configuration File

# $NBRC_PATH
#
# Default: `$HOME/.nbrc`
#
# The location of the .nbrc configuration file.
export NBRC_PATH="${NBRC_PATH:-"${HOME}/.${_ME}rc"}"

# Handle symlinked NBRC_PATH.
if [[ -L "${NBRC_PATH}" ]]
then
  NBRC_PATH="$(_resolve_symlink "${NBRC_PATH}")"
fi

# Source rc file.
if [[ -e "${NBRC_PATH}" ]]
then
  source "${NBRC_PATH}"
fi

# NB_DIR ############################################################### NB_DIR

# $NB_DIR
#
# Default: `$HOME/.nb`
#
# The location of the directory that contains the notebooks.
export NB_DIR="${NB_DIR:-"${HOME}/.${_ME}"}"

# Handle symlinked NB_DIR.
if [[ -L "${NB_DIR:-}"      ]]
then
  NB_DIR="$(_resolve_symlink "${NB_DIR}")"
fi

# Validate that NB_DIR exists and is writable.
if [[ -z "${NB_DIR:?}"      ]] ||
   [[    "${NB_DIR}" == "/" ]] ||
   {
     [[   -e "${NB_DIR}"    ]] &&
     [[ ! -w "${NB_DIR}"    ]]
   }
then
  _exit_1 cat <<HEREDOC
NB_DIR is not valid:
  ${NB_DIR}

Remove any NB_DIR settings in .${_ME}rc to reset to default:
  ${NBRC_PATH}

NB_DIR settings prompt:
  ${_ME} settings nb_dir
HEREDOC
fi

# Current Notebook ########################################### Current Notebook

# $NB_NOTEBOOK_PATH
#
# Default: ''
#
# The path to the current notebook.
export NB_NOTEBOOK_PATH="${NB_NOTEBOOK_PATH:-}"

# $_GLOBAL_NOTEBOOK_PATH
#
# The path of the current global notebook.
export _GLOBAL_NOTEBOOK_PATH=

# $_LOCAL_NOTEBOOK_PATH
#
# The path of the local notebook, if one is found. The current working
# directory and all parents are searched.
export _LOCAL_NOTEBOOK_PATH=

# __set_notebook_paths()
#
# Usage:
#   __set_notebook_paths
#
# Description:
#   Set the notebook path variables to reflect the current environment.
__set_notebook_paths() {
  __set_local_notebook_path() {
    if [[ "${PWD}" == "/" ]]
    then
      cd "${_CURRENT_WORKING_DIR}"

      return 0
    elif [[ -d "${PWD}/.git"    ]] &&
         [[ -f "${PWD}/.index"  ]]
    then
      _LOCAL_NOTEBOOK_PATH="${PWD}"

      cd "${_CURRENT_WORKING_DIR}"

      return 0
    else
      cd ..
      __set_local_notebook_path
    fi
  }; __set_local_notebook_path

  __set_global_notebook_path() {
    if [[ -n "${NB_NOTEBOOK_PATH:-}"  ]]
    then
      _GLOBAL_NOTEBOOK_PATH="${NB_NOTEBOOK_PATH}"
    elif [[ -e "${NB_DIR}/.current"   ]]
    then
      local _global_notebook_name=
      _global_notebook_name="$(<"${NB_DIR}/.current")"

      if [[ -d "${NB_DIR}/${_global_notebook_name}" ]]
      then
        _GLOBAL_NOTEBOOK_PATH="${NB_DIR}/${_global_notebook_name}"
      fi
    else
      _GLOBAL_NOTEBOOK_PATH="${NB_DIR}/home"
    fi
  }; __set_global_notebook_path

  if [[ -n "${_LOCAL_NOTEBOOK_PATH:-}" ]]
  then
    NB_NOTEBOOK_PATH="${_LOCAL_NOTEBOOK_PATH}"
  else
    NB_NOTEBOOK_PATH="${_GLOBAL_NOTEBOOK_PATH}"
  fi
}; __set_notebook_paths

# Source notebook configuration file.

if [[ -e "${NB_NOTEBOOK_PATH}/.nbrc" ]]
then
  # shellcheck disable=SC1091
  source "${NB_NOTEBOOK_PATH}/.nbrc"
fi

# Base Configuration ####################################### Base Configuration

# $NB_AUDIO_TOOL
#
# Default: '' (first available)
#
# Example Values: 'mplayer', 'afplay'
export NB_AUDIO_TOOL="${NB_AUDIO_TOOL:-}"

# $NB_AUTO_SYNC
#
# Default: '1'
#
# When set to '1', each `_git checkpoint()` call will automativally run
# `$_ME sync`. To disable this behavior, set the value to '0'.
export NB_AUTO_SYNC="${NB_AUTO_SYNC:-1}"

# $NB_AUTO_SYNC_SECONDS
#
# Default: '60'
#
# The minimum number of seconds between automatic Git sync operations when
# `$NB_AUTO_SYNC` is enabled.
export NB_AUTO_SYNC_SECONDS="${NB_AUTO_SYNC_SECONDS:-60}"

# $NB_BROWSER
#
# Default: value of $BROWSER
#
# Example Values: 'links', 'w3m'
export NB_BROWSER="${NB_BROWSER:-${BROWSER:-}}"

# $NB_DATA_TOOL
#
# Default: '' (first available)
#
# Example Values: 'visidata', 'sc-im'
export NB_DATA_TOOL="${NB_DATA_TOOL:-}"

# $NB_DEFAULT_EXTENSION
#
# Default: 'md'
#
# Example Values: 'md' 'org'
export NB_DEFAULT_EXTENSION="${NB_DEFAULT_EXTENSION:-md}"

# $NB_DEFAULT_TEMPLATE
#
# Default: ''
#
# A string template or a path to a template file.
#
# Example Values: '/path/to/template/file' '# {{title}} {{content}}'
export NB_DEFAULT_TEMPLATE="${NB_DEFAULT_TEMPLATE:-}"

# $NB_DIRECTORY_TOOL
#
# Default: '' (nb browse)
#
# Example Values: 'ranger', 'mc'
export NB_DIRECTORY_TOOL="${NB_DIRECTORY_TOOL:-}"

# $NB_ENCRYPTION_TOOL
#
# Default: 'openssl'
#
# Supported Values: 'gpg' 'openssl'
export NB_ENCRYPTION_TOOL="${NB_ENCRYPTION_TOOL:-openssl}"

# $NB_FOOTER
#
# Default: '1'
#
# Supported Values: '0' '1'
export NB_FOOTER="${NB_FOOTER:-1}"

# $NB_GUI_BROWSER
#
# Default: ''
#
# Example Value: 'firefox'
export NB_GUI_BROWSER="${NB_GUI_BROWSER:-}"

# $NB_HEADER
#
# Default: '2'
#
# Supported Values: '0' '1' '2' '3'
export NB_HEADER="${NB_HEADER:-2}"

# $NB_IMAGE_TOOL
#
# Default: '' (first available)
#
# Example Values: 'imgcat', 'catimg'
export NB_IMAGE_TOOL="${NB_IMAGE_TOOL:-}"

# $NB_SERVER_HOST
#
# Default: 'localhost'
export NB_SERVER_HOST="${NB_SERVER_HOST:-localhost}"

# $NB_SERVER_PORT
#
# Default: '6789'
export NB_SERVER_PORT="${NB_SERVER_PORT:-6789}"

# $NB_SYNTAX_THEME
#
# Default: 'base16'
#
# Supported Values: Theme names listed with `bat --list-themes`
export NB_SYNTAX_THEME="${NB_SYNTAX_THEME:-base16}"

# $_GIT_ENABLED
#
# Default: '1'
#
# Supported Values: '0' '1'
export _GIT_ENABLED="${_GIT_ENABLED:-1}"

# limit ################################################################# limit

# $NB_LIMIT
#
# Default: '15'
#
# Set to a positive number to limit the output of `nb` and `nb ls` to that value.
# Set to "auto" to automatically limit output to the current terminal height.
# Set a maximum auto limit with `auto^<max>`, e.g., `auto^15`.
# Subtract an auto limit offset for multiline prompts with `auto-<offset>`.
# Add an auto limit offet with `auto+<offset>`.
# Combine both modifiers with `auto-<offset>^<max>` or `auto+<offset>^<max>`.
#
# Supported Values:
#   - <max>
#   - auto
#   - auto^<max>
#   - auto-<offset>
#   - auto+<offset>
#   - auto-<offset>^<max>
#   - auto+<offset>^<max>
#
# Example Values:
#   - 15
#   - auto
#   - auto^15
#   - auto-2
#   - auto+2
#   - auto-2^15
#   - auto+2^15

export _AUTO_LIMIT=
export _AUTO_LIMIT_MAX=

case "${NB_LIMIT:-}" in
  auto*)
    _AUTO_LIMIT="${NB_LIMIT#auto}"
    _AUTO_LIMIT="${_AUTO_LIMIT%^*}"
    _AUTO_LIMIT="${_AUTO_LIMIT:-0}"

    if [[ "${NB_LIMIT:-}" =~ \^     ]]
    then
      _AUTO_LIMIT_MAX="${NB_LIMIT#*^}"
    fi

    export NB_LIMIT="${NB_LIMIT}"
    ;;
  *)
    export _AUTO_LIMIT=
    export NB_LIMIT="${NB_LIMIT:-15}"
  ;;
esac

# $EDITOR ############################################################# $EDITOR

# $NB_EDITOR
#
# Default: value of $EDITOR or $VISUAL
#
# Example Values: 'vim', `code`'
NB_EDITOR="${NB_EDITOR:-${EDITOR:-${VISUAL:-}}}"

__set_editor() {
  local _editors=(
    editor
    code
    subl
    hx
    micro
    mate
    macdown
    nano
    pico
    vim
    vi
    emacs
  )

  if [[   -z "${NB_EDITOR:-}" ]]
  then
    local __editor=
    for   __editor in "${_editors[@]}"
    do
      if hash "${__editor}" 2>/dev/null
      then
        NB_EDITOR="${__editor}"

        break
      fi
    done

    if [[ -z "${NB_EDITOR:-}" ]]
    then
      cat <<HEREDOC
Command line text editor not found. Set the \$EDITOR variable in your
environment or in the \`${_ME}\` configuration file located at:
  ${NBRC_PATH}

More information about setting \$EDITOR:
  https://askubuntu.com/q/432524

\`${_ME}\` uses text editors with command line support, such as:

- Visual Studio Code
    https://code.visualstudio.com
- Sublime Text
    https://www.sublimetext.com
- Atom
    https://atom.io
- MacDown
    https://macdown.uranusjr.com
- Vim
    https://en.wikipedia.org/wiki/Vim_(text_editor)
- Emacs
    https://en.wikipedia.org/wiki/Emacs
- TextMate
    https://macromates.com
- Helix
    https://helix-editor.com
- micro
    https://github.com/zyedidia/micro
- nano
    https://en.wikipedia.org/wiki/GNU_nano
- or many of these:
    https://en.wikipedia.org/wiki/List_of_text_editors
HEREDOC
      exit 1
    fi
  fi
}; __set_editor

# Indicators ####################################################### Indicators

# $NB_INDICATOR_<type>
#
# Description:
#   Reassign or turn off file type indicator icons.
#
# Examples:
#   # reassign pinned indicator
#   export NB_INDICATOR_PINNED="💖"
#
#   # turn off bookmark indicators
#   export NB_INDICATOR_BOOKMARK=""
#
# Parameter Expansion:
#   |    | set / not blank | set / blank |    unset    |
#   ----------------------------------------------------
#   | -  |    parameter    |    blank    | replacement |
#   | :+ |   replacement   |    blank    |    blank    |

# $NB_INDICATOR_AUDIO
export  NB_INDICATOR_AUDIO="${NB_INDICATOR_AUDIO-🔉}"
export _NB_INDICATOR_AUDIO="${NB_INDICATOR_AUDIO:+"${NB_INDICATOR_AUDIO} "}"

# $NB_INDICATOR_BOOKMARK
export  NB_INDICATOR_BOOKMARK="${NB_INDICATOR_BOOKMARK-🔖}"
export _NB_INDICATOR_BOOKMARK="${NB_INDICATOR_BOOKMARK:+"${NB_INDICATOR_BOOKMARK} "}"

# $NB_INDICATOR_DOCUMENT
export  NB_INDICATOR_DOCUMENT="${NB_INDICATOR_DOCUMENT-📄}"
export _NB_INDICATOR_DOCUMENT="${NB_INDICATOR_DOCUMENT:+"${NB_INDICATOR_DOCUMENT} "}"

# $NB_INDICATOR_EBOOK
export  NB_INDICATOR_EBOOK="${NB_INDICATOR_EBOOK-📖}"
export _NB_INDICATOR_EBOOK="${NB_INDICATOR_EBOOK:+"${NB_INDICATOR_EBOOK} "}"

# $NB_INDICATOR_ENCRYPTED
export  NB_INDICATOR_ENCRYPTED="${NB_INDICATOR_ENCRYPTED-🔒}"
export _NB_INDICATOR_ENCRYPTED="${NB_INDICATOR_ENCRYPTED:+"${NB_INDICATOR_ENCRYPTED} "}"

# $NB_INDICATOR_FOLDER
export  NB_INDICATOR_FOLDER="${NB_INDICATOR_FOLDER-📂}"
export _NB_INDICATOR_FOLDER="${NB_INDICATOR_FOLDER:+"${NB_INDICATOR_FOLDER} "}"

# $NB_INDICATOR_IMAGE
export  NB_INDICATOR_IMAGE="${NB_INDICATOR_IMAGE-🌄}"
export _NB_INDICATOR_IMAGE="${NB_INDICATOR_IMAGE:+"${NB_INDICATOR_IMAGE} "}"

# $NB_INDICATOR_PINNED
export  NB_INDICATOR_PINNED="${NB_INDICATOR_PINNED-📌}"
export _NB_INDICATOR_PINNED="${NB_INDICATOR_PINNED:+"${NB_INDICATOR_PINNED} "}"

# $NB_INDICATOR_TODO
export  NB_INDICATOR_TODO="${NB_INDICATOR_TODO-✔️ }"
export _NB_INDICATOR_TODO="${NB_INDICATOR_TODO:+"${NB_INDICATOR_TODO} "}"

# $NB_INDICATOR_TODO_DONE
export  NB_INDICATOR_TODO_DONE="${NB_INDICATOR_TODO_DONE-✅}"
export _NB_INDICATOR_TODO_DONE="${NB_INDICATOR_TODO_DONE:+"${NB_INDICATOR_TODO_DONE} "}"

# $NB_INDICATOR_VIDEO
export  NB_INDICATOR_VIDEO="${NB_INDICATOR_VIDEO-📹}"
export _NB_INDICATOR_VIDEO="${NB_INDICATOR_VIDEO:+"${NB_INDICATOR_VIDEO} "}"

# Color ################################################################# Color

# $_COLOR_ENABLED
#
# Default: '1'
#
# Supported Values: '0' '1'
export _COLOR_ENABLED="${_COLOR_ENABLED:-1}"

# $NB_COLOR_THEME
#
# Default: 'nb'
#
# The color theme.
export NB_COLOR_THEME="${NB_COLOR_THEME:-nb}"

case "${NB_COLOR_THEME}" in
  nb)
    : # Colors assigned as default values below.
    ;;
  blacklight)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-39}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-56}"
    ;;
  console)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-40}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-28}"
    ;;
  desert)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-179}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-95}"
    ;;
  electro)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-200}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-62}"
    ;;
  forest)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-29}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-59}"
    ;;
  lavender)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-183}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-61}"
    ;;
  mage)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-199}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-55}"
    ;;
  mint)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-43}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-60}"
    ;;
  ocean)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-75}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-26}"
    ;;
  raspberry)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-162}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-90}"
    ;;
  smoke|monochrome)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-248}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-241}"
    ;;
  unicorn)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-183}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-153}"
    ;;
  utility)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-227}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-8}"
    ;;
  1)
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-164}"
    export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-60}"
    ;;
esac

export _NB_COLOR_THEMES=(
  blacklight
  console
  desert
  electro
  forest
  nb
  ocean
  raspberry
  smoke
  unicorn
  utility
)

# User defined themes can be installed in the $NB_DIR/.plugins directory.
# Themes have an .nb-theme extension and contain a single if statement
# assigning the color environment variables to tput ANSI color numbers.
#
# Example:
#
#     # filename: ~/.nb/.plugins/example.nb-theme
#     if [[ "${NB_COLOR_THEME}" == "example" ]]
#     then
#       export NB_COLOR_PRIMARY=68
#       export NB_COLOR_SECONDARY=8
#     fi
#
#  To view a list of available color numbers, run `nb settings colors`
__load_themes() {
  if [[   -d "${NB_DIR}/.themes"  ]] &&
     [[ ! -e "${NB_DIR}/.plugins" ]]
  then # migrate legacy .themes directory. TODO: Remove.
    mv "${NB_DIR}/.themes" "${NB_DIR}/.plugins"
  fi

  if [[ -d "${NB_DIR}/.plugins"   ]]
  then
    set +f
    local __file=
    for   __file in "${NB_DIR}/.plugins"/*."${_ME}"-theme*
    do
      if [[ -e "${__file}"        ]]
      then
        local _basename=
        _basename="$(basename "${__file}")"

        local _name="${_basename%%.*}"

        _NB_COLOR_THEMES+=("${_name}")

        source "${__file}"
      fi
    done
    set -f
  fi
}; __load_themes

# $NB_COLOR_PRIMARY
#
# Default: Value depends on terminal capabilities.
#
# Set highlighting color. This should be set to an xterm color number, usually
# a value between 1 and 256. For a table of common colors and their numbers
# run:
#
#   nb settings colors
#
# Supported Values: [0..255+]
__set_color_primary() {
  local _colors=
  _colors="$(_tput colors)"

  if [[ -n "${_colors}" ]] && [[ "${_colors}" -gt 8 ]]
  then
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-69}"
  else
    export NB_COLOR_PRIMARY="${NB_COLOR_PRIMARY:-4}"
  fi
}; __set_color_primary

# $NB_COLOR_SECONDARY
#
# Default: '8'
#
# Color for lines and other accents. This should be set to an xterm color
# number, usually a value between 1 and 256. For a table of common colors and
# their numbers, run:
#
#   nb settings colors
#
# Supported Values: [0..255+]
export NB_COLOR_SECONDARY="${NB_COLOR_SECONDARY:-8}"

# Color Variables
#
# Avoid multiple tput calls by assigning output to variables.
export _TPUT_SGR0=
if [[ -n "${TMUX:-}" ]]
then
  # Avoid `tmux` and `less` quirks: https://unix.stackexchange.com/a/446541
  _TPUT_SGR0="$(printf '\033[m')"
else
  _TPUT_SGR0="$(_tput sgr0)"
fi

export _TPUT_COLOR_PRIMARY=
       _TPUT_COLOR_PRIMARY="$(_tput setaf "${NB_COLOR_PRIMARY}")"

export _TPUT_COLOR_SECONDARY=
       _TPUT_COLOR_SECONDARY="$(_tput setaf "${NB_COLOR_SECONDARY}")"

export _TPUT_SETAF_8=
       _TPUT_SETAF_8="$(_tput setaf 8)"

export _TPUT_SMUL=
       _TPUT_SMUL="$(_tput smul)"

# _color_brackets()
#
# Usage:
#   _color_brackets <string>
#
# Description:
#   Print <string> with surrounding color brackets.
_color_brackets() {
  if ! ((_COLOR_ENABLED))
  then
    printf "[%s]" "${1:-}"

    return 0
  fi

  printf "%s%s[%s%s%s]%s"     \
    "${_TPUT_SGR0}"           \
    "${_TPUT_SETAF_8}"        \
    "${_TPUT_COLOR_PRIMARY}"  \
    "${1:-}"                  \
    "${_TPUT_SETAF_8}"        \
    "${_TPUT_SGR0}"
}

# _color_muted()
#
# Usage:
#   _color_muted <string>
#
# Print the given string with the muted color.
_color_muted() {
  if ! ((_COLOR_ENABLED))
  then
    printf "%s" "${1:-}"

    return 0
  fi

  printf "%s%s%s%s"     \
    "${_TPUT_SGR0}"     \
    "${_TPUT_SETAF_8}"  \
    "${1:-}"            \
    "${_TPUT_SGR0}"
}

# _color_primary()
#
# Usage:
#   _color_primary <string> [--underline]
#
# Description:
#   Use `tput` to highlight the given string.
_color_primary() {
  if ! ((_COLOR_ENABLED))
  then
    printf "%s\\n" "${1:-}"

    return 0
  fi

  if [[ "${2:-}" == "--underline" ]]
  then
    printf "%s%s%s%s%s\\n"        \
      "${_TPUT_SGR0}"             \
      "${_TPUT_SMUL}"             \
      "${_TPUT_COLOR_PRIMARY}"    \
      "${1:-}"                    \
      "${_TPUT_SGR0}"
  else
    printf "%s%s%s%s\\n"          \
      "${_TPUT_SGR0}"             \
      "${_TPUT_COLOR_PRIMARY}"    \
      "${1:-}"                    \
      "${_TPUT_SGR0}"
  fi
}

# _color_secondary()
#
# Usage:
#   _color_secondary <string>
#
# Description:
#   Highlight the given string using the accent color.
_color_secondary() {
  if ! ((_COLOR_ENABLED))
  then
    printf "%s\\n" "${1:-}"

    return 0
  fi

  printf "%s%s%s\\n" "${_TPUT_COLOR_SECONDARY}" "${1:-}" "${_TPUT_SGR0}"
}

# Unset CLICOLOR_FORCE to avoid unexpected color output in `ls` et al.
unset CLICOLOR_FORCE

# Cache & Temp ################################################### Cache & Temp

# $_NB_CACHE_PATH
#
# The full path to the cache directory.
export _NB_CACHE_PATH="${NB_DIR}/.cache"

if [[   -d "${NB_DIR}"          ]] &&
   [[ ! -e "${_NB_CACHE_PATH}"  ]]
then
  mkdir -p "${_NB_CACHE_PATH}"
fi

# $TMPDIR
#
# Reset $TMPDIR if it's set to the current working directory by npm.
if [[ "${TMPDIR:-}" == "${PWD}" ]]
then
  export TMPDIR="/tmp"
fi

# $_NB_TEMP_DIRECTORY
#
# The full path to the temp directory.
export _NB_TEMP_DIRECTORY
_NB_TEMP_DIRECTORY="$(mktemp -d)"

# $_NB_TEMP_PIDS
#
# A list of PIDS that should be terminated on exit.
_NB_TEMP_PIDS=()

# _temp()
#
# Usage:
#   _temp cache [clear]
#   _temp cleanup
#   _temp directory
#   _temp file [<basename> | <relative-path> | <extension>] [--touch]
#   _temp pid <pid>
#
# Subcommands:
#   cache       Print the full path to the cache directory, or optionally clear
#               the cache.
#   cleanup     Force delete the temp directory.
#   directory   Print the full path the the temp directory.
#   file        Initialize a temporary file path.
#   pid         Specify a process ID that should be terminated on exit.
#
# Description:
#   Manage temp and cache files and directories.
_temp() {
  # Usage: _temp_validate_path <path>
  _temp_validate_path() {
    [[ -n "${1:?}"              ]] &&
    [[    "${1}" != "/"         ]] &&
    [[    "${1}" != "${HOME}"   ]] &&
    [[    "${1}" != "${PWD}"    ]] &&
    [[ -e "${1}"                ]]
  }

  local _subcommand="${1:-}"

  case "${_subcommand}" in
    cache)
      if [[ "${2:-}" == "clear" ]]
      then
        if _temp_validate_path "${_NB_CACHE_PATH:?}"
        then
          rm -r "${_NB_CACHE_PATH:?}"
          mkdir -p "${_NB_CACHE_PATH}"
        fi
      else
        printf "%s\\n" "${_NB_CACHE_PATH}"
      fi
      ;;
    cleanup)
      if _temp_validate_path "${_NB_TEMP_DIRECTORY:?}"
      then
        rm -rf "${_NB_TEMP_DIRECTORY:?}"
      fi

      local __pid=
      for   __pid in "${_NB_TEMP_PIDS[@]:-}"
      do
        [[ -n "${__pid:-}" ]] || continue

        kill "${__pid}" 2>/dev/null || :
      done
      ;;
    dir|directory)
      printf "%s\\n" "${_NB_TEMP_DIRECTORY:-}"
      ;;
    file)
      local _extension=
      local _relative_path=
      local _touch=0

      local __arg=
      for   __arg in "${2:-}" "${3:-}"
      do
        case "${__arg}" in
          "")       :                           ;;
          --touch)  _touch=1                    ;;
          \.*)      _extension="${__arg:-}"     ;;
          *)        _relative_path="${__arg:-}" ;;
        esac
      done

      local _temp_file_path=

      if [[ -z  "${_relative_path:-}"       ]]
      then
        _temp_file_path="${_NB_TEMP_DIRECTORY}/${RANDOM}${_extension:-}"
      else
        _temp_file_path="${_NB_TEMP_DIRECTORY}/${_relative_path:-}"
      fi

      if [[     "${_relative_path:-}" =~ /  ]]
      then
        mkdir -p "${_temp_file_path%/*}"
      fi

      if ((_touch))
      then
        touch "${_temp_file_path}"
      fi

      printf "%s\\n" "${_temp_file_path:-}"
      ;;
    pid)
      _NB_TEMP_PIDS+=("${2:?}")
      ;;
  esac
}

trap "_temp cleanup"                        EXIT
trap "exit"                                 INT
trap 'printf "\\n"; _temp cleanup; exit 0'  SIGINT
trap 'printf "\\n"; _temp cleanup; exit 0'  SIGTERM

###############################################################################
# Configuration Validation
###############################################################################

# _validate_configuration()
#
# Usage:
#   _validate_configuration
#
# Description:
#   Check the runtime environment and display an error message when running in
#   an unsupported configuration.
_validate_configuration() {
  if { ((${NB_BASH_UPDATE_PROMPT_ENABLED:-0}))        ||
       {
         [[ "${BASH_VERSINFO[0]:-999999999}" -lt 4 ]] &&
         ((${NB_BASH_UPDATE_PROMPT_ENABLED:-1}))
       }
     }                                                &&
     _command_exists "brew"                           &&
     {
       # command initiated by user
       [[ -t 1                          ]]            ||
       ((${NB_TEST_MOCK_TTY:-0}))
     }
  then
    local _config_file_path="${NB_DIR}/.nb-bash-3-enabled"

    if [[ -e "${_config_file_path}"     ]]
    then
      local _config_file_version=
      _config_file_version="$(head -n 1 "${_config_file_path:-}")"

      if [[ "${_config_file_version:-}" != "${_VERSION}" ]] ||
         ((${NB_BASH_UPDATE_PROMPT_ENABLED:-0}))
      then
        rm "${_config_file_path:?}"
      fi
    fi

    if [[ ! -e "${_config_file_path:-}" ]]  &&
       ((${NB_BASH_UPDATE_PROMPT_ENABLED:-1}))
    then
      local _color_me=
      _color_me="$(_color_muted '`')$(_color_primary "${_ME}")$(_color_muted '`')"

      {
        printf "Update Bash\\n"
        printf "%s\\n" "$(_color_muted  "-------------")"

        cat <<HEREDOC
${_color_me} works best with the current version of Bash.

${_color_me} can $(_color_primary "update") your system to $(_color_primary "Bash 5") via Homebrew
or you can proceed with Bash 3.2.

Answering $(_color_primary "y") or $(_color_primary "yes") will run the following command:

  $(_color_primary "brew install bash")

This command could take a minute to run.
HEREDOC
      } | _warn printf "%s\\n" "$(cat)"

      while true
      do
        local __yn=

        if _contains "-y"     "${@:-}" ||
           _contains "--yes"  "${@:-}"
        then
          __yn="y"
        else
          printf "%s\\n" "$(_color_muted "------------------------")"

          IFS='' read -r -e -d $'\n' -p   \
"$(_color_primary "Update") to Bash 5?  $(_color_brackets "y/N") " __yn
        fi

        case "${__yn}" in
          [Yy]*)
            printf "\\n"

            _warn printf "Updating Bash%s\\n\\n" "$(_color_muted "...")"

            if brew install bash
            then
              printf "\\n"

              {
                printf "%s\\n"    "$(_color_muted  "------------------")"
                printf "  %s to %s!\\n"         \
                  "$(_color_primary "Updated")" \
                  "$(_color_primary "Bash 5")"
                printf "  %s\\n"  "$(_color_muted  "------------------")"
              } | _warn printf "%s\\n" "$(cat)"

              printf "\\n"
            else
              printf "\\n"

              _warn printf "Unable to update to Bash 5.\\n\\n"
            fi


            if [[ -e "${_config_file_path:?}" ]]
            then
              rm "${_config_file_path:?}"
            fi

            break
            ;;
          *)
            cat <<HEREDOC > "${_config_file_path:?}"
${_VERSION}

This presence of this file indicates that Bash 3 support is enabled.
HEREDOC

            printf "\\n"

            {
              printf "%s\\n" "$(_color_muted    "-------------------------")"
              printf                          "  Bash 3.2 support enabled.\\n"
              printf "%s\\n" "$(_color_muted  "  -------------------------")"
            } | _warn printf "%s\\n" "$(cat)"

            printf "\\n"

            break
            ;;
        esac
      done
    fi
  fi
}

if [[ -e "${NB_DIR:-}" ]]
then
  _validate_configuration "${@:-}"
fi

###############################################################################
# Helpers: Group 1                                             Helpers: Group 1
# ----------------                                             ----------------
###############################################################################
# --------------------------------------------------------------------------- #

# $_BT
#
# Backtick with ANSI-C quoting for string building.
_BT=$'`'

# $_CHEVRON_LEFT
#
# A left-pointing chevron character.
_CHEVRON_LEFT="❮"

# $_CHEVRON_RIGHT
#
# A right-pointing chevron character.
_CHEVRON_RIGHT="❯"

# $_COLUMNS
#
# The terminal width in number of columns (characters).
_COLUMNS="$(_tput cols)"

# $_FILE_TYPES
#
# An array of supported aggregate file types.
_FILE_TYPES=(archive audio bookmark document folder image text video)

# $_IGNORE_PATTERNS
#
# An array of filename patterns to ignore, formatted as `sed -e` arguments.
_IGNORE_PATTERNS=(
  -e '/~$/d'
  -e '/^#.*#$/d'
  -e '/\.swa?p$/d'
  -e '/^\.#*/d'
  -e '/.*_ltex\.json$/d' # ltex-utils.nvim
)

# $_MD
#
# Middle dot character.
_MD="·"

# $_NBSP
#
# No-break space character.
_NBSP=" "

# $_NEWLINE
#
# Newline with ANSI-C quoting for string building.
_NEWLINE=$'\n'

# $_SLASH
#
# Slash with ANSI-C quoting for string building support and macOS Bash
# string substitution.
_SLASH=$'/'

# _URL_PATTERNS
#
# Patterns for matching URLs.
#
# https://en.wikipedia.org/wiki/List_of_URI_schemes
export _URL_PATTERNS=(
  "([.a-z0-9+-]+)://[^[:space:]]+"
  "(afp|attachment|platform):/[^[:space:]]+"
  "aim:[^[:space:]]+\?[^[:space:]]+"
  "(dab|fm):[^[:space:]]+\.[^[:space:]]+\.[^[:space:]]+"
  "(data|geo):[^[:space:]]+,[^[:space:]]+"
  "doi:10\.[^[:space:]]+"
  "(msnim|things):[^[:space:]]+\?[^[:space:]]+"
  "(feed|mvn|paparazzi|view-source):https?://[^[:space:]]+"
  "git@[^[:space:]]+:[^[:space:]]+"
  "gtalk:chat[^[:space:]]+"
  "(im|mailto|reload|sips?|xmpp):[^[:space:]]+@[^[:space:]]+"
  "jar:[^[:space:]]+!/[^[:space:]]+"
  "magnet:\?xt=urn:[^[:space:]]+"
  "maps:q=[^[:space:]]+"
  "(sms|tel):\+[0-9]+"
  "(jdbc|spotify|urn):[^[:space:]]+:[^[:space:]]+"
  "tag:[^[:space:]]+,[^[:space:]]+:[^[:space:]]+"
  "ymsgr:sendIM?[^[:space:]]+"
  # TODO: develop strategy to avoid matching notebook: selectors
  # "(apt|amss|barion|bitcoin|callto|cid|dns|drm|fax|gg):[^[:space:]]+"
  # "(go|iax|javascript|message|mid|mvn|news|openpgp4fpr):[^[:space:]]+"
  # "(palm|pres|proxy|psyc|query|session|shc|skype):[^[:space:]]+"
  # "(stuns?|trueconf|turns?|ws|xfire):[^[:space:]]+"
  # "itms:"
)

# Fallbacks for non-unicode environments.
if [[ ! "${LANG:-x}" =~ (utf-|UTF-) ]]
then
  _CHEVRON_LEFT="<"
  _CHEVRON_RIGHT=">"
  _MD="-"
fi

# _alias_subcommand()
#
# Usage:
#   _alias_subcommand <subcommand> <alias>
#
# Description:
#   Create an <alias> of <subcommand>. NOTE: aliases also have to be added to
#   the $_SUBCOMMANDS variable.
_alias_subcommand() {
  local _alias="${2:-}"
  local _subcommand="${1:-}"

  if [[ -z "${_alias:-}" ]]
  then
    return 1
  fi

  shopt -u extglob

  eval "_describe_${_alias}() { _describe_${_subcommand}  \"\${@:-}\"; }"
  eval "_${_alias}()          { _${_subcommand}           \"\${@:-}\"; }"

  shopt -s extglob
}

# _bat()
#
# Usage:
#   _bat [--command-exists] [<bat options>]
#
# Description:
#   Wrapper for `bat`, aka `batcat` on debian.
#
# Exit / Error / Return Status (--command-exists):
#   0 (success, true)  If a `bat` or `batcat` exacutable is found on the system.
#   1 (error,  false)  if not.
_BAT_COMMAND=
_bat() {
  if _command_exists "batcat"
  then
    _BAT_COMMAND="batcat"
  elif _command_exists "bat"
  then
    _BAT_COMMAND="bat"
  fi

  if [[ "${1:-}" == "--command-exists"  ]]
  then
    if [[ -n "${_BAT_COMMAND:-}"        ]]
    then
      return 0
    else
      return 1
    fi
  fi

  "${_BAT_COMMAND}" "${@}"
}

# _file_is_archive()
#
# Usage:
#   _file_is_archive <path>
#
# Exit / Error / Return Status:
#   0 (success, true)  If file is an archive.
#   1 (error,  false)  if not.
export _ARCHIVE_FILE_EXTENSIONS=(
  7z
  apk
  bz2
  dmg
  gz
  lz
  rar
  s7z
  sit
  sitx
  sparsebundle
  tar
  tgz
  tbz2
  tlz
  txz
  xz
  zip
  zipx
  Z
)
_file_is_archive() {
  local _file_path="${1:-}"
  local _file_type="${_file_path##*.}"

  LC_ALL=C _contains "${_file_type}" "${_ARCHIVE_FILE_EXTENSIONS[@]}"
}

# _file_is_audio()
#
# Usage:
#   _file_is_audio (<path> | <filename>)
#
# Exit / Error / Return Status:
#   0 (success, true)  If file is an audio file.
#   1 (error,  false)  if not.
export _AUDIO_FILE_EXTENSIONS=(
  aac
  aiff
  flac
  m4a
  mp3
  ogg
  wav
)
_file_is_audio() {
  local _file_path="${1:-}"
  local _file_type="${_file_path##*.}"

  LC_ALL=C _contains "${_file_type}" "${_AUDIO_FILE_EXTENSIONS[@]}"
}

# _file_is_bookmark()
#
# Usage:
#   _file_is_bookmark (<path> | <filename>)
#
# Exit / Error / Return Status:
#   0 (success, true) If file is a bookmark.
#   1 (error,  false) if not.
export _BOOKMARK_FILE_EXTENSIONS=(
  bookmark.md
  bookmark.md.enc
)
_file_is_bookmark() {
  # Use explicit matching for legacy bookmark name support.
  [[ "${1:-}" =~ ([(-|.)]bookmark.md|[(-|.)]bookmark.md.enc) ]]
}

# _file_is_document()
#
# Usage:
#   _file_is_document (<path> | <filename>)
#
# Exit / Error / Return Status:
#   0 (success, true)  If file is a Word, Open Office, PDF, or other document.
#   1 (error,  false)  if not.
export _DOCUMENT_FILE_EXTENSIONS=(
  doc
  docx
  odt
  pdf
  rtf
  xls
  xlsx
)
_file_is_document() {
  local _file_path="${1:-}"
  local _file_type="${_file_path##*.}"

  LC_ALL=C _contains "${_file_type}" "${_DOCUMENT_FILE_EXTENSIONS[@]}"
}

# _file_is_encrypted()
#
# Usage:
#   _file_is_encrypted <path>
#
# Exit / Error / Return Status:
#   0 (success, true)  If file is encrypted.
#   1 (error,  false)  if not.
export _ENCRYPTED_FILE_EXTENSIONS=(
  enc
)
_file_is_encrypted() {
  local _file_path="${1:-}"
  local _file_type="${_file_path##*.}"

  # `file` with 'soft' test is slow, so avoid calling it.
  LC_ALL=C _contains "${_file_type}" "${_ENCRYPTED_FILE_EXTENSIONS[@]}" ||
    {
      ! LC_ALL=C _contains "${_file_type}"  \
        "${_TEXT_FILE_EXTENSIONS[@]}"       \
        "${_IMAGE_FILE_EXTENSIONS[@]}"      \
        "${_DOCUMENT_FILE_EXTENSIONS[@]}"   \
        "${_AUDIO_FILE_EXTENSIONS[@]}"      \
        "${_VIDEO_FILE_EXTENSIONS[@]}"      &&
        if _command_exists "file"
        then
          [[ "$(file "${_file_path:-}"      \
                  --exclude=apptype         \
                  --exclude=tokens          \
                  --exclude=cdf             \
                  --exclude=compress        \
                  --exclude=elf             \
                  --exclude=tar)" =~ (encrypted|openssl) ]]
        else
          return 1
        fi
    }
}

# _file_is_image()
#
# Usage:
#   _file_is_image (<path> | <filename>)
#
# Exit / Error / Return Status:
#   0 (success, true)  If file is an image.
#   1 (error,  false)  if not.
export _IMAGE_FILE_EXTENSIONS=(
  afphoto
  ai
  bmp
  gif
  heic
  ind
  indd
  jpg
  jpeg
  png
  psd
  raw
  svg
  svgz
  tif
  tiff
  webp
)
_file_is_image() {
  local _file_path="${1:-}"
  local _file_type="${_file_path##*.}"

  LC_ALL=C _contains "${_file_type}" "${_IMAGE_FILE_EXTENSIONS[@]}"
}

# _file_is_text()
#
# Usage:
#   _file_is_text <path>
#
# Exit / Error / Return Status:
#   0 (success, true)  If file is text.
#   1 (error,  false)  if not.
#
# Resources:
#   Markdown: https://superuser.com/a/285878
export _TEXT_FILE_EXTENSIONS=(
  adoc
  asciidoc
  bash
  bib
  coffee
  css
  go
  html
  js
  json
  jsx
  latex
  markdown
  md
  mdown
  mdwn
  mdtxt
  mdtext
  mkd
  mkdn
  org
  py
  rb
  Rmd
  rst
  scss
  sh
  sql
  tex
  text
  textile
  ts
  tsx
  txt
  xml
)
_file_is_text() {
  local _file_path="${1:-}"
  local _file_type="${_file_path##*.}"

  # Avoid calling `file` for better performance.
  LC_ALL=C _contains "${_file_type}" "${_TEXT_FILE_EXTENSIONS[@]}" ||
    {
      ! LC_ALL=C _contains "${_file_type}"  \
        "${_IMAGE_FILE_EXTENSIONS[@]}"      \
        "${_DOCUMENT_FILE_EXTENSIONS[@]}"   \
        "${_ENCRYPTED_FILE_EXTENSIONS[@]}"  \
        "${_AUDIO_FILE_EXTENSIONS[@]}"      \
        "${_VIDEO_FILE_EXTENSIONS[@]}"      \
        "${_ARCHIVE_FILE_EXTENSIONS[@]}"        &&
        [[ !    "${_file_type}" =~ \.epub$  ]]  &&
        [[ ! -d "${_file_path:-}"           ]]  &&
        if _command_exists "file"
        then
          [[ "$(file "${_file_path:-}"      \
                  --exclude=apptype         \
                  --exclude=tokens          \
                  --exclude=cdf             \
                  --exclude=compress        \
                  --exclude=elf             \
                  --exclude=tar             \
                  -b --mime-type)" =~ ^text ]]
        else
          [[ -f "${_file_path:-}"           ]]
        fi
    }
}

# _file_is_todo()
#
# Usage:
#   _file_is_todo (<path> | <filename>)
#
# Exit / Error / Return Status:
#   0 (success, true) If file is a todo.
#   1 (error,  false) if not.
export _TODO_FILE_EXTENSIONS=(
  todo.md
  todo.md.enc
)
_file_is_todo() {
  [[ "${1:-}" =~ (todo\.md|todo\.md\.enc) ]]
}

# _file_is_video()
#
# Usage:
#   _file_is_video (<path> | <filename>)
#
# Exit / Error / Return Status:
#   0 (success, true)  If file is a video file.
#   1 (error,  false)  if not.
export _VIDEO_FILE_EXTENSIONS=(
  avi
  flv
  m4p
  m4v
  mp2
  mp4
  mov
  mpeg
  mpg
  qt
  webm
  wmv
)
_file_is_video() {
  local _file_path="${1:-}"
  local _file_type="${_file_path##*.}"

  LC_ALL=C _contains "${_file_type}" "${_VIDEO_FILE_EXTENSIONS[@]}"
}

# _get_content()
#
# Usage:
#   _get_content <path> [--title]
#
# Options:
#   --title  Print the title or nothing if a title is not found.
#
# Description:
#   Print the title or first line of the text document at <path>. When a title
#   is not found, print the first line, prefixed with '__first_line:'.
#
#   Supports both Markdown h1 styles, YAML front matter, Org Mode, LaTeX,
#   and AsciiDoc.
#
#   - Markdown
#     - Supported:
#       - # This is a Title
#       - This is a Title
#         ===============
#       - ---
#         title: This is a Title
#         ---
#     - https://daringfireball.net/projects/markdown/syntax#header
#     - https://jekyllrb.com/docs/front-matter/
#   - Org Mode
#     - Supported:
#       - #+TITLE: This is a Title
#     - https://orgmode.org/guide/Export-Settings.html
#   - LaTeX
#     - Supported:
#       - \title{This is a Title}
#   - AsciiDoc
#     - Supported:
#       - = This is a Title
_get_content() {
  local _counter=0
  local _first_line=
  local _in_code_block=0
  local _in_front_matter=0
  local _maybe_title=
  local _path="${1:-}"
  local _title=

  if [[ "${2:-}" == --title ]]
  then
    local _only_title=1
  else
    local _only_title=0
  fi

  # turn on case-insensitive matching
  shopt -s nocasematch

  if [[   -z "${_path}" ]]
  then
    return 1
  elif [[ -d "${_path}" ]]
  then
    return 0
  elif [[ -e "${_path}" ]]
  then

    # `awk` `_get_first_line` alternative
    # -----------------------------------
    #       awk -f - "${_path}" <<'HEREDOC'
    # (state == 0) && /^---$/ { state=1; next }
    # (state == 1) && /^---$/ { state=0; next }
    # (state == 0) && /^```/  { state=1; next }
    # (state == 1) && /^```/  { state=0; next }
    #
    # (state == 0) && /^./    { print; exit   }
    # HEREDOC

    if [[ "${_path}" =~ (\.md$|\.markdown$) ]]
    then
      local               __line=
      while IFS= read -r  __line || [[ -n "${__line:-}"     ]]
      do
        if [[ "${__line}" =~ ^([[:space:]]*#[[:space:]]+)   ]] &&
           ! ((_in_code_block))
        then # line starts with an atx-style H1
          _title="${__line#"${BASH_REMATCH[1]:-}"}"

          if [[ "${_title}" =~ ([[:space:]]+#[[:space:]]*)$ ]]
          then
            _title="${_title%"${BASH_REMATCH[1]:-}"}"
          fi

          # `sed` alternative
          # -----------------
          # _title="$(
          #   printf "%s\\n" "${__line}"    \
          #     | sed                       \
          #       -e 's/^[[:space:]]*# //'  \
          #       -e 's/ #$//'
          #   )"

          break
        elif [[ "${__line}" =~ ^---$    ]]
        then # start or end of front matter block
          if ((_in_front_matter))
          then
            _in_front_matter=0
          else
            _in_front_matter=1
          fi
        elif [[ "${__line}" =~ ^\`\`\`  ]]
        then # start or end of code block
          if ((_in_code_block))
          then
            _in_code_block=0
          else
            _in_code_block=1
          fi
        elif ((_in_front_matter))   &&  [[ "${__line}" =~ ^title\:  ]]
        then # front matter title
          _title="$(printf "%s\\n" "${__line}" | LC_ALL=C sed 's/^title: //')"

          break
        elif ! ((_in_front_matter)) && ! ((_in_code_block))
        then
          if [[ -z "${_maybe_title:-}"  ]]  &&  [[ -n "${__line:-}" ]]
          then  # potential setext-style H1
            _maybe_title="${__line}"
          elif [[ -n "${_maybe_title:-}"            ]] &&
               [[ "${__line}" =~ ^[[:space:]]*\=+$  ]]
          then # underline for setext-style H1 on previous line
            _title="$(
              printf "%s\\n" "${_maybe_title}" | LC_ALL=C sed 's/^[[:space:]]*//'
            )"

            break
          elif [[ -n "${_maybe_title:-}"        ]]
          then # in normal content, title not found
            if ! ((_only_title))
            then
              if [[ "${#_maybe_title}" -gt 500  ]]
              then
                _first_line="${_maybe_title:0:500}..."
              else
                _first_line="${_maybe_title}"
              fi
            fi

            if [[ ! "${_maybe_title}"  =~ ^\[   ]]
            then # only break with first non-link line
              break
            fi
          else
            continue
          fi
        fi
      done < "${_path}"

      if [[ -z "${_title:-"${_first_line:-}"}"  ]] &&
         [[ -n "${_maybe_title:-}"              ]]
      then
        _first_line="${_maybe_title:-}"
      fi
    elif [[ "${_path}"    =~ (\.latex$|\.tex$)  ]]
    then
      local               __line=
      while IFS= read -r  __line  ||  [[ -n "${__line:-}" ]]
      do
        _counter="$((_counter+1))"

        if [[ "${__line}" =~  ^\\title\{        ]]
        then
          _title="$(
            printf "%s\\n" "${__line}" | LC_ALL=C sed 's/\\title{\(.*\)}/\1/'
          )"

          break
        elif [[ -n "${__line:-}"      ]]
        then
          if [[ -z "${_first_line:-}" ]]
          then
            _first_line="${__line}"
          fi

          if [[ ! "${__line}" =~ ^\\  ]] &&
             [[ "${_counter}" -gt 20  ]]
          then
            break
          fi
        else
          continue
        fi
      done < "${_path}"
    elif [[   "${_path}" =~ \.org$    ]]
    then
      local               __line=
      while IFS= read -r  __line  ||  [[ -n "${__line}"   ]]
      do
        _counter="$((_counter+1))"

        # NOTE: Titles can be defined with multiple #+TITLE: lines.
        if [[ "${__line}" =~ ^\#\+TITLE\: ]]
        then
          if [[ -n "${_title:-}"          ]]
          then
            _title="${_title} "
          fi

          _title+="$(
            printf "%s\\n" "${__line}"    \
              | LC_ALL=C sed              \
                  -e 's/^#+TITLE: //'     \
                  -e 's/^#+title: //'
          )"
        elif [[ -n "${__line:-}"      ]]
        then

          if [[ -z "${_first_line:-}" ]]
          then
            _first_line="${__line}"
          fi

          if [[ ! "${__line}" =~ ^\#  ]] &&
             [[ "${_counter}" -gt 10  ]]
          then
            break
          fi
        else
          continue
        fi
      done < "${_path}"
    elif [[ "${_path}"    =~ (\.adoc$|\.asciidoc$)  ]]
    then
      local               __line=
      while IFS= read -r  __line  ||  [[ -n "${__line:-}" ]]
      do
        _counter="$((_counter+1))"

        if [[ "${__line}" =~  ^=\     ]]
        then
          _title="${__line#= }"

          break
        elif [[ -n "${__line:-}"      ]]
        then
          if [[ -z "${_first_line:-}" ]]
          then
            _first_line="${__line}"
          fi

          if [[ ! "${__line}" =~ ^=\  ]] &&
             [[ "${_counter}" -gt 20  ]]
          then
            break
          fi
        else
          continue
        fi
      done < "${_path}"
    elif ! ((_only_title))        &&
         LC_ALL=C _contains "${_path##*.}" "${_TEXT_FILE_EXTENSIONS[@]}"
    then
      local               __line=
      while IFS= read -r  __line  ||  [[ -n "${__line:-}" ]]
      do
        if [[ -n "${__line:-}"        ]]
        then
          if [[ "${#__line}" -gt 500  ]]
          then
            _first_line="${__line:0:500}..."
          else
            _first_line="${__line}"
          fi

          break
        fi
      done < "${_path}"
    fi

    if [[ -n "${_title:-}"    ]]
    then
      printf "%s\\n" "${_title/%$'\r'}"
    elif ! ((_only_title)) && [[ -n "${_first_line:-}"    ]]
    then
      printf "%s\\n" "__first_line:${_first_line/%$'\r'}"
    fi

    # turn off case-insensitive matching
    shopt -u nocasematch
  fi
}

# _get_id_selector()
#
# Usage:
#   _get_id_selector <path> | <selector> [--notebook]
#
# Options:
#   --notebook  Always include the notebook name in the output.
#
# Description:
#   Convert a <path> or <selector> to valid selector constructed with ids,
#   which are resolved first during selector resolution. This function gives
#   precedence to folder names in input.
_get_id_selector() {
  local _folder_path=
  local _id_selector=
  local _notebook_name=
  local _notebook_path=
  local _relative_path=
  local _selector="${1:-}"
  local _selector_relative_path=
  local _trailing_slash=0

  case "${2:-}" in
    --notebook) local _always_include_notebook=1 ;;
    *)          local _always_include_notebook=0 ;;
  esac

  if [[ -z "${_selector:-}"     ]]
  then
    return 0
  fi

  if [[ "${_selector:-}" =~ /$  ]]
  then
    _trailing_slash=1
  fi

  if [[ "${_selector:-}" =~ ^/  ]]
  then # selector is full path
    if [[ "${_selector}" =~ ^${NB_DIR}      ]]
    then
      local _path_with_notebook="${_selector#"${NB_DIR}"/}"
      _notebook_name="${_path_with_notebook%%/*}"
      _notebook_path="${NB_DIR}/${_notebook_name}"

      if [[ "${_path_with_notebook:-}" =~ / ]]
      then
        _selector_relative_path="${_path_with_notebook#*/}"
      fi
    else
      _notebook_name="local"

      _notebook_path="$(
        cd "${_selector%/*}"    &&
          __set_notebook_paths  &&
          _notebooks current --path --no-color
      )"

      if [[ "${_selector:-}" == "${_notebook_path:-}" ]]
      then
        _selector_relative_path=
      else
        _selector_relative_path="${_selector#"${_notebook_path}"/}"
      fi
    fi
  else
    if [[ "${_selector:-}" =~ :   ]]
    then
      _notebook_name="${_selector%%:*}"
      _selector_relative_path="${_selector#*:}"
    else
      _selector_relative_path="${_selector:-}"
    fi
  fi

  if [[ -z "${_notebook_path:-}"  ]]
  then
    case "${_notebook_name:-}" in
      local) _notebook_path="$(_notebooks --local --path --no-color)" ;;
      *)     _notebook_path="${NB_DIR}/${_notebook_name}"             ;;
    esac
  fi

  local _parent_folder_path=

  if [[ -n "${_notebook_name:-}"  ]]
  then
    _id_selector+="${_notebook_name}:"
    _parent_folder_path="${_notebook_path:-}"
  else
    _parent_folder_path="$(_notebooks current --path)"

    if ((_always_include_notebook))
    then
      if _notebooks current --local
      then
        _id_selector+="local:"
      else
        _id_selector+="${_parent_folder_path##*/}:"
      fi
    fi
  fi

  local _id_path=

  if [[ -n "${_selector_relative_path:-}" ]]
  then
    local _selector_segments=()

    IFS="/" read -ra _selector_segments <<< "${_selector_relative_path:-}"

    local i=
    for ((i=0; i < ${#_selector_segments[@]}; i++))
    do
      local _segment_id=

      if [[ "${i}" -eq "$((${#_selector_segments[@]} - 1))" ]]
      then # it's the last segment
        if [[ "${_selector_segments[i]:-}" =~ ^[0-9]+$      ]] &&
           ! ((_trailing_slash))
        then
          _segment_id="${_selector_segments[i]:-}"
        fi
      fi

      if [[ -z "${_segment_id:-}"         ]]
      then
        _segment_id="$(
          _index get_id                   \
            "${_selector_segments[i]:-}"  \
            "${_parent_folder_path}"      || :
        )"
      fi

      local _segment_basename=

      if [[ -z "${_segment_id:-}"                     ]] &&
         [[ "${_selector_segments[i]:-}"  =~ ^[0-9]+$ ]]
      then
        _segment_basename="$(
          _index get_basename             \
            "${_selector_segments[i]:-}"  \
            "${_parent_folder_path}" 2>/dev/null || :
        )"

        if [[ -n "${_segment_basename:-}" ]]
        then
          _segment_id="${_selector_segments[i]:-}"
        fi
      fi

      if [[ -z "${_segment_id:-}" ]]
      then
        return 1
      fi

      if [[ -z "${_id_path:-}"    ]]
      then
        _id_path+="${_segment_id}"
      else
        _id_path+="/${_segment_id}"
      fi

      _parent_folder_path+="/${_segment_basename:-${_selector_segments[i]:-}}"
    done
  fi

  if [[ -n "${_id_path:-}"        ]] &&
     [[ !  "${_id_path}" == "/"   ]]
  then
    _id_selector+="${_id_path}"
  fi

  if ((_trailing_slash))
  then
    _id_selector+="/"
  fi

  printf "%s\\n" "${_id_selector:-}"
}

# _get_last_modified_timestamp()
#
# Usage:
#   _get_last_modified_timestamp <path>
#
# Description:
#   Print the last modified timestamp for the file at <path>.
_get_last_modified_timestamp() {
  local _path="${1:-}"
  local _stat_output=

  [[ -z "${_path:-}" ]] && return 1

  if [[ -L "${_path}" ]]
  then
    _path="$(_resolve_symlink "${_path}")"
  fi

  if ! _stat_output="$(
       stat -c %Y "${_path}" 2>/dev/null
     )" # GNU
  then
    if ! _stat_output="$(
         gstat -c %Y "${_path}" 2>/dev/null
       )" # GNU prefixed
    then
      _stat_output="$(
        stat -f '%m' "${_path}"
      )" # BSD/macOS
    fi
  fi

  if [[ -n "${_stat_output:-}" ]]
  then
    printf "%s\\n" "${_stat_output}"

    return 0
  else
    return 1
  fi
}

# _get_visible_length()
#
# Usage:
#   _get_visible_length <string> [<extra-length>]
#
# Description:
#   Calculate the apparent length of <string>, with byte and character
#   calculations for handling unicode characters.
#
# More Information:
#   https://stackoverflow.com/a/31009961
_get_visible_length() {
  local _extra_length="${2:-0}"
  local _string="${1:-}"

  _LANG="${LANG:-}" _LC_ALL="${LC_ALL:-}"

  local _length_chars=
  _length_chars="${#_string}"

  LANG=C LC_ALL=C

  local _length_bytes=
  _length_bytes="${#_string}"

  LANG="${_LANG:-}" LC_ALL="${_LC_ALL:-}"

  local _difference=
  _difference=$(((_length_bytes-_length_chars)/3))

  local _calculated_length=
  _calculated_length=$((_length_chars+_difference))

  if ((_extra_length))
  then
    _calculated_length=$((_calculated_length+_extra_length))
  fi

  printf "%s\\n" "${_calculated_length:-0}"
}

# _grep_supports_color()
#
# Usage:
#   _grep_supports_color
#
# Exit / Error / Return Status:
#   0 (success, true)  If grep supports the --color option.
#   1 (error,  false)  if not.
_grep_supports_color() {
  printf "\\n" | grep --color=never "" >/dev/null 2>&1
}

# _highlight_syntax_if_available()
#
# Usage:
#   _highlight_syntax_if_available [<path> | <extension>]
#
# Description:
#   If `bat` or Pygments is available, use it to highlight syntax. When neither
#   is available, pipe through `cat`.
#
# References:
#   https://github.com/sharkdp/bat
#   https://pygments.org/
_highlight_syntax_if_available() {
  # Usage: _highlight_syntax_with_extension <extension>
  _highlight_syntax_with_extension() {
    ! _contains "${1:-}" "db" # TODO
  }

  local _extension=
  local _path=

  if [[ "${1:-}" =~ / ]]
  then
    _path="${1}"
  elif [[ -n "${1:-}" ]]
  then
    _extension="${1}"
  else
    _extension="md"
  fi

  if ! ((_COLOR_ENABLED))
  then
    if [[ -n "${_path:-}"   ]]
    then
      cat "${_path}"
    else
      cat
    fi

    return 0
  fi

  if _bat --command-exists
  then
    local _arguments=()

    if [[ -n "${_path:-}"   ]]
    then
      _arguments+=("${_path}")
    elif _highlight_syntax_with_extension "${_extension}"
    then
      _arguments+=("--language" "${_extension}")

      if ! printf "" | _bat  --color     always          \
                            --language  "${_extension}" \
                            --paging    never           \
                            --plain                     \
                            2>/dev/null
      then
        cat

        return 0
      fi
    fi

    _bat "${_arguments[@]}"  \
      --color   always      \
      --paging  never       \
      --plain               \
      --theme "${NB_SYNTAX_THEME:-base16}"
  elif hash "highlight" 2>/dev/null
  then
    local _arguments=("-O" "ansi")

    if [[ -n "${_path:-}"   ]]
    then
      _arguments+=("${_path}")
    elif _highlight_syntax_with_extension "${_extension}"
    then
      _arguments+=("--syntax" "${_extension}")
    fi

    highlight "${_arguments[@]}"
  elif ((_COLOR_ENABLED)) && hash "pygmentize" 2>/dev/null
  then # pygments is installed.
    local _arguments=("-O" "style=default" "-f" "terminal")

    if [[ -n "${_path:-}"   ]]
    then
      _arguments+=("${_path}")
    elif _highlight_syntax_with_extension "${_extension}"
    then
      _arguments+=("-l" "${_extension}")
    fi

    pygmentize "${_arguments[@]}" 2>/dev/null
  else
    if [[ -n "${_path:-}"   ]]
    then
      cat "${_path}"
    else
      cat
    fi
  fi
}

# _join()
#
# Usage:
#   _join <delimiter> <list-item>...
#
# Description:
#   Print a string containing all <list-item> arguments separated by
#   <delimiter>.
#
# Example:
#   _join "${_delimeter}" "${_list[@]}"
#
# More Information:
#   https://stackoverflow.com/a/17841619
_join() {
  local _delimiter="${1:-}"

  shift

  local _joined_string="${1:-}"

  shift

  local __element=
  for   __element in "${@:-}"
  do
    [[ -n "${__element:-}" ]] || continue

    _joined_string+="${_delimiter:-}${__element:-}"
  done

  printf "%s\\n" "${_joined_string}"
}

# _less_prompt()
#
# Usage:
#   _less_prompt
#
# Description:
#   The prompt to display in `less`.
_less_prompt() {
  # TODO: remove when less 668 or higher is widely available
  local _less_version=
  _less_version="$(less --version | head -1)"
  _less_version="${_less_version#* }"
  _less_version="${_less_version%% *}"
  _less_version="${_less_version%%.*}"

  local _prompt="\
> scroll for more, h for help, or q to quit"

  if [[ "${_COLUMNS}" -gt 81 ]]
  then
    # TODO: remove when less 668 or higher is widely available
    if [[ "${_less_version:-}" -gt "653" ]] &&
       [[ "${_less_version:-}" -lt "668" ]]
    then # render prompt without multibyte characters
      _prompt="\
> scroll for more, f / b to jump forward / back, h for help, or q to quit"
    else
      _prompt="\
> scroll for more, f / b to jump ↓ / ↑, h for help, or q to quit"
    fi
  fi

  printf "%s\\n" "${_prompt}"
}

# _list_files()
#
# Usage:
#   _list_files <path> [--reverse] [--sort] [--standard-input] [--type <type>]
#
# Description:
#   List files in the current notebook or filenames from standard input.
_list_files() {
  local _path=
  local _read_from_standard_input=0
  local _reverse=0
  local _sort=0
  local _type=

  while ((${#}))
  do
    case "${1:-}" in
      --reverse)
        _reverse=1
        ;;
      --sort)
        _sort=1
        ;;
      --standard-input)
        _read_from_standard_input=1
        ;;
      --type)
        if _option_value_is_present "${2:-}"
        then
          _type="${2}"

          shift
        fi
        ;;
      --[A-Za-z]*)
        _type="${1:2}"
        ;;
      [^-]*)
        if [[ -z "${_path:-}" ]] && [[ "${1:-}" =~ ^/ ]]
        then
          _path="${1}"
        fi
    esac

    shift
  done

  if [[ -z "${_path:-}"   ]]
  then
    _path="$(_notebooks current --path)"
  fi

  if ((_read_from_standard_input)) && _piped_input
  then
    cat
  elif ((_sort))
  then
    cat "${_path}/.index"
  else
    ls -t -1 "${_path}"
  fi | {
    if ((_reverse))
    then
      # https://stackoverflow.com/a/744093
      LC_ALL=C sed '1!G;h;$!d'
    else
      cat
    fi
  } | {
    if [[ -n "${_type:-}" ]]
    then
      local __extension=
      local _grep_patterns=()

      case "${_type}" in
        bookmark|bookmarks)
          grep                  \
            -e '\.bookmark\.'   \
            -e '\-bookmark\.'
          ;;
        book|books)
          grep -e 'epub$'
          ;;
        note|notes)
          for __extension in "${_TEXT_FILE_EXTENSIONS[@]}"
          do
            _grep_patterns+=("-e" "${__extension}$")
          done

          grep "${_grep_patterns[@]}" \
            | grep -v                 \
                -e '\.bookmark\.'     \
                -e '\-bookmark\.'
          ;;
        folder|folders|directory|directories)
          local         __line=
          while read -r __line
          do
            if [[ -d "${_path}/${__line}" ]]
            then
              printf "%s\\n" "${__line}"
            fi
          done
          ;;
        archive)
          for __extension in "${_ARCHIVE_FILE_EXTENSIONS[@]}"
          do
            _grep_patterns+=("-e" "${__extension}$" "-e" "${__extension}.enc$")
          done

          grep "${_grep_patterns[@]}"
          ;;
        audio|music)
          for __extension in "${_AUDIO_FILE_EXTENSIONS[@]}"
          do
            _grep_patterns+=("-e" "${__extension}$" "-e" "${__extension}.enc$")
          done

          grep "${_grep_patterns[@]}"
          ;;
        document|documents|doc|docs)
          for __extension in "${_DOCUMENT_FILE_EXTENSIONS[@]}"
          do
            _grep_patterns+=("-e" "\.${__extension}$" "-e" "\.${__extension}\.enc$")
          done

          grep "${_grep_patterns[@]}"
          ;;
        encrypted)
          for __extension in "${_ENCRYPTED_FILE_EXTENSIONS[@]}"
          do
            _grep_patterns+=("-e" "\.${__extension}$")
          done

          grep "${_grep_patterns[@]}"
          ;;
        image|images|picture|pictures)
          for __extension in "${_IMAGE_FILE_EXTENSIONS[@]}"
          do
            _grep_patterns+=("-e" "\.${__extension}$" "-e" "\.${__extension}\.enc$")
          done

          grep "${_grep_patterns[@]}"
          ;;
        text|txt)
          for __extension in "${_TEXT_FILE_EXTENSIONS[@]}"
          do
            _grep_patterns+=("-e" "\.${__extension}$")
          done

          grep "${_grep_patterns[@]}"
          ;;
        todo|todos)
          for __extension in "${_TODO_FILE_EXTENSIONS[@]}"
          do
            _grep_patterns+=("-e" "\.${__extension}$")
          done

          grep "${_grep_patterns[@]}"
          ;;
        video|videos)
          for __extension in "${_VIDEO_FILE_EXTENSIONS[@]}"
          do
            _grep_patterns+=("-e" "\.${__extension}$" "-e" "\.${__extension}\.enc$")
          done

          grep "${_grep_patterns[@]}"
          ;;
        *)
          grep -e "\.${_type}$"
          ;;
      esac
    else
      cat
    fi
  }
}

# _open_in_gui_app()
#
# Usage:
#   _open_in_gui_app <url> | <path>
#
# Description:
#   Open <url> or <path> in the system GUI web browser or application for the
#   given file type.
_open_in_gui_app() {
  local _target="${1:-}"

  [[ -n "${_target:-}" ]] || return 1

  if [[ -n "${NB_GUI_BROWSER:-}" ]] &&
     _string_is_url "${_target:-}"
  then
    if [[ "${OSTYPE}" =~ cygwin|msys|win32    ]]
    then
      start "${NB_GUI_BROWSER:-}" "${_target}"
    else
      local _gui_browser_command=("${NB_GUI_BROWSER:-}")

      if _command_exists "${_gui_browser_command[0]:-}" ||
         [[ -f "${_gui_browser_command[0]:-}" ]]
      then
        "${_gui_browser_command[@]:-}" "${_target:-}" 2>/dev/null &
      fi
    fi
  elif _command_exists "wslview"
  then
    wslview "${_target}"
  elif _command_exists "xdg-open"
  then
    xdg-open "${_target}"
  elif _command_exists "open"
  then
    open "${_target}"
  elif [[ "${OSTYPE}" =~ cygwin|msys|win32    ]]
  then # https://stackoverflow.com/q/3739327
    rundll32 url.dll,FileProtocolHandler "${_target}"
  else
    return 1
  fi
}

# _pager()
#
# Usage:
#   _pager
#
# Description:
#   Display standard input in the preferred pager, `less`, `bat`, or `cat`.
_pager() {
  local _less_options=()
  _less_options=(-R --CLEAR-SCREEN --prompt="$(_less_prompt)" --mouse)

  if [[ -n  "${PAGER:-}"          ]]
  then
    local _pager_command=()
    IFS=" " read -r -a _pager_command <<< "${PAGER:-}"

    if [[   "${PAGER:-}" =~ less  ]]
    then
      "${_pager_command[@]:-less}" "${_less_options[@]:-}"
    else
      "${_pager_command[@]:-cat}"
    fi
  elif _command_exists "less"
  then
    less "${_less_options[@]:-}"
  elif _bat --command-exists
  then
    _bat --style numbers,grid
  else
    cat
  fi
}

# _pandoc()
#
# Usage:
#   _pandoc [--standard-input | <path>] [<pandoc-options>]
#
# Description:
#   Interact with pandoc, using iconv when available.
_pandoc() {
  if ! _command_exists "pandoc"
  then
    _warn printf "%spandoc%s not found.\\n" "${_BT}" "${_BT}"

    return 1
  fi

  local _pandoc_arguments=()
  local _path=
  local _read_from_standard_input=0

  case "${1:-}" in
    --standard-input)
      _read_from_standard_input=1
      ;;
    -*)
      _pandoc_arguments+=("${1:-}")
      ;;
    *)
      _path="${1:-}"
      ;;
  esac

  shift

  [[ -n "${1:-}" ]] && _pandoc_arguments+=("${@}")

  if [[ -n "${_path:-}" ]]
  then
    cd "${_path%/*}"
  fi

  if _command_exists "iconv"          &&  {
       ((_read_from_standard_input))  ||  _file_is_text "${_path:-}"
     }
  then
    {
      if ((_read_from_standard_input))
      then
        iconv -c -t utf-8
      else
        iconv -c -t utf-8 "${_path}"
      fi
    } | {
      if [[ -n "${_pandoc_arguments[*]:-}"  ]]
      then
        pandoc "${_pandoc_arguments[@]:-}" --wrap=preserve
      else
        pandoc --wrap=preserve
      fi
    } | {
      iconv -f utf-8
    }
  else
    if ! ((_read_from_standard_input))
    then
      _pandoc_arguments=("${_path}" "${_pandoc_arguments[@]:-}")
    fi

    if [[ -n "${_pandoc_arguments[*]:-}"    ]]
    then
      pandoc "${_pandoc_arguments[@]:-}"
    else
      pandoc
    fi
  fi
}

# _piped_input()
#
# Usage:
#   _piped_input
#
# Exit / Error / Return Status:
#   0 (success, true)  If piped input is present.
#   1 (error,  false)  If the current input is interactive (eg, a shell).
_piped_input() {
  [[ ! -t 0 ]]
}

# _print_line()
#
# Usage:
#   _print_line <text> [--muted] [--no-wrap] [--visible-length [<extra-length>]
#
# Description:
#   Print a line of dashes the length of <text>.
#
# More Information:
#   https://wiki.bash-hackers.org/commands/builtin/printf
_print_line() {
  local _extra_length=0
  local _muted=0
  local _text=
  local _visible_length=0
  local _wrap_line=1

  while ((${#}))
  do
    case "${1:-}" in
      --muted*) _muted=1              ;;
      --no*w*)  _wrap_line=0          ;;
      --vis*)   _visible_length=1     ;;
      *)
        case "${_text:-}" in
          '') _text="${1:-}"          ;;
          *)  _extra_length="${1:-}"  ;;
        esac
        ;;
    esac

    shift
  done

  local _text_length=

  if ((_visible_length))
  then
    _text_length="$(
      _get_visible_length "${_text:-}" "${_extra_length:-0}"
    )"
  else
    _text_length="${#_text}"
  fi

  local _full_width_line=0

  if ! ((_wrap_line)) && {
       [[ -z "${_text_length:-}"                    ]] ||
       [[    "${_text_length:-}" -gt "${_COLUMNS}"  ]]
     }
  then
    _full_width_line=1
  fi

  local _line=

  if ((_full_width_line))
  then
    printf -v _line "%*s" "${_COLUMNS}" ""
  else
    printf -v _line "%*s" "${_text_length}" ""
  fi

  if ((_muted))
  then
    _color_muted "${_line// /-}"
  else
    _color_secondary "${_line// /-}"
  fi |  if ((_full_width_line))
        then
          tr -d '\n'
        else
          cat
        fi
}

# _print_padding()
#
# Usage:
#   _print_padding <line> <columns> [<aligned>]
#
# Description:
#   Print a string of spaces that can be used as left padding to
#   center-align <line>. <aligned> is an optional boolean that can
#   be used to print no padding, returning an empty string.
_print_padding() {
  local _padding_centered="${3:-1}"
  local _padding_columns="${2:-}"
  local _padding_line="${1:-}"

  local _padding_line_length="${#_padding_line}"

  local _padding_amount=$(( (_padding_columns-_padding_line_length) / 2 ))

  if ((_padding_centered)) && ((_padding_amount))
  then
    printf "%-${_padding_amount}s" " "
  fi
}

# _print_welcome()
#
# Usage:
#   _print_welcome
#
# Description:
#   Print the welcome message.
_print_welcome() {
  local _padding=
  _padding="$(_print_padding " / / | | | | |_) |" "${_COLUMNS}")"

  _print_line "$(printf "%-${_COLUMNS}s" '.')"

  cat <<HEREDOC
${_padding}$(_color_primary "Welcome") to
${_padding}__          _
${_padding}\ \   _ __ | |__
${_padding} \ \ | '_ \| '_ \\
${_padding} / / | | | | |_) |
${_padding}/_/  |_| |_|_.__/
HEREDOC

  _print_line "$(printf "%-${_COLUMNS}s" '.')"
}

# _selector_get_identifier()
#
# Usage:
#   _selector_get_identifier <selector>
#
# Description:
#   Print the identifier (non-notebook) portion of a selector.
_selector_get_identifier() {
  local _selector="${1:-}"

  if [[   "${_selector:-}" =~ :     ]] &&
     [[ ! "${_selector:-}" =~ /.*:  ]]
  then
    printf "%s\\n" "${_selector#*:}" # strip notebook name
  else
    printf "%s\\n" "${_selector:-}"
  fi
}

# _selector_resolve_folders()
#
# Usage:
#   _selector_resolve_folders <selector> [<notebook-path>] [--build]
#
# Options:
#   --build  Build a new path that includes segments that don't exist yet.
#
# Description:
#   Resolve a selector path, which can be a mix of folder names and ids.
_selector_resolve_folders() {
  local _build_path=0
  local _folder_relative_path=
  local _notebook_path=
  local _selector=

  local __arg=
  for   __arg in "${@:-}"
  do
    case "${__arg}" in
      --build)
        _build_path=1
        ;;
      *)
        if [[ -z "${_selector:-}"   ]]
        then
          _selector="${__arg}"
        else
          _notebook_path="${__arg}"
        fi
        ;;
    esac
  done

  local _selector_path="${_selector#*:}"

  if [[ "${_selector}" =~ :         ]]
  then
    local _selector_notebook_path=
    _selector_notebook_path="$(
      _notebooks show "${_selector%%:*}" --path 2>/dev/null || :
    )"

    if [[ -n "${_selector_notebook_path:-}"     ]]
    then
      _notebook_path="${_selector_notebook_path}"
    fi
  fi

  if [[ -z "${_notebook_path:-}"    ]]
  then
    _notebook_path="$(_notebooks current --path)"
  fi

  if [[ "${_selector_path}" =~ ^/   ]]
  then
    _selector_path="${_selector_path#"${_notebook_path}"/}"
  fi

  if [[ ! "${_selector_path}"  =~ / ]]
  then
    if ((_build_path))
    then
      _build_path=0
      _selector_path="${_selector_path}/"
    else
      return 0
    fi
  fi

  while [[ "${_selector_path}" =~ / ]]
  do
    local _folder_name=
    local _parent_folder_path=
    local _selector_segment="${_selector_path%%\/*}"

    if [[ -z "${_folder_relative_path:-}"       ]]
    then
      _parent_folder_path="${_notebook_path}"
    else
      _parent_folder_path="${_notebook_path}/${_folder_relative_path}"
    fi

    if [[ -n "${_selector_segment:-}"           ]]
    then
      if [[ "${_selector_segment}" =~ ^[0-9]+$  ]]
      then # folder name might be an id
        _folder_name="$(
          _index get_basename "${_selector_segment:?}" "${_parent_folder_path:?}" ||
            printf "%s\\n" "${_selector_segment:?}"
        )"
      fi

      if [[ -z "${_folder_name:-}"              ]]
      then
        _folder_name="${_selector_segment}"
      fi

      if [[ -d "${_parent_folder_path:?}/${_folder_name:?}" ]] ||
         ((_build_path))
      then
        if [[ -z "${_folder_relative_path:-}"   ]]
        then
          _folder_relative_path="${_folder_name}"
        else
          _folder_relative_path+="/${_folder_name}"
        fi

        _selector_path="${_selector_path#*/}"

        continue
      fi
    fi

    return 1
  done

  printf "%s\\n" "${_folder_relative_path:-}"
}

# _selector_resolve_path()
#
# Usage:
#   _selector_resolve_path <selector> [<notebook-path>] [--full | --relative]
#                          [--skip-titles]
#
# Options:
#   --full  Print the full path.
#
# Description:
#   Determine relative path of the file that is identified by the given <id>,
#   <filename>, <path>, or <title> and is in the current notebook or a
#   notebook specified with a colon prefix.
#
#   Examples:
#     1
#     example.md
#     title
#     relative/path/to/example.md
#     /path/to/example.md
#     notebook:1
#     notebook:example.md
#     notebook:title
#     notebook:relative/path/to/example.md
#     notebook:/path/to/example.md
_selector_resolve_path() {
  local _identifier=
  local _notebook_path=
  local _print_full_path=0
  local _relative_path=
  local _selector=
  local _skip_titles=0

  local __arg=
  for   __arg in "${@:-}"
  do
    case "${__arg:-}" in
      --full)
        _print_full_path=1
        ;;
      --skip-titles)
        _skip_titles=1
        ;;
      [^-]*)
        if [[ -z "${_selector:-}"   ]]
        then
          _selector="${__arg%/}" # strip trailing /
        else
          _notebook_path="${__arg:-}"
        fi
        ;;
    esac
  done

  if [[ -n "${_selector}"           ]]
  then
    if [[ -z "${_notebook_path:-}"  ]] &&
       [[ "${_selector}" =~ (:|^/)  ]]
    then
      _notebook_path="$(
        _notebooks show "${_selector}" --path 2>/dev/null || :
      )"
    fi

    if [[ -z "${_notebook_path:-}"  ]]
    then
      _notebook_path="$(
        _notebooks current --path 2>/dev/null || :
      )"
    fi

    _identifier="$(_selector_get_identifier "${_selector}")"
    _identifier="${_identifier%/}" # strip trailing /

    if [[ -e "${_identifier}"                     ]] &&
       [[ "${_identifier}" =~ ^${_notebook_path}  ]]
    then # <selector> is a full path in the current notebook
      _relative_path="${_identifier/${_notebook_path}}"
      _relative_path="${_relative_path#\/}"
    elif [[ "${_identifier}" =~ ^/  ]] &&
         [[ -e "${_identifier:-}"   ]]
    then # <selector> is a full path in a different notebook
      _notebook_path="$(
        _notebooks show "${_identifier}" --path 2>/dev/null
      )"

      _relative_path="${_identifier/"${_notebook_path}"\//}"
    elif [[ -e  "${_notebook_path}/${_identifier}"  ]] &&
         [[ !   "${_identifier}" =~ ^[0-9]+$        ]]
    then # <selector> is a relative path with a non-numeric filename
      _relative_path="${_identifier}"
    else
      local _folder_path="${_notebook_path}"
      local _folder_relative_path=
      _folder_relative_path="$(
        _selector_resolve_folders "${_selector}" "${_notebook_path}"
      )" || return 0

      if [[ -n "${_folder_relative_path:-}"     ]]
      then
        _folder_path="${_notebook_path}/${_folder_relative_path}"
      fi

      _identifier="${_identifier##*/}"

      if [[ -e "${_folder_path}/${_identifier}" ]] &&
         [[ !  "${_identifier}" =~ ^[0-9]+$     ]]
      then # <selector> is relative path with a non-numeric filename
        _relative_path="${_folder_relative_path}/${_identifier}"
      elif [[ "${_identifier}" =~ ^[0-9]+$      ]]
      then # <selector> is an id
        local _basename=
        _basename="$(_index get_basename "${_identifier}" "${_folder_path}")"

        if [[ -n "${_basename:-}"                     ]]
        then
          if [[ -n "${_folder_relative_path:-}"       ]]
          then
            _relative_path="${_folder_relative_path}/${_basename}"
          else
            _relative_path="${_basename}"
          fi
        elif [[ -e "${_notebook_path}/${_identifier}" ]]
        then # <selector> is a relative path with numeric filename
          _relative_path="${_identifier}"
        fi
      elif ! ((_skip_titles))
      then # <selector> might be a title
        local _maybe_title="${_identifier##*\/}"

        _relative_path="$(
          {
            _list_files "${_folder_path}"
          } | {
            local         __filename=
            while read -r __filename || [[ -n "${__filename:-}" ]]
            do
              local _title=
              _title="$(
                _get_content "${_folder_path}/${__filename}" --title
              )"

              if [[ -n "${_title}"                              ]] &&
                 {
                   [[ "${_title}" == "${_maybe_title}"          ]] ||
                   {
                     [[ "${__filename}"   =~ todo\.md$          ]] &&
                     [[ "${_maybe_title}" == "${_title##*] }"   ]]
                   }
                 }
              then
                local _full_path="${_folder_path}/${__filename}"

                printf "%s\\n" "${_full_path/"${_notebook_path}"\//}"

                break
              fi
            done
          }
        )"
      fi
    fi
  fi

  if [[ -n "${_identifier:-}" ]] && [[ -z "${_relative_path:-}" ]]
  then
    return 0
  elif ((_print_full_path))
  then
    printf "%s\\n" "$(_join "/" "${_notebook_path}" "${_relative_path:-}")"
  else
    printf "%s\\n" "${_relative_path:-}"
  fi
}

# _spinner()
#
# Usage:
#   _spinner <pid>
#
# Description:
#   Display an ascii spinner while <pid> is running.
#
# Example Usage:
#   ```
#   _spinner_example() {
#     printf "Working..."
#     (sleep 1) &
#     _spinner $!
#     printf "Done!\\n"
#   }
#   (_spinner_example)
#   ```
#
# More Information:
#   http://fitnr.com/showing-a-bash-spinner.html
_spinner() {
  local _delay=0.1
  local _pid="${1:-}"
  local _spin_string="|/-\\"

  if [[ -z "${_pid:-}" ]]
  then
    _exit_1 printf "Usage: _spinner <pid>\\n"
  fi

  while ps a | awk '{print $1}' | grep -q "${_pid}"
  do
    local _temp="${_spin_string#?}"

    if ((_COLOR_ENABLED))
    then
      printf " %s%s[%s%c%s]%s"    \
        "${_TPUT_SGR0}"           \
        "${_TPUT_SETAF_8}"        \
        "${_TPUT_COLOR_PRIMARY}"  \
        "${_spin_string}"         \
        "${_TPUT_SETAF_8}"        \
        "${_TPUT_SGR0}"

      printf "\b\b\b\b"
    fi

    sleep ${_delay}

    _spin_string="${_temp}${_spin_string%"${_temp}"}"
  done

  return 0
}

# _string_is_email()
#
# Usage:
#   _string_is_email <string>
#
# Exit / Error / Return Status:
#   0 (success, true)  If the string is recognized as an email address.
#   1 (error,  false)  if not.
_string_is_email() {
  [[ "${1:-}" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]+$ ]]
}

# _string_is_url()
#
# Usage:
#   _string_is_url <string>
#
# Exit / Error / Return Status:
#   0 (success, true)  If the string is a recognized URL.
#   1 (error,  false)  if not.
_string_is_url() {
  [[ -z "${1:-}" ]] && return 1

  local _url_match_patterns=()

  local __url_match_pattern=
  for   __url_match_pattern in "${_URL_PATTERNS[@]}"
  do
    _url_match_patterns+=(-e "^${__url_match_pattern}$")
  done

  printf "%s\\n" "${1:-}" | grep -E -q "${_url_match_patterns[@]:-}" &>/dev/null
}

# _wrap()
#
# Usage:
#   _wrap [on | off]
#
# Description:
#   Turn on line wrapping / automatic margins.
_wrap() {
  if [[ "${1:-}" == "off"  ]]
  then
    # NOTE: `tput` vs escape sequence:
    # https://unix.stackexchange.com/a/558771
    # https://unix.stackexchange.com/a/515938
    # https://superuser.com/a/189068

    # tput rmam
    printf '\033[?7l'
  elif [[ "${1:-}" == "on" ]]
  then
    # tput smam
    printf '\033[?7h'
  fi
}

###############################################################################
# describe
###############################################################################

# describe()
#
# Usage:
#   describe <name> <description>
#   describe --get <name>
#
# Options:
#   --get  Print the description for <name> if one has been set.
#
# Examples:
# ```
#   describe "list" <<HEREDOC
# Usage:
#   ${_ME} list
#
# Description:
#   List items.
# HEREDOC
#
# describe --get "list"
# ```
#
# Set or print a description for a specified command or function <name>. The
# <description> text can be passed as the second argument or as standard input.
#
# To make the <description> text available to other functions, `describe()`
# assigns the text to a variable with the format `$____DESCRIBE_<name>`.
#
# When the `--get` option is used, the description for <name> is printed, if
# one has been set.
describe() {
  set +e
  [[ -z "${1:-}"          ]] &&
    _exit_1 printf "describe(): <name> required.\\n"

  if [[ "${1}" == "--get" ]]
  then # get ------------------------------------------------------------------
    [[ -z "${2:-}"        ]] &&
      _exit_1 printf "describe(): <description> required.\\n"

    local _name="${2:-}"
    local _describe_var="____DESCRIBE_${_name//-/_}"

    if [[ !   "${_name}" =~ ^\-               ]] &&
       [[     "${_name}" =~ ^[A-Za-z0-9_-]+$  ]] &&
       [[ -n  "${!_describe_var:-}"           ]]
    then
      printf "%s\\n" "${!_describe_var}"
    elif _command_exists "_describe_${_name:-}"
    then
      "_describe_${_name:-}"
    else
      printf "No additional information for \`%s\`\\n" "${_name}"
    fi
  else # set ------------------------------------------------------------------
    if [[ -n "${2:-}"     ]]
    then # argument is present
      read -r -d '' "____DESCRIBE_${1//-/_}" <<HEREDOC
${2}
HEREDOC

      eval "_describe_${1}() { printf \"%s\\n\" \"${2:-}\"; }"
    else # no argument is present, so assume piped input
      local _describe_var="____DESCRIBE_${1//-/_}"

      read -r -d '' "${_describe_var}"

      eval "_describe_${1}() { printf \"%s\\n\" \"${!_describe_var:-}\"; }"
    fi
  fi
  set -e
}

# Support legacy `desc` name.
desc() { describe "${@}"; }

###############################################################################
# Subcommands: Group 1                                     Subcommands: Group 1
# --------------------                                     --------------------
#
# `ls` and dependencies.
###############################################################################
# --------------------------------------------------------------------------- #

# count · ############################################################# · count

_describe_count() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} count [<notebook>:][<folder-path>/]

$(_color_primary "Description"):
  Print the number of items in the first level of the current notebook,
  <notebook>, or the folder at <folder-path>.
HEREDOC
}
_count() {
  local _list_files_options=()
  local _selector=
  local _skip_unmatched_selector=0

  while ((${#}))
  do
    case "${1:-}" in
      --skip-unmatched-selector)
        _skip_unmatched_selector=1
        ;;
      --type)
        _list_files_options+=("${1}")
        _list_files_options+=(_option_get_value "${1}" "${2:-}")

        shift
        ;;
      -*|/*)
        _list_files_options+=("${1}")
        ;;
      *)
        _selector="${1}"
        ;;
    esac

    shift
  done

  if [[ -n "${_selector:-}"         ]]
  then
    local _selector_path=
    _selector_path="$(_selector_resolve_path "${_selector}" --full)"

    if [[ -z "${_selector_path:-}"  ]]
    then
      if ! ((_skip_unmatched_selector))
      then
        _warn printf "Not found: %s\\n" "$(_color_primary "${_selector:-}")"

        return 1
      fi
    else
      _list_files_options+=("${_selector_path:-}")
    fi
  fi

  _list_files "${_list_files_options[@]:-}" | wc -l | tr -d ' '
}

# git · ################################################################# · git

_describe_git() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} git [checkpoint [<message>] | dirty]
  ${_ME} git <git-options>...

$(_color_primary "Subcommands"):
  checkpoint    Create a new git commit in the current notebook and sync with
                the remote if \`${_ME} set auto_sync\` is enabled.
  dirty         0 (success, true) if there are uncommitted changes in the
                current notebook. 1 (error, false) if the notebook is clean.

$(_color_primary "Description"):
  Run \`git\` commands within the current notebook directory.

$(_color_primary "Read More"):
  ${_README_URL}#-git-sync
  ${_README_URL}#-revision-history

$(_color_primary "See Also"):
  ${_ME} help history
  ${_ME} help remote
  ${_ME} help run
  ${_ME} help status
  ${_ME} help sync

$(_color_primary "Examples"):
  ${_ME} git status
  ${_ME} git diff
  ${_ME} git log
  ${_ME} example:git status
HEREDOC
}
_git() {
  # _git_autosyncable()
  #
  # Usage:
  #   _git_autosyncable [<notebook-path>]
  #
  # Exit / Error / Return Status:
  #   0 (success, true)  If autosync should trigger.
  #   1 (error,  false)  If autosync should not trigger.
  _git_autosyncable() {
    ((_GIT_ENABLED)) || return 1

    local _last_fetch_timestamp=
    local _notebook_path="${1:-}"

    if [[ -z "${_notebook_path}" ]]
    then
      _notebook_path="$(_notebooks current --path)"
    fi

    if ! ((NB_AUTO_SYNC))
    then # autosync not enabled.
      return 1
    fi

    if ! git -C "${_notebook_path}" config --get remote.origin.url &>/dev/null
    then # there is no remote configured.
      return 1
    fi

    if [[ ! -e "${_notebook_path}/.git/FETCH_HEAD" ]]
    then # no previous fetches, but has an origin and autosync is enabled.
      return 0
    fi

    if [[ -s "${_notebook_path}/.git/nb/last_sync_state_checked" ]]
    then
      _last_fetch_timestamp="$(
        cat "${_notebook_path}/.git/nb/last_sync_state_checked" 2>/dev/null
      )"
    fi

    if [[ -z "${_last_fetch_timestamp:-}" ]]
    then
      _last_fetch_timestamp="$(
        _get_last_modified_timestamp "${_notebook_path}/.git/FETCH_HEAD"
      )"
    fi

    local _current_timestamp=
    _current_timestamp="$(date +%s)"

    local _diff=
    _diff=$((_current_timestamp-_last_fetch_timestamp))

    [[ "${_diff}" -gt "${NB_AUTO_SYNC_SECONDS:-60}" ]]
  }

  # _git_checkpoint()
  #
  # Usage:
  #   _git_checkpoint <notebook-path> <commit-message>
  #
  # Description:
  #   Commit all files in <notebook-path> with the provided <commit-message>.
  _git_checkpoint() {
    ((_GIT_ENABLED)) || return 0

    # Usage: _git_checkpoint_commit <notebook-path> <message>
    _git_checkpoint_commit() {
      local _message="${2:-}"
      local _notebook_path="${1:-}"

      if [[ -z "${_notebook_path:-}" ]] || [[ -z "${_message:-}" ]]
      then
        _exit_1 printf \
           "Usage: _git_checkpoint_commit <message> <notebook-path>"
      fi

      git -C "${_notebook_path}" add --all &&
        git -C "${_notebook_path}" commit -a -m "${_message}"
    }

    local _message=
    local _notebook_path=
    local _wait=0

    local __arg=
    for   __arg in "${@:-}"
    do
      case "${__arg}" in
        --spinner|--wait)
          _wait=1
          ;;
        *)
          if [[ -z "${_notebook_path}"  ]] &&
             [[ "${__arg}" =~ ^/        ]] &&
             [[ -d "${__arg}"           ]]
          then
            _notebook_path="${__arg}"
          elif [[ -z "${_message}" ]]
          then
            _message="${__arg}"
          fi
          ;;
      esac
    done

    if [[ -z "${_notebook_path:-}" ]]
    then
      _notebook_path="$(_notebooks current --path)"
    fi

    if [[ -z "${_message}" ]]
    then
      _message="[${_ME}] Commit"
    fi

    if ((NB_AUTO_SYNC))
    then
      (
        {
          # only commit when the index is dirty
          if _git dirty "${_notebook_path}"
          then
            _git_checkpoint_commit "${_notebook_path}" "${_message}" &>/dev/null
          fi && GIT_TERMINAL_PROMPT=0 _git sync "${_notebook_path}"  &>/dev/null
        } || :
      ) &
    else
      (
        _git_checkpoint_commit "${_notebook_path}" "${_message}" &>/dev/null ||
          return 0
      ) &
    fi

    if ((_wait))
    then
      if ! _piped_input
      then # interative shell
        _spinner  ${!}
      fi

      wait      ${!}
      return    ${?}
    else
      return    0
    fi
  }

  # _git_dirty()
  #
  # Usage:
  #   _git_dirty [<notebook-path>]
  #
  # Exit / Error / Return Status:
  #   0 (success, true)  If there are uncommitted changes in <notebook-path>
  #                      or the current notebook.
  #   1 (error,  false)  If <notebook-path> or the current notebook is clean.
  _git_dirty() {
    ((_GIT_ENABLED)) || return 1

    local _target_path="${1:-}"

    if [[ -z "${_target_path:-}" ]]
    then
      _target_path="$(_notebooks current --path)"
    fi

    [[ -n "$(git -C "${_target_path}" status --porcelain)" ]]
  }

  # _git_out_of_sync()
  #
  # Usage:
  #   _git_out_of_sync [<notebook-path>]
  #
  # Exit / Error / Return Status:
  #   0 (success, true)  If <notebook-path> or the current notebook is out of
  #                      sync with the remote.
  #   1 (error,  false)  If <notebook-path> or the current notebook is synced
  #                      with the remote.
  _git_out_of_sync() {
    ((_GIT_ENABLED)) || return 1

    local _notebook_path="${1:-}"

    if [[ -z "${_notebook_path:-}" ]]
    then
      _notebook_path="$(_notebooks current --path)"
    fi

    # get the current branch name
    local _branch=
    _branch="$(
      git -C "${_notebook_path}" rev-parse --abbrev-ref HEAD
    )"

    # get the local branch HEAD SHA
    local _local_head=
    _local_head="$(
      git -C "${_notebook_path}" rev-parse "${_branch}"
    )"

    # get the remote branch HEAD SHA
    local _remote_head=
    _remote_head="$(
      git -C "${_notebook_path}" ls-remote origin "refs/heads/${_branch}" 2>/dev/null | awk '{print $1}'
    )"

    mkdir -p "${_notebook_path}/.git/nb"
    date +%s > "${_notebook_path}/.git/nb/last_sync_state_checked"

    [[ -n "${_remote_head:-}" ]] && [[ "${_local_head}" != "${_remote_head}" ]]
  }

  # _git_required()
  #
  # Usage:
  #   _git_required
  #
  # Description:
  #   Exit with `_exit_1` if `git` isn't found.
  _git_required() {
    ((_GIT_ENABLED)) || return 0

    if ! _command_exists "git"
    then
      _exit_1 cat <<HEREDOC
Welcome to $(_color_primary "${_ME}")!

Git is required, but wasn't found. Install Git, then run \`${_ME}\` again.

About Git: $(_color_primary "https://git-scm.com")
HEREDOC
    fi

    local _git_name=
    _git_name="$(git config --global --includes user.name   || printf '')"

    local _git_email=
    _git_email="$(git config --global --includes user.email || printf '')"

    if [[ -z "${_git_name:-}"   ]]  ||
       [[ -z "${_git_email:-}"  ]]
    then
      cat <<HEREDOC
Welcome to $(_color_primary "${_ME}")!

Git requires some additional setup before using $(_color_primary "${_ME}").
Enter the name and email address you'd like to use with Git.
Edits you make are attributed to this name and email address.
HEREDOC
      if [[ -z "${_git_name:-}"   ]]
      then
        while true
        do
          local __name=
          IFS='' read -r -e -d $'\n' -p "$(_color_primary "Name"):  " __name

          if [[ -n "${__name:-}"  ]]
          then
            git config --global --includes user.name "${__name}"

            break
          fi
        done
      fi

      if [[ -z "${_git_email:-}"  ]]
      then
        while true
        do
          local __email=
          IFS='' read -r -e -d $'\n' -p "$(_color_primary "Email"): " __email

          if [[ -n "${__email:-}" ]]
          then
            git config --global --includes user.email "${__email}"

            break
          fi
        done
      fi
    fi
  }

  # _git_sync()
  #
  # Usage:
  #   _git_sync [<notebook-path>]
  #
  # Description:
  #   Sync <notebook-path> or the current notebook with the remote.
  _git_sync() {
    local _notebook_path="${1:-}"
    local _prompt="${GIT_TERMINAL_PROMPT:-1}"

    if _contains "--skip-prompt" "${1:-}" "${2:-}"
    then
      _prompt=0
    fi

    if [[ -z "${_notebook_path:-}"  ]]
    then
      _notebook_path="$(_notebooks current --path)"
    fi

    local _remote_url=

    if ! _remote_url="$(git -C "${_notebook_path}" remote get-url origin 2>/dev/null)" ||
       [[ -z "${_remote_url:-}"     ]]
    then
      return 0
    fi

    local _git_branch=
    _git_branch="$(git -C "${_notebook_path}" rev-parse --abbrev-ref HEAD 2>/dev/null)"

    local _branch_query_succeeded=0

    local _remote_branches=
    _remote_branches=($(
      git -C "${_notebook_path}" ls-remote --heads "${_remote_url}" 2>/dev/null \
        | LC_ALL=C sed "s/.*\///g"
    )) && _branch_query_succeeded=1

    if ! GIT_TERMINAL_PROMPT=0 git -C "${_notebook_path}" fetch origin "${_git_branch}" &>/dev/null
    then
      if _contains "${_git_branch}" "${_remote_branches[@]:-}" ||
         ! ((_branch_query_succeeded))
      then
        if ((_prompt))
        then # fetch again, displaying git prompt and/or errors after newline
          printf "\\n"

          if ! GIT_TERMINAL_PROMPT=1 git -C "${_notebook_path}" fetch origin "${_git_branch}"
          then
            exit 1
          fi
        else
          return 1
        fi
      fi
    fi

    if ((_prompt))
    then
      if ! _contains "${_git_branch}" "${_remote_branches[@]:-}"  ||
         ! git -C "${_notebook_path}" show-branch                 \
           "remotes/origin/${_git_branch}" > /dev/null 2>&1       ||
         {
           local _local_branch_root_hash=
           _local_branch_root_hash="$(
             git -C "${_notebook_path}" rev-list --max-parents=0  \
               "${_git_branch}"
           )"

           local _remote_branch_root_hash=
           _remote_branch_root_hash="$(
             git -C "${_notebook_path}" rev-list --max-parents=0  \
               "remotes/origin/${_git_branch}"
           )"

           [[ "${_local_branch_root_hash:-}" != "${_remote_branch_root_hash:-}" ]]
         }
      then
        printf "\\n"

        _remote set "${_remote_url}" "${_git_branch}" --skip-preamble

        _git_branch="$(git -C "${_notebook_path}" rev-parse --abbrev-ref HEAD)"
      fi
    fi

    if git -C "${_notebook_path}" show-branch \
         "remotes/origin/${_git_branch}"      \
         > /dev/null 2>&1                     &&
         ! git -C "${_notebook_path}" rebase "origin/${_git_branch}" &>/dev/null
    then
      local _merge_error=1

      local _conflicted_files=
      _conflicted_files=($(
        GIT_PAGER='' git -C "${_notebook_path}" diff --name-only --diff-filter=U
      ))

      local _conflicted_binary_files=()
      local _conflicted_text_files=()

      if [[ -n "${_conflicted_files[*]:-}" ]]
      then
        local __maybe_index_relative_path=
        for   __maybe_index_relative_path in "${_conflicted_files[@]}"
        do
          if [[ "${__maybe_index_relative_path}" =~ (^.index$|/.index$) ]]
          then
            # Remove git conflict markers to keep both.
            # More info: https://stackoverflow.com/a/55187779
            _sed_i              \
              -e '/^<<<<<<</d'  \
              -e '/^>>>>>>>/d'  \
              -e '/=======/d'   \
              "${_notebook_path}/${__maybe_index_relative_path}"

            git -C "${_notebook_path}" add "${__maybe_index_relative_path}"
          fi
        done

        local __relative_path=
        for   __relative_path in "${_conflicted_files[@]}"
        do
          [[ "${__relative_path}" =~ (^.index$|/.index$) ]] && continue

          if _file_is_text "${__relative_path}"
          then
            _conflicted_text_files+=("${__relative_path}")

            git -C "${_notebook_path}" add                \
              "${__relative_path}"
          else
            git -C "${_notebook_path}" checkout           \
              "origin/${_git_branch}" -- "${__relative_path}"

            local _conflicted_file=
            _conflicted_file="$(
              _notebooks show "${_notebook_path}"         \
                --filename  "${__relative_path%%.*}--conflicted-copy.${__relative_path#*.}"
            )"

            _conflicted_binary_files+=("${_conflicted_file}")

            git -C "${_notebook_path}" mv                 \
              "${__relative_path}" "${_conflicted_file}"

            git -C "${_notebook_path}" checkout           \
              "${_git_branch}" -- "${__relative_path}"

            git -C "${_notebook_path}" add "${_conflicted_file}"
            git -C "${_notebook_path}" add "${__relative_path}"
          fi
        done

        GIT_EDITOR=true git -C "${_notebook_path}" rebase \
          --continue &>/dev/null                          &&
            _merge_error=0
      fi

      if ((_merge_error))
      then
        git -C "${_notebook_path}" rebase --abort

        _warn printf                                              \
          "Merge conflict. Use \`%s git\` to merge manually.\\n"  \
          "${_ME}"

        return 1
      else
        local _notebook_name=
        _notebook_name="$(_notebooks show "${_notebook_path}" --name)"

        if ((${#_conflicted_text_files[@]}))
        then
          printf "\\n"

          _warn cat <<HEREDOC
Files containing conflicts:

$(printf "  %s\\n" "${_conflicted_text_files[@]/#/${_notebook_name}:}")

Resolve conflicts with \`${_ME} edit\`. More info: \`${_ME} help sync\`
HEREDOC
        fi

        if ((${#_conflicted_binary_files[@]}))
        then
          printf "\\n"

          _warn cat <<HEREDOC
Conflicted copies of binary files:

$(printf "  %s\\n" "${_conflicted_binary_files[@]/#/${_notebook_name}:}")
HEREDOC
        fi
      fi
    fi

    GIT_TERMINAL_PROMPT="${GIT_TERMINAL_PROMPT:-1}" \
      git -C "${_notebook_path}" push               \
      --set-upstream                                \
      origin "${_git_branch}"                       \
      &>/dev/null || {
        _warn printf "Unable to push to remote.\\n"

        return 1
      }
  }

  case "${1:-}" in
    *autosync*)
      _git_autosyncable "${2:-}"
      ;;
    checkpoint)
      shift

      _git_checkpoint "${@:-}"
      ;;
    dirty)
      _git_dirty "${2:-}"
      ;;
    out*of*sync|o|oos|out)
      _git_out_of_sync "${2:-}"
      ;;
    required|setup)
      _git_required
      ;;
    sync)
      _git_sync "${2:-}" "${3:-}"
      ;;
    *)
      local _notebook_path=
      _notebook_path="$(_notebooks current --path)"

      if [[ -n "${1:-}" ]]
      then
        git -C "${_notebook_path}" "${@}"
      else
        git -C "${_notebook_path}"
      fi
      ;;
  esac
}

# help · ############################################################### · help

export _README_URL="https://github.com/xwmx/nb"

_describe_help() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} help [<subcommand>] [-p | --print]
  ${_ME} help [-c | --colors] | [-r | --readme] | [-s | --short] [-p | --print]

$(_color_primary "Options"):
  -c, --colors  View information about color themes and color settings.
  -p, --print   Print to standard output / terminal.
  -r, --readme  View the \`${_ME}\` README file.
  -s, --short   Print shorter help without subcommand descriptions.

$(_color_primary "Description"):
  Print the program help information. When a subcommand name is passed, print
  the help information for the subcommand.

$(_color_primary "Examples"):
  ${_ME} help
  ${_ME} help add
  ${_ME} help import
  ${_ME} h notebooks
  ${_ME} h e

$(_color_primary "Shortcut Alias"):
  ${_ME} h
HEREDOC
}
_help() {
  local _arguments=()
  local _color_help=0
  local _readme=0
  local _shell=0
  local _short=0
  local _use_pager=1

  local __arg=
  for   __arg in "${@:-}"
  do
    case "${__arg}" in
      +) _help "add"    && return 0 ;;
      -) _help "delete" && return 0 ;;
      --pager)
        _use_pager=1
        ;;
      -p|--print|--dump|--skip*pager|--no*pager)
        _use_pager=0
        ;;
      -r|*readme*|*README*)
        _readme=1
        ;;
      --shell)
        _shell=1
        ;;
      -s|--short)
        _short=1
        ;;
      -c|*color*|*colour*|*theme*)
        _color_help=1
        ;;
      *)
        _arguments+=("${__arg}")
        ;;
    esac
  done

  if ! ((_COLOR_ENABLED))
  then
    _TPUT_COLOR_PRIMARY=""
    _TPUT_SETAF_8=""
    _TPUT_SGR0=""
  fi

  if ((_readme))
  then
    _download_from --no-chrome              \
      "${_REPO_RAW_URL}/README.md"          \
        | if _command_exists "pandoc"       &&
             _web_browser --check
          then
            _pandoc                         \
              --standard-input              \
              --from  markdown              \
              --to    html                  \
              2>/dev/null                   \
              | _web_browser

            return 0
          else
            _highlight_syntax_if_available  \
              | if ((_use_pager))
                then
                  _pager
                else
                  cat
                fi
          fi
  else
    if ((_color_help))
    then
      # NOTE: this screen mirrors the content from README.md#-color-themes:
      # https://github.com/xwmx/nb#-color-themes
      _color_primary  " __          _                     _"
      _color_primary  " \ \   _ __ | |__         ___ ___ | | ___  _ __ ___"
      _color_primary  "  \ \ | '_ \| '_ \   _   / __/ _ \| |/ _ \| '__/ __|"
      _color_primary  "  / / | | | | |_) | (_) | (_| (_) | | (_) | |  \__ \\"
      _color_primary  " /_/  |_| |_|_.__/       \___\___/|_|\___/|_|  |___/"
      printf "\\n"
      _color_secondary \
                      " ---------------------------------------------------"
      printf "\\n"
      cat <<HEREDOC
\`${_ME}\` uses color to highlight various interface elements, including ids,
the current notebook name, the shell prompt, and divider lines.

\`${_ME}\` includes several built-in color themes and also supports user-defined
themes. The current color theme can be set using \`${_ME} set color_theme\`:

    $(_color_primary "${_ME} set color_theme")

Custom color themes are \`${_ME}\` plugins with a \`.${_ME}-theme\` file extension.
A theme is defined with a single \`if\` statement indicating the name and
assigning the color environment variables to \`tput\` ANSI color numbers:

    $(_color_secondary "# turquoise.${_ME}-theme")
    $(_color_primary "if [[ \"\${NB_COLOR_THEME}\" == ${_TPUT_SGR0}\"turquoise\"${_TPUT_COLOR_PRIMARY} ]]")
    $(_color_primary "then")
    $(_color_primary "  export NB_COLOR_PRIMARY=${_TPUT_SGR0}43${_TPUT_COLOR_PRIMARY}")
    $(_color_primary "  export NB_COLOR_SECONDARY=${_TPUT_SGR0}38${_TPUT_COLOR_PRIMARY}")
    $(_color_primary "fi")

View this theme as a complete file

    $(_color_primary "https://github.com/xwmx/nb/blob/master/plugins/turquoise.${_ME}-theme")

Themes can be installed using the \`${_ME} plugins\` subcommand:

    $(_color_muted ">") $(_color_primary "${_ME} plugins install https://github.com/xwmx/nb/blob/master/plugins/turquoise.${_ME}-theme")
    $(_color_secondary "Plugin installed:")
    $(_color_secondary "/home/example/.${_ME}/.plugins/turquoise.${_ME}-theme")

Once a theme is installed, use it with \`${_ME} set color_theme\`:

    $(_color_muted ">") $(_color_primary "${_ME} set color_theme turquoise")
    $(_color_secondary "NB_COLOR_THEME set to turquoise")

The primary and secondary colors can also be overridden individually,
making color themes easily customizable:

    $(_color_secondary "# open the settings prompt for the primary color")
    $(_color_primary "${_ME} set color_primary")

    $(_color_secondary "# open the settings prompt for the secondary color")
    $(_color_primary "${_ME} set color_secondary")

To view a table of available colors and numbers, run:

    $(_color_primary "${_ME} settings colors")

To set the syntax highlighting color theme, use:

    $(_color_primary "${_ME} set syntax_theme")

HEREDOC
    elif [[ -z "${_arguments[*]:-}" ]] || ((_short))
    then
      _color_primary        " __          _"
      _color_primary        " \ \   _ __ | |__"
      _color_primary        "  \ \ | '_ \| '_ \\"
      _color_primary        "  / / | | | | |_) |"
      _color_primary        " /_/  |_| |_|_.__/"

      printf        \
        "\\n %s\\n" \
        "$(_color_secondary  "------------------")"

      cat <<HEREDOC

$(_color_brackets "${_ME}") Command line and local web note-taking, bookmarking, and archiving with
plain text data storage, encryption, filtering and search, pinning, #tagging,
Git-backed versioning and syncing, Pandoc-backed conversion, global and local
notebooks, customizable color themes, [[wiki-style linking]], plugins, and more
in a single portable, user-friendly script.

$(_color_primary "Help"):
  ${_ME} help               Display this help information.
  ${_ME} help <subcommand>  View help information for <subcommand>.
  ${_ME} help --colors      View information about color settings.
  ${_ME} help --readme      View the \`${_ME}\` README file.

$(_color_primary "Usage"):
  ${_ME}
  ${_ME} [<ls-options>...] [<id> | <filename> | <path> | <title> | <notebook>]
  ${_ME} [<url>] [<bookmark options>...]
  ${_ME} add [<notebook>:][<folder-path>/][<filename>] [<content>]
         [-b | --browse] [-c <content> | --content <content>] [--edit]
         [-e | --encrypt] [-f <filename> | --filename <filename>]
         [--folder <folder-path>] [--no-template] [--tags <tag1>,<tag2>...]
         [--template <template>] [-t <title> | --title <title>] [--type <type>]
  ${_ME} add bookmark [<bookmark-options>...]
  ${_ME} add folder [<name>]
  ${_ME} add todo [<todo-options>...]
  ${_ME} archive [<notebook>]
  ${_ME} bookmark [<ls-options>...]
  ${_ME} bookmark [<notebook>:][<folder-path>/] <url>...
              [-c <comment> | --comment <comment>] [--edit] [-e | --encrypt]
              [-f <filename> | --filename <filename>] [--no-request]
              [-q <quote> | --quote <quote>] [--save-source]
              [-r (<url> | <selector>) | --related (<url> | <selector>)]...
              [-t <tag1>,<tag2>... | --tags <tag1>,<tag2>...] [--title <title>]
  ${_ME} bookmark [list [<list-options>...]]
  ${_ME} bookmark (edit | delete | open | peek | url)
              ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
  ${_ME} bookmark search <query>
  ${_ME} browse [<notebook>:][<folder-path>/][<id> | <filename> | <title>] [--daemon]
            [-g | --gui] [-n | --notebooks] [-p | --print] [-q | --query <query>]
            [-s | --serve] [-t <tag> | --tag <tag> | --tags <tag1>,<tag2>...]
  ${_ME} browse add [<notebook>:][<folder-path>/][<filename>]
            [-c <content> | --content <content>] [--tags <tag1>,<tag2>...]
            [-t <title> | --title <title>]
  ${_ME} browse delete ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
  ${_ME} browse edit ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
  ${_ME} completions (check | install [-d | --download] | uninstall)
  ${_ME} copy ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
          [[<notebook>:][<folder-path>/]<filename>]
  ${_ME} count [<notebook>:][<folder-path>/]
  ${_ME} delete ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])...
            [-f | --force]
  ${_ME} do ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
        [<task-number>]
  ${_ME} edit ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
          [-c <content> | --content <content>] [--edit]
          [-e <editor> | --editor <editor>] [-l | --last] [--overwrite]
          [--prepend]
  ${_ME} env [-l | --long]
  ${_ME} env [install | update] [--ace | --mathjax]
  ${_ME} export ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
            <path> [-f | --force] [<pandoc options>...]
  ${_ME} export notebook <name> [<path>]
  ${_ME} export pandoc ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
            [<pandoc options>...]
  ${_ME} folders (add | delete) [<notebook>:][<folder-path>/]<folder-name>
  ${_ME} folders <list-options>...
  ${_ME} git [checkpoint [<message>] | dirty]
  ${_ME} git <git-options>...
  ${_ME} help [<subcommand>] [-p | --print]
  ${_ME} help [-c | --colors] | [-r | --readme] | [-s | --short] [-p | --print]
  ${_ME} history [<notebook>:][<folder-path>/][<id> | <filename> | <title>]
  ${_ME} import [bookmarks | copy | download | move] (<path>... | <url>)
            [--convert] [<notebook>:][<folder-path>/][<filename>]
  ${_ME} import notebook <path> [<name>]
  ${_ME} init [<remote-url> [<branch>]] [--author] [--email <email>]
          [--name <name>]
  ${_ME} list [-e [<length>] | --excerpt [<length>]] [--filenames]
          [-f | --folders-first] [-n <limit> | --limit <limit> | --<limit>]
          [--no-id] [--no-indicator] [-p <number> | --page <number>] [--pager]
          [--paths] [-s | --sort] [-r | --reverse] [--tags]
          [-t <type> | --type <type> | --<type>]
          [<notebook>:][<folder-path>/][<id> | <filename> | <path> | <query>]
  ${_ME} ls [-a | --all] [-b | --browse] [-e [<length>] | --excerpt [<length>]]
        [--filenames] [-f | --folders-first] [-g | --gui]
        [-n <limit> | --limit <limit> | --<limit>] [--no-footer] [--no-header]
        [--no-id] [--no-indicator] [-p <number> | --page <number>] [--pager]
        [--paths] [-s | --sort] [-r | --reverse] [--tags]
        [-t <type> | --type <type> | --<type>]
        [<notebook>:][<folder-path>/][<id> | <filename> | <path> | <query>]
  ${_ME} move ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
          ([<notebook>:][<path>] | --reset | --to-bookmark | --to-note |
          --to-title | --to-todo) [-f | --force]
  ${_ME} notebooks [<name> | <query>] [--ar | --archived] [--global] [--local]
               [--names] [--paths] [--unar | --unarchived]
  ${_ME} notebooks add ([<name>] [<remote-url> [<branch>... | --all]]) [--author]
                   [--email <email>] [--name <name>]
  ${_ME} notebooks (archive | open | peek | status | unarchive) [<name>]
  ${_ME} notebooks author [<name> | <path>] [--email <email>] [--name <name>]
  ${_ME} notebooks current [--path | --selected | --filename [<filename>]]
                       [--global | --local]
  ${_ME} notebooks delete <name> [-f | --force]
  ${_ME} notebooks (export <name> [<path>] | import <path>)
  ${_ME} notebooks init [<path> [<remote-url> [<branch>]]] [--author]
                    [--email <email>] [--name <name>]
  ${_ME} notebooks rename <old-name> <new-name>
  ${_ME} notebooks select <selector>
  ${_ME} notebooks show (<name> | <path> | <selector>) [--ar | --archived]
                    [--escaped | --name | --path | --filename [<filename>]]
  ${_ME} notebooks use <name>
  ${_ME} open ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
  ${_ME} peek ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
  ${_ME} pin  ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
  ${_ME} plugins [<name>] [--paths]
  ${_ME} plugins install [<path> | <url>] [--force]
  ${_ME} plugins uninstall <name> [--force]
  ${_ME} remote [branches [<url>] | remove | rename [<branch-name>] <name>]
  ${_ME} remote [delete <branch-name> | reset <branch-name>]
  ${_ME} remote set <url> [<branch-name>]
  ${_ME} run <command> [<arguments>...]
  ${_ME} search ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
            <query>... [-a | --all] [--and <query>] [--not <query>] [--or <query>]
            [-l | --list] [--path] [-t <tag1>,<tag2>... | --tag <tag1>,<tag2>...]
            [-t | --tags] [--type <type> | --<type>] [--utility <name>]
  ${_ME} set [<name> [<value>] | <number> [<value>]]
  ${_ME} settings [colors [<number> | themes] | edit | list [--long]]
  ${_ME} settings (get | show | unset) (<name> | <number>)
  ${_ME} settings set (<name> | <number>) <value>
  ${_ME} shell [<subcommand> [<options>...] | --clear-history]
  ${_ME} show ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
          [[-a | --added] | [--authors] | [-b | --browse] | --filename | --id |
          --info-line | --path | [-p | --print] | --relative-path | [-r |
          --render] | --title | --type [<type>] | [-u | --updated]] [--no-color]
  ${_ME} show <notebook>
  ${_ME} status [<notebook>]
  ${_ME} subcommands [add <name>...] [alias <name> <alias>]
                 [describe <name> <usage>]
  ${_ME} sync [-a | --all]
  ${_ME} tasks ([<notebook>:][<folder-path>/][<id> | <filename> | <description>])
           [open | closed]
  ${_ME} todo add [<notebook>:][<folder-path>/][<filename>] <title>
              [--description <description>] [--due <date>]
              [-r (<url> | <selector>) | --related (<url> | <selector>)]
              [--tags <tag1>,<tag2>...] [--task <title>...]
  ${_ME} todo do   ([<notebook>:][<folder-path>/][<id> | <filename> | <description>])
               [<task-number>]
  ${_ME} todo undo ([<notebook>:][<folder-path>/][<id> | <filename> | <description>])
               [<task-number>]
  ${_ME} todos [<notebook>:][<folder-path>/] [open | closed] [--pager]
               [--tags <tag1>,<tag2>...]
  ${_ME} todos tasks ([<notebook>:][<folder-path>/][<id> | <filename> | <description>])
                 [open | closed] [--pager]
  ${_ME} unarchive [<notebook>]
  ${_ME} undo ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
          [<task-number>]
  ${_ME} unpin ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
  ${_ME} unset (<name> | <number>)
  ${_ME} update
  ${_ME} use <notebook>
  ${_ME} -h | --help | help [<subcommand> | --readme]
  ${_ME} -i | --interactive [<subcommand> [<options>...]]
  ${_ME} --no-color
  ${_ME} --version | version
HEREDOC

      if ! ((_short))
      then
        cat <<HEREDOC

$(_color_primary "Subcommands"):
  (default)    List notes and notebooks. This is an alias for \`${_ME} ls\`.
               When a <url> is provided, create a new bookmark.
  add          Add a note, folder, or file.
  archive      Archive the current or specified notebook.
  bookmark     Add, open, list, and search bookmarks.
  browse       Browse and manage linked items in terminal and GUI browsers.
  completions  Install and uninstall completion scripts.
  copy         Copy or duplicate an item.
  count        Print the number of items in a notebook or folder.
  delete       Delete a note.
  do           Mark a todo or task as done.
  edit         Edit a note.
  env          Print environment information and install dependencies.
  export       Export a note to a variety of different formats.
  folders      Add, delete, and list folders.
  git          Run \`git\` commands within the current notebook.
  help         View help information for the program or a subcommand.
  history      View git history for the current notebook or a note.
  import       Import a file into the current notebook.
  init         Initialize the first notebook.
  list         List notes in the current notebook.
  ls           List notebooks and notes in the current notebook.
  move         Move or rename a note.
  notebooks    Manage notebooks.
  open         Open a bookmarked web page or notebook folder, or edit a note.
  peek         View a note, bookmarked web page, or notebook in the terminal.
  pin          Pin an item so it appears first in lists.
  plugins      Install and uninstall plugins and themes.
  remote       Configure the remote URL and branch for the notebook.
  run          Run shell commands within the current notebook.
  search       Search notes.
  settings     Edit configuration settings.
  shell        Start the \`${_ME}\` interactive shell.
  show         Show a note or notebook.
  status       Print notebook status information.
  subcommands  List, add, alias, and describe subcommands.
  sync         Sync local notebook with the remote repository.
  tasks        List tasks in todos, notebooks, folders, and other items.
  todo         Manage todos and tasks.
  unarchive    Unarchive the current or specified notebook.
  undo         Mark a todo or task as not done.
  unset        Return a setting to its default value.
  unpin        Unpin a pinned item.
  update       Update \`${_ME}\` to the latest version.
  use          Switch to a notebook.
  version      Display version information.

$(_color_primary "Notebook Usage"):
  ${_ME} <notebook>:[<subcommand>] [<identifier>] [<options>...]
  ${_ME} <subcommand> <notebook>:<identifier> [<options>...]

$(_color_primary "Program Options"):
  -h, --help          Display this help information.
  -i, --interactive   Start the \`${_ME}\` interactive shell.
  --no-color          Print without color highlighting.
  --version           Display version information.

$(_color_primary "More Information"):
  https://github.com/${_REPO}

$(_color_primary "Sponsor & Donate"):
  https://github.com/sponsors/xwmx
  https://paypal.me/WilliamMelody

$(_color_primary "Created By"):
  William Melody
  https://github.com/xwmx
  https://www.williammelody.com

$(_color_primary "Contributors"):
  https://github.com/xwmx/nb/graphs/contributors

HEREDOC
      fi
    else
      printf "%s\\n" "$(describe --get "${_arguments[@]}")"
    fi | {
      if ((_shell))
      then
        LC_ALL=C sed -e "s/^  ${_ME} /  /" -e "/^  ${_ME}$/d"
      else
        cat
      fi
    } | {
      if ((_color_help))
      then
        cat
      else
        local _replacement_pattern="${_TPUT_SGR0}${_TPUT_SETAF_8}\1${_TPUT_SGR0}"

        LC_ALL=C sed -E                                                               \
-e "/^\ \ |\[\[wiki\-style\ linking\]\]/s/(\[|\]|\(|\)|\|)/${_replacement_pattern}/g" \
-e "s/#tag/${_TPUT_SGR0}${_TPUT_SETAF_8}#${_TPUT_SGR0}tag/g"                          \
-e "s/(currently\ set\ to: )(.*)/\1${_TPUT_SGR0}${_TPUT_COLOR_PRIMARY}\2${_TPUT_SGR0}/g"
      fi
    } | {
      LC_ALL=C sed -e "s/\`/${_TPUT_SGR0}${_TPUT_SETAF_8}\`${_TPUT_SGR0}/g"
    } | {
      if ((_use_pager))
      then
        _pager
      else
        cat
      fi
    }
  fi
}
_alias_subcommand "help" "h"

# index · ############################################################# · index

_describe_index() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} index add <filename>
  ${_ME} index delete <filename>
  ${_ME} index edit
  ${_ME} index get_basename <id>
  ${_ME} index get_id <filename>
  ${_ME} index get_max_id
  ${_ME} index rebuild [--ancestors]
  ${_ME} index reconcile [--ancestors] [--commit]
  ${_ME} index show
  ${_ME} index update <existing-filename> <new-filename>
  ${_ME} index verify
  ${_ME} index <subcommand> <options>... [<folder-path>]

$(_color_primary "Options"):
  --ancestors   Perform the action on all folders within the notebook that
                are ancestors of the current folder.
  --commit      Commit changes to git.

$(_color_primary "Subcommands"):
  add           Add <filename> to the index.
  delete        Delete <filename> from the index.
  edit          Open the index file in \`\$EDITOR\`.
  get_basename  Print the filename / basename at the specified <id>.
  get_id        Get the id for <filename>.
  get_max_id    Get the maximum id for the folder.
  rebuild       Rebuild the index, listing files by last modified, reversed.
                Some ids will change. Prefer \`${_ME} index reconcile\`.
  reconcile     Remove duplicates and update index for added and deleted files.
  show          Print the index.
  update        Overwrite the <existing-filename> entry with <new-filename>.
  verify        Verify that the index matches the folder contents.

$(_color_primary "Description"):
  Manage the index for the current folder or the folder at <folder-path>,
  which can be passed as the final argument to any \`index\` subcommand.

  \`index\` is used internally by \`${_ME}\` and using it manually will
  probably corrupt the index. If something goes wrong with an index,
  fix it with \`${_ME} index reconcile\`.

  An index is a text file named '.index' in any folder within a notebook.
  .index contains a list of filenames and the line number of each filename
  represents the id. .index files are included in the git repository so
  ids are preserved across systems.
HEREDOC
}
_index() {
  local _ancestors=0
  local _commit_changes=0
  local _folder_path=
  local _subcommand="${1:-}"

  case "${_subcommand:-}" in
    edit|get_max_id|show|verify)
      _folder_path="${2:-}"
      ;;
    rebuild|reconcile)
      shift

      local __arg=
      for   __arg in "${@:-}"
      do
        case "${__arg:-}" in
          --ancestors)
            _ancestors=1
            ;;
          --commit|--checkpoint)
            _commit_changes=1
            ;;
          *)
            _folder_path="${__arg:-}"
            ;;
        esac
      done
      ;;
    add|delete|get_basename|get_id)
      _folder_path="${3:-}"
      ;;
    update)
      _folder_path="${4:-}"
      ;;
    *)
      [[ -d "${1:-}" ]] && _folder_path="${1:-}"
      ;;
  esac

  _folder_path="${_folder_path:-"${NB_NOTEBOOK_PATH}"}"

  local _index_path="${_folder_path}/.index"
  local _notebook_path="${NB_NOTEBOOK_PATH}"

  if [[ ! "${_folder_path:-}" =~ ^${NB_NOTEBOOK_PATH} ]]
  then
    local _notebook_and_relative_path="${_folder_path#"${NB_DIR}"/}"
    _notebook_path="${NB_DIR}/${_notebook_and_relative_path%%/*}"
  fi

  if [[ ! -e "${_index_path}" ]]
  then
    case "${_subcommand}" in
      add)
        _index reconcile "${_folder_path}" --ancestors
        ;;
      edit|rebuild|reconcile)
        :
        ;;
      *)
        _index reconcile "${_folder_path}" --ancestors --commit
        ;;
    esac
  fi

  case "${_subcommand}" in
    add)
      local _basename="${2:-}"

      if [[ -z "${_basename}" ]]
      then
        _exit_1 _help index
      fi

      if [[ ! -e "${_folder_path}/${_basename}" ]]
      then
        _exit_1 printf "File not found: %s\\n" "${_folder_path}/${_basename}"
      fi

      if ! grep -q "^${_basename}$" "${_index_path}"
      then
        {
          printf "%s\\n" "${_basename}" | LC_ALL=C sed -E "${_IGNORE_PATTERNS[@]:-}"
        } >> "${_index_path}"
      fi
      ;;
    delete)
      local _basename="${2:-}"

      if [[ -z "${_basename}" ]]
      then
        _exit_1 _help index
      fi

      _basename="${_basename//'['/\\[}"
      _basename="${_basename//']'/\\]}"

      if grep -q "^${_basename}$" "${_index_path}"
      then
        _sed_i -e "s/^${_basename}$//g" "${_index_path}"
      else
        return 1
      fi
      ;;
    edit)
      _edit_file "${_index_path}" --no-wait

      return 0
      ;;
    get_basename)
      # Usage: _index_get_basename <id> <index-path>
      _index_get_basename() {
        if [[ -z "${1:-}" ]] || [[ "${1:-}" == "0" ]]
        then
          return 1
        fi

        LC_ALL=C sed "${1:-}q;d" "${2:-}"
      }

      local _id_number="${2:-}"
      if [[ -z "${_id_number}"  ]]
      then
        _exit_1 _help index
      fi

      local _basename=
      _basename="$(_index_get_basename "${_id_number}" "${_index_path}")"

      if [[ -z "${_basename}"   ]]
      then
        _index reconcile &&
          _basename="$(_index_get_basename "${_id_number}" "${_index_path}")"
      fi

      if [[ -z "${_basename}"   ]]
      then
        return 1
      else
        printf "%s\\n" "${_basename}"
      fi
      ;;
    get_id)
      # Usage: _index_get_id <basename> <index-path>
      _index_get_id() {
        # Alternatives:
        # awk 'match($0,v){print NR; exit}' v="^${1:-}$" "${2:-}"
        # git -C "${3:?}" grep  \
        #   --line-number       \
        #   --no-color          \
        #   -e "^${1:?}$"       \
        #   "${2:?}"            \
        #   | cut -d: -f2
        # grep -n "^${1:-}$" "${2:-}"                         | cut -d: -f1
        # rg --color=never --line-number "^${1:-}$" "${2:-}"  | cut -d: -f1

        local _basename="${1:-}"
        _basename="${_basename//\[/\\\[}"
        _basename="${_basename//\]/\\\]}"

        LC_ALL=C sed -n "/^${_basename:-}$/=" "${2:-}"
      }

      local _basename="${2:-}"

      if [[ -z "${_basename}" ]]
      then
        _help index

        return 1
      fi

      local _id=
      _id="$(_index_get_id "${_basename}" "${_index_path}")"

      if [[ -z "${_id}" ]]
      then
        _index reconcile &&
          _id="$(_index_get_id "${_basename}" "${_index_path}")"
      fi

      if [[ -z "${_id}" ]]
      then
        return 1
      else
        printf "%s\\n" "${_id}"
      fi

      # Alternative
      # -----------

      # local _basename="${2:-}"
      # local _id=

      # if [[ -z "${_basename}" ]]
      # then
      #   _help index
      #
      #   return 1
      # fi

      # _index_get_id "${_basename:-}" "${_index_path:-}" | {
      #   read -r _id

      #   if [[ -n "${_id:-}"   ]]
      #   then
      #     printf "%s\\n" "${_id:-}"
      #   else
      #     _index reconcile &&
      #       _index_get_id "${_basename:-}" "${_index_path:-}" | {
      #           read -r _id

      #           if [[ -n "${_id:-}" ]]
      #           then
      #             printf "%s\\n" "${_id:-}"
      #           else
      #             return 1
      #           fi
      #         }
      #   fi
      # }
      ;;
    get_max_id)
      wc -l < "${_index_path}" | tr -d '[:space:]'

      printf "\\n"
      ;;
    rebuild)
      local _top_path="${_folder_path:?}"

      if ((_ancestors))
      then
        _top_path="${_notebook_path:?}"
      fi

      local _rebuild_type="Rebuild"

      if [[ ! -e "${_folder_path:?}/.index" ]]
      then
        _rebuild_type="Initialize"
      fi

      local _current_folder_path="${_folder_path:?}"

      while [[ "${_current_folder_path:?}" =~ ${_top_path:?} ]]
      do
        {
          ls -t -r "${_current_folder_path:?}"
        } | {
          LC_ALL=C sed -E "${_IGNORE_PATTERNS[@]:-}"
        } > "${_current_folder_path:?}/.index"

        _current_folder_path="${_current_folder_path%/*}"
      done  &&
        _git checkpoint "${_notebook_path}" "[${_ME}] ${_rebuild_type:-Rebuild} Index"

      return 0
      ;;
    reconcile)
      # Usage: _index_reconcile_remove_duplicates <index-path>
      _index_reconcile_remove_duplicates() {
        local _reconcile_index_path="${1:-}"
        [[ -z "${_reconcile_index_path:-}" ]] && return 1

        local _temp_file=
        _temp_file="$(_temp file)"

        exec 3> "${_temp_file}"
        exec 4< "${_temp_file}"

        rm "${_temp_file:?}"

        # Remove duplicates and preserve newlines.
        awk '!NF || !seen[$0]++' "${_reconcile_index_path}" >&3
        cat <&4 > "${_reconcile_index_path}"

        exec 3>&-
        exec 4<&-
      }

      local _top_path="${_folder_path:?}"

      [[ -d "${_top_path}" ]] || return 0

      if ((_ancestors))
      then
        _top_path="${_notebook_path:?}"
      fi

      local _current_folder_path="${_folder_path:?}"

      while [[ "${_current_folder_path:?}" =~ ^${_top_path} ]]
      do
        if [[ ! -e "${_current_folder_path:?}/.index"       ]]
        then
          {
            ls -t -r "${_current_folder_path:?}"
          } | {
            LC_ALL=C sed -E "${_IGNORE_PATTERNS[@]:-}"
          } > "${_current_folder_path:?}/.index"
        fi

        local -a _index_list=()
        _index_list=($(<"${_current_folder_path:?}/.index"))

        local -a _file_list=()
        _file_list=($(
          {
            ls -t -r "${_current_folder_path:?}"
          } | {
            LC_ALL=C sed -E "${_IGNORE_PATTERNS[@]:-}"
          }
        ))

        _index_reconcile_remove_duplicates "${_current_folder_path:?}/.index"

        local -a _index_file_list_diff=()
        _index_file_list_diff=($(
          printf "%s\\n"          \
            "${_index_list[@]:-}" \
            "${_file_list[@]:-}"  \
            | sort                \
            | uniq -u
        ))

        local -a _diff_in_index=()
        _diff_in_index=($(
          printf "%s\\n"                    \
            "${_index_list[@]:-}"           \
            "${_index_file_list_diff[@]:-}" \
            | sort                          \
            | uniq -d                       \
            | uniq
        ))

        local __item=
        for   __item in "${_diff_in_index[@]:-}"
        do
          if [[ -n "${__item}" ]]
          then
            _contains "${__item}" "${_file_list[@]:-}" ||
              _index delete "${__item}" "${_current_folder_path:?}"
          fi
        done

        local -a _diff_in_file_list=()
        _diff_in_file_list=($(
          printf "%s\\n"                    \
            "${_file_list[@]:-}"            \
            "${_index_file_list_diff[@]:-}" \
            | sort                          \
            | uniq -d                       \
            | uniq
        ))

        local __item=
        for   __item in "${_diff_in_file_list[@]:-}"
        do
          if [[ -n "${__item}" ]]
          then
            _contains "${__item}" "${_index_list[@]:-}" ||
              _index add "${__item}" "${_current_folder_path:?}"
          fi
        done

        _current_folder_path="${_current_folder_path%/*}"
      done

      if ((_commit_changes))
      then
        _git checkpoint "${_notebook_path}" "[${_ME}] Reconcile Index"
      fi
      ;;
    show)
      cat "${_index_path}"
      ;;
    update)
      local _new_basename="${3:-}"
      local _old_basename="${2:-}"

      if [[ -z "${_old_basename}" ]] || [[ -z "${_new_basename}" ]]
      then
        _exit_1 _help index
      fi

      _old_basename="${_old_basename//'['/\\[}"
      _old_basename="${_old_basename//']'/\\]}"

      if grep -q "^${_old_basename}$" "${_index_path}"
      then
        _sed_i -e "s/^${_old_basename}$/${_new_basename}/g" "${_index_path}"
      else
        return 1
      fi
      ;;
    verify)
      local _valid=1

      local -a _index_list=()
      _index_list=($(<"${_index_path}"))

      local -a _file_list=()
      _file_list=($(
        {
          ls -t -r "${_folder_path}"
        } | {
          LC_ALL=C sed -E "${_IGNORE_PATTERNS[@]:-}"
        }
      ))

      local -a _index_file_list_diff=()
      _index_file_list_diff=($(
        printf "%s\\n"          \
          "${_index_list[@]:-}" \
          "${_file_list[@]:-}"  \
          | sort                \
          | uniq -u
      ))

      if [[ -n "${_index_file_list_diff[*]:-}" ]]
      then
        _valid=0
      fi

      local __item=
      for   __item in $(printf "%s\\n" "${_index_list[@]:-}" | uniq -c)
      do
        local _count=
        _count="$(printf "%s\\n" "${__item}" | awk '{print $1}')"

        if [[ "${_count}" -gt 1 ]]
        then
          _valid=0

          break
        fi
      done

      if ! ((_valid))
      then
        _warn                                                               \
          printf "Index corrupted. To fix, run:\\n  %s index reconcile\\n"  \
          "${_ME}"

        return 1
      else
        return 0
      fi
      ;;
    *)
      :
      ;;
  esac
}

# init · ############################################################### · init

_describe_init() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} init [<remote-url> [<branch>]] [--author] [--email <email>]
          [--name <name>]

$(_color_primary "Options"):
  --author         Display the local email and name config prompt.
  --email <email>  Set the local commit author email address to <email>.
  --name  <name>   Set the local commit author name to <name>.

$(_color_primary "Description"):
  Initialize the initial "home" notebook and generate a configuration file at:

      ${NBRC_PATH}

  Pass optional <remote-url> and <branch> arguments to create the initial
  "home" notebook using a clone of an existing notebook.

$(_color_primary "See Also"):
  ${_ME} help notebooks

$(_color_primary "Examples"):
  ${_ME} init
  ${_ME} init https://github.com/example/example.git
  ${_ME} init https://github.com/example/example.git example-branch
HEREDOC
}
_init() {
  # Usage: _init_create_home_notebook [<url> [<branch>]] [--author]
  #                                   [--email <email>] [--name <name>]
  _init_create_home_notebook() {
    local _author=0
    local _author_arguments=()
    local _remote_branch=
    local _remote_url=

    while ((${#}))
    do
      case "${1:-}" in
        --author) _author=1 ;;
        --email|--name)
          _author=1
          _author_arguments+=("${1:-}")

          if _option_value_is_present "${2:-}"
          then
            _author_arguments+=("${2:-}")

            shift
          fi
          ;;
        *)
          if   [[ -z "${_remote_url:-}"     ]] &&
               _string_is_url "${1:-}"
          then
            _remote_url="${1:-}"
          elif [[ -z "${_remote_branch:-}"  ]]
          then
            _remote_branch="${1:-}"
          fi
          ;;
      esac

      shift
    done

    ((_author)) && _author_arguments+=("${NB_DIR}/home")

    if   [[ -n "${_remote_url:-}"     ]]
    then
      if [[ -n "${_remote_branch:-}"  ]]
      then
        git clone --no-local --single-branch --branch "${_remote_branch:-}" \
          "${_remote_url}"                                                  \
          "${NB_DIR}/home"
      else
        git clone --no-local --single-branch "${_remote_url}" "${NB_DIR}/home"
      fi && if ((_author))
            then
              _notebooks author "${_author_arguments[@]:-}"
            fi
    else
      {
        mkdir -p  "${NB_DIR}/home"
      } && {
        if ((_GIT_ENABLED))
        then
          git -C  "${NB_DIR}/home" init   &>/dev/null
        fi
      } && {
        if ((_author))
        then
          _notebooks author "${_author_arguments[@]:-}"
        fi
      } && {
        touch  "${NB_DIR}/home/.index"
      } && {
        _git checkpoint "${NB_DIR}/home" "[${_ME}] Initialize"
      }
    fi

    _notebooks use "home" 1>/dev/null

    # printf "Created notebook:           %s\\n" "$(_color_primary "home")"
  }

  # Usage: _init_create_nb_dir
  _init_create_nb_dir() {
    if    [[ -d "${NB_DIR}" ]]
    then
      printf "Data directory exists:      %s\\n" "$(_color_primary "${NB_DIR}")"
    elif  [[ -e "${NB_DIR}" ]]
    then
      _exit_1 cat <<HEREDOC
Unable to set up the $(_color_primary "${_ME}") data directory. File exists at:
${NB_DIR}
HEREDOC
    else
      mkdir -p "${NB_DIR}"
      printf "Created data directory:     %s\\n" "$(_color_primary "${NB_DIR}")"
    fi
  }

  # Usage: _init_create_rc_file
  _init_create_rc_file() {
    if [[ -e "${NBRC_PATH}" ]]
    then
      printf "Configuration file exists:  %s\\n" \
        "$(_color_primary "${NBRC_PATH}")"
    else
      cat <<HEREDOC > "${NBRC_PATH}"
#!/usr/bin/env bash
###############################################################################
# .${_ME}rc
#
# Configuration file for \`${_ME}\`, a command line note-taking, bookmarking,
# and knowledge base application with encryption, search, Git-backed syncing,
# and more in a single portable script.
#
# Edit this file manually or manage settings using the \`${_ME} settings\`
# subcommand. Configuration options are set as environment variables, eg:
#   export NB_ENCRYPTION_TOOL=gpg
#
# https://github.com/${_REPO}
###############################################################################
HEREDOC
      printf "Created configuration file: %s\\n" "$(_color_primary "${NBRC_PATH}")"
    fi
  }

  # Usage: _init_print_header
  _init_print_header() {
    printf "%s%s\\n" "$(_color_primary "Initializing")" "$(_color_muted "...")"
  }

  if [[ -e "${NB_DIR}" ]] && [[ ! -d "${NB_DIR}" ]]
  then
    _exit_1 printf "NB_DIR exists and is not a directory: %s\\n" \
      "$(_color_primary "${NB_DIR}")"
  fi

  if [[ -d "${_GLOBAL_NOTEBOOK_PATH}" ]]
  then
    _exit_1 cat <<HEREDOC
$(_color_primary "${_ME}") already initialized. To initialize a local notebook, use:
  $(_color_primary "${_ME} notebooks init")
More Information:
  $(_color_primary "${_ME} help notebooks")
HEREDOC
  fi

  _print_welcome                            &&
    _init_print_header          1>/dev/null &&
    _init_create_nb_dir         1>/dev/null &&
    _init_create_rc_file        1>/dev/null &&
    _validate_configuration     "${@:-}"    &&
    _init_create_home_notebook  "${@:-}"
}

# list · ############################################################### · list

_describe_list() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} list [-e [<length>] | --excerpt [<length>]] [--filenames]
          [-f | --folders-first] [-n <limit> | --limit <limit> | --<limit>]
          [--no-id] [--no-indicator] [-p <number> | --page <number>] [--pager]
          [--paths] [-s | --sort] [-r | --reverse] [--tags]
          [-t <type> | --type <type> | --<type>]
          [<notebook>:][<folder-path>/][<id> | <filename> | <path> | <query>]

$(_color_primary "Options"):
  -e, --excerpt [<length>]        Print an excerpt <length> lines long under
                                  each note's filename [default: 3].
  --filenames                     Print the filename for each note.
  -f, --folders-first             Print folders before other items.
  -n, --limit <limit>, --<limit>  The maximum number of notes to list.
  --no-id                         Don't include the id in list items.
  --no-indicator                  Don't include the indicator in list items.
  -p, --page <number>             The page to view in the list paginated by
                                  a <limit> option or \`${_ME} set limit\`.
  --pager                         Display output in the pager.
  --paths                         Print the full path to each item.
  -s, --sort                      Order notes by id.
  -r, --reverse                   List items in reverse order.
  --tags                          List tags in the notebook or folder.
  -t, --type <type>, --<type>     List items of <type>. <type> can be a file
                                  extension or one of the following types:
                                  archive, audio, book, bookmark, document,
                                  folder, image, note, text, video

$(_color_primary "Description"):
  List notes in the current notebook.

  When <id>, <filename>, <path>, or <title> are present, the listing for the
  matching note is displayed. When no match is found, titles and filenames
  are searched for any that match <query> as a case-insensitive regular
  expression.

$(_color_primary "Read More"):
  ${_README_URL}#listing--filtering

$(_color_primary "Indicators"):
  ${_NB_INDICATOR_AUDIO:-} Audio
  ${_NB_INDICATOR_EBOOK:-} Book
  ${_NB_INDICATOR_BOOKMARK:-} Bookmark
  ${_NB_INDICATOR_ENCRYPTED:-} Encrypted
  ${_NB_INDICATOR_FOLDER:-} Folder
  ${_NB_INDICATOR_IMAGE:-} Image
  ${_NB_INDICATOR_DOCUMENT:-} PDF, Word, or Open Office document
  ${_NB_INDICATOR_VIDEO:-} Video

$(_color_primary "See Also"):
  ${_ME} help browse
  ${_ME} help ls
  ${_ME} help pin
  ${_ME} help search
  ${_ME} help unpin

$(_color_primary "Examples"):
  ${_ME} list
  ${_ME} list example.md -e 10
  ${_ME} list --excerpt --no-id
  ${_ME} list --filenames --reverse
  ${_ME} list "^Example.*"
  ${_ME} list --10
  ${_ME} list --type document
  ${_ME} example:list
HEREDOC
}
_list() {
  local _error_on_empty=0
  local _excerpt_length=3
  local _folders_first=0
  local _force_line_wrap=0
  local _limit=
  local _line_wrap=1
  local _list_filenames=0
  local _list_paths=0
  local _no_id=0
  local _only_pinned=0
  local _page=1
  local _paginate=0
  local _print_excerpt=0
  local _print_indicators=1
  local _print_notebook_selectors=0
  local _recursive=0
  local _recursive_arguments=()
  local _reverse=0
  local _selector_arguments=()
  local _sort=0
  local _type=
  local _use_pager=0
  local _with_pinned=0

  while ((${#}))
  do
    case "${1:-}" in
      -a|--all)
        _limit=
        ;;
      -e|--excerpt)
        _print_excerpt=1
        _recursive_arguments+=("--excerpt")

        if _option_value_is_present "${2:-}"
        then
          _excerpt_length="${2:-}"
          _recursive_arguments+=("${2:-}")

          shift
        fi
        ;;
      --*empty)
        _error_on_empty=1
        _recursive_arguments+=("--error-on-empty")
        ;;
      --filename*)
        _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
          _limit="${2:-}"

          shift
        fi
        ;;
      --no*color)
        _COLOR_ENABLED=0
        ;;
      --no*folders*first|--no*ff|-no*ff|--no*f|-no*f)
        _folders_first=0
        ;;
      --no-id*|--noid*|--no*index)
        _no_id=1
        _recursive_arguments+=("--no-id")
        ;;
      --no*indicator*|--no*icon*|--no*emoji*|--no*unicode*)
        _print_indicators=0
        _recursive_arguments+=("--no-indicators")
        ;;
      --no*wrap|--truncate)
        _line_wrap=0
        _recursive_arguments+=("--no-wrap")
        ;;
      --notebook-selectors)
        _print_notebook_selectors=1
        ;;
      -p|--page)
        _page="$(_option_get_value "${1}" "${2:-}")"
        ((_page))               || _page=1
        [[ -z "${_limit:-}" ]]  && _limit="${NB_LIMIT}"
        _paginate=1

        shift
        ;;
      --pager|--less)
        _use_pager=1
        ;;
      --path*)
        _list_paths=1
        _recursive_arguments+=("--paths")
        ;;
      --pinned)
        _only_pinned=1
        _with_pinned=1
        _recursive_arguments+=("--pinned")
        ;;
      --recursive|--tree)
        _recursive=1
        ;;
      -r|--reverse)
        _reverse=1
        ;;
      -s|--sort)
        _sort=1
        ;;
      --tags|--hashtags)
        _search "${_selector_arguments[@]:-}" "${@:-}"

        return 0
        ;;
      --titles)
        : # Do nothing. This is the default behavior.
        ;;
      -t|--type)
        _type="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      --with*pinned)
        _with_pinned=1
        ;;
      --wrap)
        _force_line_wrap=1
        _recursive_arguments+=("--wrap")
        ;;
      *)
        if   [[   "${1:-}" =~ ^-+[0-9]+$  ]]
        then
          _limit="${1##*-}"
        elif [[   "${1:-}" =~ ^--         ]]
        then
          if ! _contains "${1:-}" "--ar" "--archived" "--unar" "--unarchived"
          then
            _type="${1:2}"
          fi
        else
          _selector_arguments+=("${1:-}")
        fi
        ;;
    esac

    shift
  done

  local _notebook_path=
  _notebook_path="$(_notebooks current --path)"

  local _filter_patterns=()
  local _folder_relative_path=
  local _selector=
  local _selector_basename=

  local __argument=
  for   __argument in "${_selector_arguments[@]:-}"
  do
    if [[   -z "${__argument:-}"  ]]
    then
      continue
    elif [[ -n "${_selector:-}"   ]]
    then # selector has already been set
      _filter_patterns+=("${__argument}")
    elif [[ "${__argument}" =~ :$ ]]
    then # argument appears to be a <notebook>: selector
      local _selector_notebook_path=
      _selector_notebook_path="$(_notebooks show "${__argument}" --path)"

      if [[ -n "${_selector_notebook_path:-}" ]]
      then
        _notebooks select "${_selector_notebook_path}"
        _notebook_path="${_selector_notebook_path}"

        _selector="${__argument}"
      else
        _filter_patterns+=("${__argument}")
      fi
    else
      local _selector_relative_path=
      _selector_relative_path="$(
        # resolve selector relative path without a trailing /
        _selector_resolve_path "${__argument%\/}" --relative
      )"

      if [[ "${__argument:-}" =~ ^/ ]]
      then # selector is a full path
        _selector="${__argument}"

        local _selector_notebook_path=
        _selector_notebook_path="$(
          _notebooks show "${__argument}" --path 2>/dev/null || :
        )"

        if [[ -n  "${_selector_notebook_path:-}"                        ]] &&
           [[ -d  "${_selector_notebook_path:-}"                        ]] &&
           [[     "${_selector_notebook_path:-}" != "${_notebook_path}" ]]
        then
          _notebooks select "${_selector_notebook_path}"
          _notebook_path="${_selector_notebook_path}"
        fi

        if [[ "${__argument}" =~ /$ ]] && [[ -d "${__argument}"   ]]
        then
          _selector_relative_path="${_selector_relative_path}/"
          _folder_relative_path="${_selector_relative_path%\/*}"
          _selector_basename="${_selector_relative_path##*\/}"
        elif [[     "${_selector_relative_path}" =~ /             ]]
        then
          _folder_relative_path="${_selector_relative_path%\/*}"
          _selector_basename="${_selector_relative_path##*\/}"
        elif [[ -n  "${_selector_relative_path:-}"                ]]
        then
          _folder_relative_path=
          _selector_basename="${_selector_relative_path}"
        elif [[ "${__argument:-}" != "${_notebook_path:-}"        ]]
        then
          _filter_patterns+=("${__argument}")
        fi
      elif [[ "${__argument:-}" =~ /$                             ]]
      then
        if [[ -n "${_selector_relative_path:-}"                   ]]
        then
          if [[ -d "${_notebook_path}/${_selector_relative_path}" ]]
          then # argument is a folder selector with trailing /
            _folder_relative_path="${_selector_relative_path}"
            _selector="${__argument}"
            _selector_basename=
          else # argument is a file selector
            if [[ "${_selector_relative_path:-}" =~ /             ]]
            then # argument is a nested file selector
              _folder_relative_path="${_selector_relative_path%\/*}"
            else # argument does not include a folder
              _folder_relative_path=
            fi

            _selector="${__argument%\/}"
            _selector_basename="${_selector_relative_path##*\/}"
          fi
        else # argument has a trailing slash and does not match an existing path
          _filter_patterns+=("${__argument}")
        fi
      elif [[ "${__argument:-}" =~ /            ]]
      then
        if [[ -n "${_selector_relative_path:-}" ]]
        then # argument is a nested file or folder path
          _folder_relative_path="${_selector_relative_path%\/*}"
          _selector="${__argument}"
          _selector_basename="${_selector_relative_path##*\/}"
        else
          # resolve selector relative path without final path segment
          _selector_relative_path="$(
            _selector_resolve_path "${__argument%\/*}" --relative
          )"

          if [[ -n "${_selector_relative_path:-}"                   ]] &&
             [[ -d "${_notebook_path}/${_selector_relative_path:-}" ]]
          then # folder path is selector, final path segment is filter pattern
            _folder_relative_path="${_selector_relative_path}"
            _selector="${__argument%\/*}"
            _selector_basename=
            _selector_relative_path="${_folder_relative_path:-}"

            _filter_patterns+=("${__argument##*\/}")
          else # argument does not resolve, treat as filter pattern
            _filter_patterns+=("${__argument}")
          fi
        fi
      else
        if [[ -n "${_selector_relative_path:-}" ]]
        then # argument is a root-level file or folder identifier
          _folder_relative_path=
          _selector="${__argument}"
          _selector_basename="${_selector_relative_path##*\/}"
        else
          if [[ "${__argument:-}" =~ :          ]]
          then # argument appears to include notebook selector
            local _selector_notebook_path=
            _selector_notebook_path="$(
              _notebooks show "${__argument%%:*}" --path || :
            )"

            if [[ -n "${_selector_notebook_path:-}"                   ]] &&
               [[ "${_selector_notebook_path}" == "${_notebook_path}" ]]
            then # argument notebook selector matches the current notebook
              _selector="${__argument%%:*}"
              _filter_patterns+=("${__argument#*:}")
            else
              _filter_patterns+=("${__argument}")
            fi
          else
            _filter_patterns+=("${__argument}")
          fi
        fi
      fi
    fi
  done

  local _filter_pattern=
  _filter_pattern="$(_join "|" "${_filter_patterns[@]:-}")"

  if [[ "${_selector:-}" =~ ^[^\/]+/ ]] && [[ -z "${_folder_relative_path:-}" ]]
  then
    _warn printf "Not found: %s\\n" "$(_color_primary "${_selector}")"

    return 1
  fi

  local _list_files_options=()

  [[ -n "${_type:-}" ]] && _list_files_options+=("--type" "${_type}")
  ((_reverse))          && _list_files_options+=("--reverse")
  ((_sort))             && _list_files_options+=("--sort")

  local _list_path="${_notebook_path}"

  # context variables

  local _maybe_id_path_context=
  local _maybe_selector_context=

  if [[ -n "${_folder_relative_path:-}"                 ]] &&
     [[ -e "${_notebook_path}/${_folder_relative_path}" ]]
  then
    _list_path="${_notebook_path}/${_folder_relative_path}"

    _maybe_id_path_context="$(
      _get_id_selector "${_folder_relative_path:-}/"
    )"

    _maybe_selector_context="${_folder_relative_path:-}/"
  fi

  if [[ ! -e "${_list_path}" ]]
  then
    _exit_1 printf "Not found: %s\\n" "$(
      _color_primary "${_folder_relative_path:-"${_selector:-}"}"
    )"
  fi

  if _notebooks current --selected || ((_print_notebook_selectors))
  then
    local _selected_notebook_name=
    _selected_notebook_name="$(
      _notebooks show "${_notebook_path}" --name --no-color
    )"

    _maybe_id_path_context="${_selected_notebook_name}:${_maybe_id_path_context:-}"

    _maybe_selector_context="${_selected_notebook_name}:${_maybe_selector_context}"
  fi

  # recursive

  # TODO: support --limit and any other loop-dependent features

  _recursive_arguments+=("${_list_files_options[@]:-}")

  if ((_recursive))
  then
    {
      find "${_list_path}" -type d -not -path '*/\.*' | sort
    } | {
      local         __folder_path=
      while read -r __folder_path
      do
        [[ -z "${__folder_path:-}"                    ]] && continue
        [[    "${__folder_path:-}" == "${_list_path}" ]] && continue

        _list "${__folder_path}/"         \
          "${_recursive_arguments[@]:-}"  \
          --error-on-empty 2>/dev/null    || :
      done
    }
  fi

  # pinning

  local _pinned_basenames=()

  if ((_with_pinned))
  then
    if [[ -f "${_list_path}/.pindex"  ]]
    then
      _pinned_basenames=($(cat "${_list_path}/.pindex"))
    fi

    # Search-Based Pinning
    #
    # Display pinned items first in the list by matching against a pattern
    # like "#pinned". To enable, assign a tag or other pattern to the
    # $NB_PINNED_PATTERN environment variable.
    #
    # Example:
    #   # file: ~/.nbrc
    #   export NB_PINNED_PATTERN="#pinned"
    if [[ -n "${NB_PINNED_PATTERN:-}" ]]
    then
      _pinned_basenames=($(
        {
          printf "%s\\n" "${_pinned_basenames[@]:-}"
          GIT_PAGER='' git -C "${_list_path}"     \
            grep                                  \
            --color=never                         \
            --extended-regexp                     \
            --files-with-matches                  \
            --ignore-case                         \
            --max-depth 0                         \
            --text                                \
            -e "${NB_PINNED_PATTERN:-"#pinned"}"  \
            "${_list_path}" 2>/dev/null || :
        } | awk '!NF || !seen[$0]++'
      ))
    fi
  fi

  # TODO: External local variables used in pipeline.
  #
  # Not affected by list path:
  #
  # ${_excerpt_length}
  # ${_limit}
  # ${_list_files_options[@]}
  # ${_with_pinned}
  #
  # Affected by list path / selector (Display):
  #
  # ${_maybe_selector_context}
  #
  # Affected by list path / selector (Logic):
  #
  # ${_filter_pattern}
  # ${_folder_relative_path}
  # ${_list_path}
  # ${_maybe_selector_context}
  # ${_pinned_basenames[@]}
  # ${_selector_arguments[@]}
  # ${_selector_basename}

  # Use code blocks to capture all output for piping to pager.
  {
    if [[ -n "${_selector_basename:-}"        ]] &&
       [[ "${#_selector_arguments[@]}" -le 1  ]]
    then
      printf "%s\\n" "${_selector_basename}"
    else
      if ((_with_pinned)) && ((${#_pinned_basenames[@]}))
      then
        {
          printf "%s\\n" "${_pinned_basenames[@]:-}"
        } | {
          local         __pinned_basename=
          while read -r __pinned_basename
          do
            if [[ -e "${_list_path:-}/${__pinned_basename:-}" ]]
            then
              printf "%s\\n" "${__pinned_basename:-}"
            else
              _sed_i -e "s/^${__pinned_basename}$//g" "${_list_path}/.pindex"
              _sed_i -e '/^[[:space:]]*$/d'           "${_list_path}/.pindex"

              if [[ ! -s "${_list_path}/.pindex"              ]]
              then
                rm -f "${_list_path}/.pindex"
              fi

              local _deleted_pin_relative_path="${__pinned_basename:-}"

              if [[ -n "${_folder_relative_path:-}"           ]]
              then
                _deleted_pin_relative_path="${_folder_relative_path}/${__pinned_basename}"
              fi

              _git checkpoint "${_notebook_path}"                   \
                "[${_ME}] Unpinned: ${_deleted_pin_relative_path}"
            fi
          done
        } | {
          _list_files "${_list_path}" "${_list_files_options[@]:-}" \
            --standard-input  || :
        }
      fi

      if ! ((_only_pinned))
      then
        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
  } | {
    LC_ALL=C sed -E "${_IGNORE_PATTERNS[@]:-}"
  } | {
    local _filenames_count=0
    local _matches=0
    local _paginated_count=0
    local _pagination_max="$((_page * _limit))"
    local _pagination_min="$(((_page * _limit) - _limit))"
    local _pinned_basenames_seen=()
    local _printed_count=0

    local _max_id=
    _max_id="$(_index get_max_id "${_list_path}")"

    if ((_line_wrap))         &&
       ((_COLOR_ENABLED))     &&
       ! ((_list_filenames))  &&
       ! ((_list_paths))      &&
       ! ((_no_id))           &&
       ! ((_force_line_wrap))
    then
      _line_wrap=0
    fi

    # begin main loop

    local         __basename=
    while read -r __basename
    do
      [[ -z "${__basename:-}" ]] && continue

      _filenames_count=$((_filenames_count+1))

      local _first_line=
      local _maybe_title=
      local _title_basename_or_path="${__basename}"
      local _title_basename_or_path_color="${__basename}"

      if [[ -z "${_filter_pattern:-}"                       ]] &&
         [[ -n "${_selector_basename:-}"                    ]] &&
         [[ "${__basename}" != "${_selector_basename}"      ]]
      then
        continue # exclude from list
      elif ((_with_pinned)) &&
           _contains "${__basename}" "${_pinned_basenames_seen[@]:-}"
      then
        continue # exclude from list
      elif [[ -n "${_selector_basename}"                    ]] &&
           [[ "${__basename:-}" == "${_selector_basename}"  ]]
      then
        # include in list
        _matches=$((_matches+1))
      elif [[ -n "${_filter_pattern:-}" ]]
      then
        # turn on case-insensitive matching
        shopt -s nocasematch

        if [[ -n "${_selector_basename}"                    ]] &&
           [[ "${__basename:-}" == "${_selector_basename}"  ]]
        then
          # include in list
          _matches=$((_matches+1))
        elif [[ ! "${_filter_pattern}" =~ ^[0-9][0-9]$      ]] &&
             [[ "${__basename:-}" =~ ${_filter_pattern}     ]]
        then
          # include in list
          _matches=$((_matches+1))
        else
          _maybe_title="$(_get_content "${_list_path}/${__basename}")"

          if [[ "${_maybe_title:-}" =~ ^__first_line:       ]]
          then
            _first_line="${_maybe_title#__first_line:}"
            _maybe_title=
          fi

          if [[ "${_maybe_title:-}" =~ ${_filter_pattern}   ]]
          then
            # include in list
            _matches=$((_matches+1))
          else
            continue # exclude from list
          fi
        fi

        # turn off case-insensitive matching
        shopt -u nocasematch
      fi

      local _pinned=0

      if ((_with_pinned))
      then
        if _contains "${__basename}" "${_pinned_basenames[@]:-}"
        then
          _pinned=1
          _pinned_basenames_seen+=("${__basename}")
        elif ((_only_pinned))
        then
          continue
        fi
      fi

      if ((_paginate))
      then
        _paginated_count=$((_paginated_count+1))

        if   [[ "${_paginated_count}" -le "${_pagination_min}"  ]]
        then
          continue
        elif [[ "${_paginated_count}" -gt "${_pagination_max}"  ]]
        then
          break
        fi
      fi

      if [[   -n "${_limit:-}"                        ]] &&
         [[      "${_printed_count}" -ge "${_limit}"  ]]
      then # the limit has been reached
        if [[ -n "${_filter_pattern:-}"               ]]
        then
          # keep looking for matches to count total
          continue
        else
          if ((_only_pinned))
          then
            _filenames_count="${#_pinned_basenames[@]}"
          else
            _filenames_count="$(
              _count "${_list_path}" "${_list_files_options[@]:-}"
            )"
          fi

          break
        fi
      fi

      if ((_list_paths))
      then
        _title_basename_or_path="${_list_path}/${__basename}"
        _title_basename_or_path_color="${_list_path}/${__basename}"
      elif ! ((_list_filenames))
      then
        if [[ -z "${_maybe_title}" ]]
        then
          _maybe_title="$(_get_content "${_list_path}/${__basename}")"
        fi

        if [[ -n "${_maybe_title}" ]]
        then
          if [[ "${_maybe_title}" =~ ^__first_line: ]]
          then
            _first_line="${_maybe_title#__first_line:}"
            _maybe_title=
          else
            _title_basename_or_path="${_maybe_title}"
            _title_basename_or_path_color="${_maybe_title}"
          fi
        fi
      fi

      local _extra_length=0
      local _indicators=

      if ((_print_indicators))
      then
        if ((_with_pinned)) && ((_pinned))
        then
          _indicators+="${_NB_INDICATOR_PINNED:-}"
        fi

        # TODO: `show --indicators` duplicated for performance
        if [[ -d "${_list_path}/${__basename}" ]]
        then
          _indicators+="${_NB_INDICATOR_FOLDER:-}"
        elif _file_is_bookmark "${_list_path}/${__basename}"
        then
          _indicators+="${_NB_INDICATOR_BOOKMARK:-}"
        elif ! LC_ALL=C _contains "${__basename##*.}" "${_TEXT_FILE_EXTENSIONS[@]}"
        then
          if _file_is_image "${_list_path}/${__basename}"
          then
            _indicators+="${_NB_INDICATOR_IMAGE:-}"
          elif _file_is_document "${_list_path}/${__basename}"
          then
            _indicators+="${_NB_INDICATOR_DOCUMENT:-}"
          elif _file_is_video "${_list_path}/${__basename}"
          then
            _indicators+="${_NB_INDICATOR_VIDEO:-}"
          elif _file_is_audio "${_list_path}/${__basename}"
          then
            _indicators+="${_NB_INDICATOR_AUDIO:-}"
          elif [[ "${__basename}" =~ \.epub$ ]]
          then
            _indicators+="${_NB_INDICATOR_EBOOK:-}"
          fi
        fi

        if _file_is_encrypted "${_list_path}/${__basename}"
        then
          _indicators+="${_NB_INDICATOR_ENCRYPTED:-}"
        fi

        if _file_is_todo "${_list_path}/${__basename}"
        then
          # TODO: review
          if [[ "${_title_basename_or_path}" =~ \[x\]\  ]]
          then
            _indicators+="${_NB_INDICATOR_TODO_DONE% } "
            _extra_length="1"
          else
            _indicators+="${_NB_INDICATOR_TODO% } "
            _extra_length="-2"
          fi

          if ((_COLOR_ENABLED))
          then
            _title_basename_or_path_color="\
${_title_basename_or_path_color/\[x\]/${_TPUT_SETAF_8}[${_TPUT_COLOR_PRIMARY}x${_TPUT_SETAF_8}]${_TPUT_SGR0}}"
            _title_basename_or_path_color="\
${_title_basename_or_path_color/\[$' '\]/${_TPUT_SETAF_8}[ ]${_TPUT_SGR0}}"
          fi
        fi
      fi

      local _item_info="${_indicators}${_title_basename_or_path}"
      local _item_info_color="${_indicators}${_title_basename_or_path_color}"

      if ! ((_list_filenames))  &&
         ! ((_list_paths))      &&
         ! ((_print_excerpt))   &&
         [[ "${_title_basename_or_path}" == "${__basename}" ]]
      then
        if [[ -n "${_first_line:-}" ]]
        then
          _item_info="${_item_info} ${_MD} \"${_first_line}\""
          _item_info_color="${_item_info_color} ${_MD} \"${_first_line}\""
        fi
      fi

      local _info_line=
      local _info_line_color=

      if ((_no_id))
      then
        _info_line="${_item_info}"
        _info_line_color="${_item_info_color}"
      else
        local _escaped_basename="${__basename}"
        _escaped_basename="${_escaped_basename//\[/\\\[}"
        _escaped_basename="${_escaped_basename//\]/\\\]}"

        local _item_id=
        # use `sed` directly instead of `_index get_id` for performance
        _item_id="$(LC_ALL=C sed -n "/^${_escaped_basename:-}$/=" "${_list_path:-}/.index")"

        if [[ -z "${_item_id:-}" ]]
        then
          _index reconcile "${_list_path:-}" --ancestors --commit

          _item_id="$(LC_ALL=C sed -n "/^${_escaped_basename:-}$/=" "${_list_path:-}/.index")"
        fi

        local _item_identifier="${_maybe_selector_context:-}${_item_id:-}"
        local _max_identifier="${_maybe_selector_context:-}${_max_id:-}"

        local _brackets_identifier="[${_item_identifier:-}]"
        # avoid calling `_color_brackets` for performance
        local _brackets_identifier_color="\
${_TPUT_SGR0}\
${_TPUT_SETAF_8}\
[\
${_TPUT_COLOR_PRIMARY}\
${_item_identifier:-}\
${_TPUT_SETAF_8}\
]\
${_TPUT_SGR0}"

        # use calculated number of spaces for nicer formatting
        local _spaces_length=
        _spaces_length=$(( ${#_max_identifier} - ${#_item_identifier} + 1 ))

        local _spaces=
        printf -v _spaces '%*s' "${_spaces_length}" ""

        _info_line="${_brackets_identifier}${_spaces}${_item_info}"
        _info_line_color="${_brackets_identifier_color}${_spaces}${_item_info_color}"
      fi

      if ! ((_line_wrap))
      then
        _wrap off
      fi

      if ((_COLOR_ENABLED))
      then
        printf "%s" "${_info_line_color}"
      else
        printf "%s" "${_info_line}"
      fi

      if ! ((_line_wrap))
      then
        _wrap on
      fi

      # end of line
      printf "\\n"

      if ((_print_excerpt))                   &&
         [[ "${_excerpt_length}" =~ ^[0-9] ]] &&
         _file_is_text "${_list_path}/${__basename}"
      then # excerpt is specified with a non-zero digit, required by `head`
        _print_line "${_info_line:-}"         \
          --no-wrap                           \
          --visible-length "${_extra_length:-0}"

        if ((${_excerpt_length:-0}))
        then
          head -n "${_excerpt_length}" "${_list_path}/${__basename}" \
            | _highlight_syntax_if_available "${__basename##*.}"

          printf "\\n"
        fi
      fi

      _printed_count=$((_printed_count+1))
    done

    # end main loop

    if [[   -n "${_limit:-}"          ]] && ! ((_paginate))
    then
      if [[ -n "${_filter_pattern:-}" ]]
      then
        if [[ "${_matches:-0}"    -gt "${_limit}" ]] &&
           [[ "${_printed_count}" -ge "${_limit}" ]]
        then
          local _label="matches"
          local _omitted_count=
          _omitted_count=$((_matches-_printed_count))

          [[ "${_omitted_count}" -eq 1 ]] && _label="match"

          printf "%s %s omitted. %s total.\\n"    \
            "${_omitted_count}"                   \
            "${_label}"                           \
            "${_matches}"

          return 0
        fi
      elif [[ "${_filenames_count}" -gt "${_limit}" ]] &&
           [[ "${_printed_count}"   -ge "${_limit}" ]]
      then
        printf "%s omitted. %s total.\\n"         \
          "$((_filenames_count-_printed_count))"  \
          "${_filenames_count}"

        return 0
      fi
    fi

    if ! ((_printed_count)) && [[ -n "${_filter_pattern:-}"   ]]
    then
      local _filter_message=

      if _notebooks current --selected
      then
        _filter_message="$(_color_primary "$(_notebooks current):")"
      fi

      if [[ -n "${_folder_relative_path:-}"     ]]
      then
        _filter_message="${_filter_message}$(_color_primary "${_folder_relative_path}/")"
      fi

      if [[ -n "${_filter_message:-}"           ]]
      then
        _filter_message="${_filter_message} "
      fi

      _filter_message="${_filter_message}$(_color_primary "${_filter_pattern:-}")"

      if [[ -n "${_type:-}"                     ]]
      then
         _filter_message="${_filter_message} Type: $(_color_primary "${_type}")"
      fi

      _warn printf "Not found: %s\\n" "${_filter_message}"

      return 1
    fi

    if ! ((_filenames_count)) && [[ -z "${_filter_pattern:-}" ]]
    then
      {
        local _maybe_id_path_context_padded_left=
        local _maybe_id_path_context_padded_right=

        if [[ -n "${_maybe_id_path_context:-}"  ]]
        then
          _maybe_id_path_context="${_maybe_id_path_context//' '/\\ }"
          _maybe_id_path_context_padded_left=" ${_maybe_id_path_context:-}"
          _maybe_id_path_context_padded_right="${_maybe_id_path_context:-} "
        fi

        if [[ "${_type}" =~ (^bookmark$|^bookmarks$)    ]]
        then
          cat <<HEREDOC
0 bookmarks.

Add a bookmark:
  $(_color_primary "${_ME} ${_maybe_id_path_context_padded_right:-}<url>")
Help information:
  $(_color_primary "${_ME} help bookmark")
HEREDOC
        elif [[ "${_type}" =~ (^todo$|^todos$)          ]]
        then
          cat <<HEREDOC
0 todos.

Add a todo:
  $(_color_primary "${_ME} todo add${_maybe_id_path_context_padded_left:-} <title>")
Help information:
  $(_color_primary "${_ME} help todo")
HEREDOC
        elif [[ -n "${_type:-}" ]] || ((_only_pinned))
        then
          if _contains "${_type}" "bookmarks" "documents" "images" "videos" "folders"
          then
            _type="$(printf "%s\\n" "${_type}" | sed -e 's/s$//')"
          fi

          if ((_only_pinned))
          then
            cat <<HEREDOC
0 pinned ${_type:+"${_type} "}items.

Pin an item:
  $(_color_primary "${_ME} pin ${_maybe_id_path_context:-}<id>")
Help information:
  $(_color_primary "${_ME} help")
HEREDOC
          else
            if [[ "${_type:-}" =~ (^folder$|^folders$)  ]]
            then
              local _empty_type_label="folders"
            else
              local _empty_type_label="${_type} items"
            fi

            cat <<HEREDOC
0 ${_empty_type_label}.

Import a file:
  $(_color_primary "${_ME} import (<path> | <url>)${_maybe_id_path_context_padded_left:-}")
Help information:
  $(_color_primary "${_ME} help import")
HEREDOC
          fi
        else
          cat <<HEREDOC
0 items.

Add a note:
  $(_color_primary "${_ME} add${_maybe_id_path_context_padded_left:-}")
Add a bookmark:
  $(_color_primary "${_ME} ${_maybe_id_path_context_padded_right:-}<url>")
Add a todo:
  $(_color_primary "${_ME} todo add${_maybe_id_path_context_padded_left:-} <title>")
Import a file:
  $(_color_primary "${_ME} import (<path> | <url>)${_maybe_id_path_context_padded_left:-}")
Help information:
  $(_color_primary "${_ME} help")
HEREDOC
        fi
      } | {
        if ((_error_on_empty))
        then
          cat 1>&2

          return 1
        else
          cat

          return 0
        fi
      }
    fi
  } | if ((_use_pager))
      then
        _pager
      else
        cat
      fi
}

# ls · ################################################################### · ls

_describe_ls() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} ls [-a | --all] [-b | --browse] [-e [<length>] | --excerpt [<length>]]
        [--filenames] [-f | --folders-first] [-g | --gui]
        [-n <limit> | --limit <limit> | --<limit>] [--no-footer] [--no-header]
        [--no-id] [--no-indicator] [-p <number> | --page <number>] [--pager]
        [--paths] [-s | --sort] [-r | --reverse] [--tags]
        [-t <type> | --type <type> | --<type>]
        [<notebook>:][<folder-path>/][<id> | <filename> | <path> | <query>]

$(_color_primary "Options"):
  -a, --all                       Print all items in the notebook. Equivalent
                                  to no limit.
  -b, --browse                    Open the specified item or current notebook
                                  with \`browse\` in a terminal web browser.
  -e, --excerpt [<length>]        Print an excerpt <length> lines long under
                                  each note's filename [default: 3].
  --filenames                     Print the filename for each note.
  -f, --folders-first             Print folders before other items.
  -g, --gui                       Open the specified item or current notebook
                                  with \`browse\` in a GUI web browser.
  -n, --limit <limit>, --<limit>  The maximum number of listed items.
                                  [default: 15]
  --no-footer                     Print without footer.
  --no-header                     Print without header.
  --no-id                         Don't include the id in list items.
  --no-indicator                  Don't include the indicator in list items.
  -p, --page <number>             The page to view in the list paginated by
                                  a <limit> option or \`${_ME} set limit\`.
  --pager                         Display output in the pager.
  --paths                         Print the full path to each item.
  -s, --sort                      Order notes by id.
  -r, --reverse                   List items in reverse order.
  --tags                          List tags in the notebook or folder.
  -t, --type <type>, --<type>     List items of <type>. <type> can be a file
                                  extension or one of the following types:
                                  note, book, bookmark, document, archive,
                                  image, video, audio, folder, text

$(_color_primary "Description"):
  List notebooks and notes in the current notebook, displaying note titles
  when available. \`${_ME} ls\` is a combination of \`${_ME} notebooks\` and
  \`${_ME} list\` in one view.

  When <id>, <filename>, <path>, or <title> are present, the listing for the
  matching note is displayed. When no match is found, titles and filenames
  are searched for any that match <query> as a case-insensitive regular
  expression.

  Options are passed through to \`list\`. For more information, see
  \`${_ME} help list\`.

$(_color_primary "Read More"):
  ${_README_URL}#listing--filtering

$(_color_primary "Indicators"):
  ${_NB_INDICATOR_AUDIO:-} Audio
  ${_NB_INDICATOR_EBOOK:-} Book
  ${_NB_INDICATOR_BOOKMARK:-} Bookmark
  ${_NB_INDICATOR_ENCRYPTED:-} Encrypted
  ${_NB_INDICATOR_FOLDER:-} Folder
  ${_NB_INDICATOR_IMAGE:-} Image
  ${_NB_INDICATOR_DOCUMENT:-} PDF, Word, or Open Office document
  ${_NB_INDICATOR_VIDEO:-} Video

$(_color_primary "See Also"):
  ${_ME} help browse
  ${_ME} help list
  ${_ME} help pin
  ${_ME} help search
  ${_ME} help unpin

$(_color_primary "Examples"):
  ${_ME}
  ${_ME} --all
  ${_ME} ls
  ${_ME} ls example.md -e 10
  ${_ME} ls --excerpt --no-id
  ${_ME} ls --reverse
  ${_ME} ls "^Example.*"
  ${_ME} ls --10
  ${_ME} ls --type document
  ${_ME} example:
  ${_ME} example: -ae
  ${_ME} example:ls

$(_color_primary "Shortcut Alias"):
  ${_ME}
HEREDOC
}
_ls() {
  # _ls_print_footer()
  #
  # Usage:
  #   _ls_print_footer [<selector>]
  _ls_print_footer() {
    local _footer_line_hi=
    local _footer_line_raw=
    local _footer_separator_raw=" ${_MD}"
    local _footer_test_line=
    local _maybe_notebook=
    local _maybe_selector_scope=
    local _maybe_selector_scope_padded_left=
    local _maybe_selector_scope_padded_right=
    local _selector_path="${1:-}"

    local _footer_separator_hi=
    _footer_separator_hi="$(_color_primary "${_footer_separator_raw}")"

    if _notebooks current --selected
    then
      _maybe_notebook="$(
        _notebooks show "$(_notebooks current)" --escaped --no-color
      ):"
    fi

    local _folder_id_path=
    _folder_id_path="$(_get_id_selector "${_selector_path:-}")"

    if [[ -n "${_maybe_notebook:-}" ]] ||
       [[ -n "${_folder_id_path:-}" ]]
    then
      _maybe_selector_scope="${_maybe_notebook}${_folder_id_path}"
      _maybe_selector_scope_padded_left=" ${_maybe_selector_scope}"
      _maybe_selector_scope_padded_right="${_maybe_selector_scope} "
    fi

    local _notebook_command="${_ME} notebooks add <name>"

    local _unarchived_notebook_count=0

    set +f
    local __path=
    for   __path in "${NB_DIR}"/*
    do
      if [[ ! -f "${__path:?}/.archived"          ]]
      then
        _unarchived_notebook_count=$((_unarchived_notebook_count + 1))
      fi

      if [[ "${_unarchived_notebook_count}" -gt 1 ]]
      then
        if [[ -n "${_maybe_notebook:-}"           ]]
        then
          _notebook_command="${_ME} use ${_maybe_notebook%%:*}"
        else
          _notebook_command="${_ME} use <notebook>"
        fi

        break
      fi
    done
    set -f

    local _commands_raw=(
      "${_CHEVRON_RIGHT} ${_ME}${_maybe_selector_scope_padded_left}"
      "${_ME} add${_maybe_selector_scope_padded_left}"
      "${_ME} ${_maybe_selector_scope_padded_right}<url>"
      "${_ME} edit ${_maybe_selector_scope}<id>"
      "${_ME} show ${_maybe_selector_scope}<id>"
      "${_ME} open ${_maybe_selector_scope}<id>"
      "${_ME} browse${_maybe_selector_scope_padded_left}"
      "${_ME} todos${_maybe_selector_scope_padded_left}"
      "${_ME} tasks${_maybe_selector_scope_padded_left}"
      "${_ME} search ${_maybe_selector_scope_padded_right}<query>"
      "${_notebook_command}"
      "${_ME} settings"
      "${_ME} help"
    )

    local _commands_hi=(
      "$(_color_muted "${_CHEVRON_RIGHT}") $(_color_secondary "${_ME}${_maybe_selector_scope_padded_left}")"
      "$(_color_secondary "${_commands_raw[1]}")"
      "$(_color_secondary "${_commands_raw[2]}")"
      "$(_color_secondary "${_commands_raw[3]}")"
      "$(_color_secondary "${_commands_raw[4]}")"
      "$(_color_secondary "${_commands_raw[5]}")"
      "$(_color_secondary "${_commands_raw[6]}")"
      "$(_color_secondary "${_commands_raw[7]}")"
      "$(_color_secondary "${_commands_raw[8]}")"
      "$(_color_secondary "${_commands_raw[9]}")"
      "$(_color_secondary "${_commands_raw[10]}")"
      "$(_color_secondary "${_commands_raw[11]}")"
      "$(_color_secondary "${_commands_raw[12]}")"
    )

    _wrap off

    _print_line "$(printf "%-${_COLUMNS}s" '.')" | tr -d '\n'

    printf "%s" "${_TPUT_SGR0}"

    _wrap on

    printf "\\n"

    local i=
    for ((i=0; i < ${#_commands_raw[@]}; i++))
    do
      if [[ -z "${_footer_test_line}"                 ]]
      then # first item in line
        _footer_test_line="${_commands_raw[i]}"
      else
        _footer_test_line="${_footer_test_line}${_footer_separator_raw} ${_commands_raw[i]}"
      fi

      if [[ "${#_footer_test_line}" -gt "${_COLUMNS}" ]]
      then # wrap to next line
        printf "%s\\n" "${_footer_line_hi}"

        # Start the line for the next iteration using the current name.
        _footer_test_line="${_commands_raw[i]}"
        _footer_line_hi="${_commands_hi[i]:-}"
        _footer_line_raw="${_commands_raw[i]}"
      else # add to line
        if [[ -z "${_footer_line_hi}" ]]
        then # first item in highlighted line
          _footer_line_hi="${_commands_hi[i]:-}"
          _footer_line_raw="${_commands_raw[i]}"
        else
          _footer_line_hi="${_footer_line_hi}${_footer_separator_hi} ${_commands_hi[i]:-}"
          _footer_line_raw="${_footer_line_raw}${_footer_separator_raw} ${_commands_raw[i]}"
        fi
      fi

      if [[ "${#_commands_raw[@]}" == $((i+1))        ]]
      then # end of list
        printf "%s\\n" "${_footer_line_hi}"
      fi
    done
  }

  # _ls_print_folder_header()
  #
  # Usage: _ls_print_folder_header <folder-path>
  _ls_print_folder_header() {
    [[ -z "${1:-}" ]] && return 0

    # printf "${_NB_INDICATOR_FOLDER:-}" # TODO: Review

    local _folder_separator=
    _folder_separator="$(_color_muted "/")"

    printf "%s\\n" "${1//\// ${_folder_separator} }"

    _print_line "$(printf "%-${_COLUMNS}s" '.')" --muted

    printf "\\n"
  }

  # _ls_print_header()
  #
  # Usage:
  #   _ls_print_header <alignment>
  #
  # Description:
  #   Build word-wrapping notebook line. `fold` doesn't account for
  #   highlighting.
  #
  #   Simple version:
  #     _notebooks --names            \
  #       | tr '\n' ' '               \
  #       | fold -s "-w$(tput cols)"  \
  #       && printf "\\n"
  _ls_print_header() {
    local _alignment="${1:-}"
    local _auto_align=1 # auto-align by default.
    local _centered=0
    local _justified=0
    local _plain=0

    [[ "${NB_HEADER}" == 2 ]] && _centered=1
    [[ "${NB_HEADER}" == 3 ]] && _justified=1

    case "${_alignment}" in
      --auto*align)
        _auto_align=1
        _centered=0
        _justified=0
        ;;
      --centered)
        _auto_align=0
        _centered=1
        _justified=0
        ;;
      --justified)
        _auto_align=0
        _centered=0
        _justified=1
        ;;
      --plain)
        _plain=1
        ;;
    esac

    local _separator=
    local _separator_hi=

    if ! ((_plain))
    then
      _separator=" ${_MD}"
      _separator_hi="$(_color_muted "${_separator}")"
    fi

    local _current_notebook_name=
    _current_notebook_name="$(_notebooks current)"

    local _highlight_archived=0

    if [[ -e "${NB_NOTEBOOK_PATH:-}/.archived" ]]
    then
      _highlight_archived=1
    fi

    {
      local _archived_count=0
      local _unarchived_notebook_names=()

      set +f
      local __path=
      for   __path in "${NB_DIR}"/*
      do
        if [[ -f "${__path:?}/.archived" ]]
        then
          _archived_count=$((_archived_count+1))
        else
          _unarchived_notebook_names+=("${__path##*\/}")
        fi
      done
      set -f

      if _notebooks current --local
      then
        printf "local\\n"
      fi

      printf "%s\\n" "${_unarchived_notebook_names[@]:-}"

      if ((_archived_count))
      then
        printf "[%s archived]\\n" "${_archived_count}"
      fi
    } | {
      local _line_hi=
      local _line_number=0
      local _line_raw=
      local _output_line_raw=
      local _padding=
      local _test_line=

      local         __header_name=
      while read -r __header_name
      do
        local _maybe_highlighted_notebook_name=

        if [[ "${_current_notebook_name}" == "${__header_name}" ]] ||
           {
             ((_highlight_archived))                               &&
             [[ "${__header_name:-}"      =~ ^\[.*\]            ]]
           }
        then
          _maybe_highlighted_notebook_name="$(
            _color_primary "${__header_name:-}" --underline
          )"
        else
          _maybe_highlighted_notebook_name="${__header_name:-}"
        fi

        if [[ -z "${_test_line}"                  ]]
        then # first item in line
          _test_line="${__header_name}"
        else
          _test_line="${_test_line}${_separator} ${__header_name}"
        fi

        if [[ "${#_test_line}" -gt "${_COLUMNS}"  ]]
        then # wrap to next line
          # Use the existing value of $_line_[highlighted|raw] without the
          # current name.
          if ((_auto_align)) || ((_centered)) && ! ((_justified))
          then
            _centered=1
            _padding="$(
              _print_padding "${_line_raw}" "${_COLUMNS}" "${_centered}"
            )"
          fi

          printf "%s%s%s\\n" "${_TPUT_SGR0}" "${_padding:-}" "${_line_hi:-}"
          _output_line_raw="${_padding}${_line_raw}\\n"
          _line_number=$((_line_number + 1))

          # Start the line for the next iteration using the current name.
          _test_line="${__header_name}"
          _line_hi="${_maybe_highlighted_notebook_name:-}"
          _line_raw="${__header_name}"
        else # add to line
          if [[ -z "${_line_hi}"                  ]]
          then # first item in highlighted line
            _line_hi="${_maybe_highlighted_notebook_name:-}"
            _line_raw="${__header_name}"
          else
            _line_hi="${_line_hi}${_separator_hi} ${_maybe_highlighted_notebook_name:-}"
            _line_raw="${_line_raw}${_separator} ${__header_name}"
          fi
        fi
      done

      if ((_line_number))  && ! ((_justified)) &&
         ((_auto_align))   ||   ((_centered))
      then
        _centered=1
      fi

      _padding="$(
        _print_padding "${_line_raw}" "${_COLUMNS}" "${_centered}"
      )"

      printf "%s%s%s\\n" "${_TPUT_SGR0}" "${_padding:-}" "${_line_hi:-}"
      _output_line_raw="${_padding}${_line_raw}\\n"

      _wrap off

      if ((_centered))
      then # print full-width line.
        _print_line "$(printf "%-${_COLUMNS}s" '.')" | tr -d '\n'
      else # print line the length of the first line.
        _print_line "$(
          # $_output_line_raw content is 2 characters too long. TODO: Review
          printf "%s" "${_output_line_raw}" | LC_ALL=C sed 's/..$//'
        )" | tr -d '\n'
      fi

      printf "%s" "${_TPUT_SGR0}"

      _wrap on

      printf "\\n"
    }
  }

  local _all=0
  local _arguments=()
  local _delegate_to_browse=0
  local _delegate_arguments=()
  local _fast_exit=0
  local _filter_patterns=()
  local _folders_first="${NB_FOLDERS_FIRST:-0}"
  local _header_flags=()
  local _limit=
  local _maybe_type=
  local _selector=
  local _selector_folder_path=
  local _use_pager=0
  local _with_pinned=1

  while ((${#}))
  do
    case "${1:-}" in
      --added*|--created*|--updated*|--ar|--archived|--unar|--unarchived)
        _delegate_arguments+=("${1}")
        ;;
      -a|--all)
        _all=1
        ;;
      --auto*align|--centered|--justified|--plain)
        _header_flags+=("${1}")
        ;;
      -b|--browse)
        _delegate_to_browse=1
        ;;
      --content|--title)
        if _option_value_is_present "${2:-}"
        then
          _delegate_arguments+=("${1}" "${2:-}")

          shift
        fi
        ;;
      --*exit*)
        _fast_exit=1
        ;;
      --folders-first|--ff|-ff|--f|-f)
        _folders_first=1
        ;;
      -g|--gui)
        _delegate_to_browse=1
        _delegate_arguments+=("${1}")
        ;;
      --limit|-n|--num|--number|--per*)
        _limit="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      --pager|--less)
        _use_pager=1
        ;;
      -l)
        : # Ignore accidental ls -l  due to muscle memory.
        ;;
      --no*folders*first|--no*ff|-no*ff|--no*f|-no*f)
        _folders_first=0
        ;;
      --no*footer)
        NB_FOOTER=0
        ;;
      --no*header)
        NB_HEADER=0
        ;;
      -s|--sort|-r|--reverse)
        _arguments+=("${1}")
        _with_pinned=0
        ;;
      --tag*)
        _delegate_arguments+=("${1}")

        if _option_value_is_present "${2:-}"
        then
          _delegate_arguments+=("${2:-}")

          shift
        fi
        ;;
      -t|--type)
        _maybe_type="$(_option_get_value "${1}" "${2:-}")"
        _arguments+=("${1}" "${2:-}")

        shift
        ;;
      --[A-Za-z]*)
        _maybe_type="${1:2}"

        _arguments+=("${1}")
        ;;
      -*)
        if [[ "${1:-}" =~ ^-+[0-9]+$  ]]
        then
          _limit="${1##*-}"
        else
          _arguments+=("${1}")

          if _option_value_is_present "${2:-}"
          then
            _arguments+=("${2:-}")

            shift
          fi
        fi
        ;;
      \#*)
        _delegate_arguments+=(--tag "${1}")
        ;;
      *:*)
        local _selector_id=
        _selector_id="$(_selector_get_identifier "${1}")"

        if [[ -n "${_selector_id:-}"  ]]
        then
          _arguments+=("${_selector_id}")
        fi

        _selector="${1:-}"
        _filter_patterns+=("${1}")
        ;;
      *)
        if [[ -z "${_selector:-}"     ]]
        then
          _selector="${1}"
        fi

        _arguments+=("${1}")
        _filter_patterns+=("${1}")
        ;;
    esac

    shift
  done

  # Delegate to `add`, `show`, and other subcommands.

  if ((${#_delegate_arguments[@]})) || ((_delegate_to_browse))
  then
    if ((_delegate_to_browse))
    then
      _defer "_browse" "${_arguments[@]:-}" "${_delegate_arguments[@]:-}"

      return 0
    else
      local i=
      for ((i=0; i < ${#_delegate_arguments[@]}; i++))
      do
        case "${_delegate_arguments[i]:-}" in
          --ar*|--unar*)
            _defer "_notebooks" list "${_delegate_arguments[@]:-}"

            return 0
            ;;
          --added*|--created*|--updated*)
            if [[ -n "${_selector:-}"     ]]
            then
              _defer "_show" "${_arguments[@]:-}" "${_delegate_arguments[@]:-}"

              return 0
            fi
            ;;
          --content|--title)
            if _option_value_is_present "${_delegate_arguments[$((i+1))]:-}"
            then
              _defer "_add" "${_arguments[@]:-}" "${_delegate_arguments[@]:-}"

              return 0
            fi
            ;;
          --tag*)
            ((_all)) && _delegate_arguments+=("--all")
            _defer "_search"                \
              "${_arguments[@]:-}"          \
              "${_delegate_arguments[@]:-}" \
              --list

            return 0
            ;;
          *)
            if [[ -n "${_arguments[i]:-}" ]]
            then
              _arguments+=("${_arguments[i]:-}")
            fi
            ;;
        esac
      done
    fi
  fi

  # Build list options.

  local _list_options=(${_arguments[@]:-})

  if ((_with_pinned))
  then
    _list_options+=("--with-pinned")
  fi

  if ((_folders_first))
  then
    _list_options+=("--folders-first")
  fi

  local _selector_relative_path="${_selector#*:}"

  if [[ -n "${_limit:-}"                            ]]
  then
    _list_options+=("--limit" "${_limit}")
  elif ! ((_all))                                       &&
       [[ -z "${_AUTO_LIMIT:-}"                     ]]  &&
       {
         [[ -z "${_selector_relative_path:-}"       ]]  ||
         {
           [[ "${_selector_relative_path:-}" =~ /   ]]  &&
           [[ -z "${_selector_relative_path##*\/}"  ]]  &&
           [[ "${#_filter_patterns[@]}" -le 1       ]]
         }
       }
  then
    _list_options+=("--limit" "${NB_LIMIT}")
  fi

  # Resolve selector folders before printing header to minimize pause
  # before printing list.

  if [[ "${_selector:-}" =~ /             ]]
  then
    _selector_folder_path="$(_selector_resolve_folders "${_selector}" || :)"

    if [[ -n "${_selector_folder_path:-}" ]]
    then
      _selector_folder_path="${_selector_folder_path}/"
    fi
  fi

  # Determine whether to display header and footer.

  local _display_header_and_footer=0

  if [[ -z "${_arguments[*]:-}"           ]]  ||
     {
       [[ "${_selector:-}" =~ (/$|:$)     ]]  &&
       [[ -n "${_selector_folder_path:-}" ]]  &&
       [[ "${#_arguments[@]}" -le 1       ]]
     }
  then
    _display_header_and_footer=1
  fi

  # Pre-load auto --limit header and footer.

  local _footer=
  local _header=

  if [[ -n "${_AUTO_LIMIT:-}"             ]]  &&
     ! ((_all))                               &&
     ! _contains "--limit" "${_list_options[@]:-}"
  then
    local _available_lines=0
    _available_lines="$(_tput lines)"

    local _header_and_footer_line_count=0

    if ((NB_HEADER)) && ((_display_header_and_footer))
    then
      _header="$(_ls_print_header "${_header_flags[@]:-}")"
    fi

    if ((NB_FOOTER)) && ((_display_header_and_footer))
    then
      _footer="$(_ls_print_footer "${_selector_folder_path:-}")"
    fi

    local _header_and_footer_line_count=0
    _header_and_footer_line_count="$(
      {
        [[ -n "${_header:-}" ]] && printf "%s\\n" "${_header:-}"
        [[ -n "${_footer:-}" ]] && printf "%s\\n" "${_footer:-}"

        printf ""
      } | wc -l | xargs
    )"

    local _auto_limit_adjustment="$((_AUTO_LIMIT - 2))"
    local _auto_limit_amount=1

    _auto_limit_amount="$((
      ${_available_lines:-1}                -
        ${_header_and_footer_line_count:-0} +
        ${_auto_limit_adjustment:-0}
    ))"

    [[ "${_auto_limit_amount}" -gt 0 ]] || _auto_limit_amount=1

    if [[ -n "${_AUTO_LIMIT_MAX:-}"  ]] &&
       [[    "${_AUTO_LIMIT_MAX:-}" -lt "${_auto_limit_amount:-1}" ]]
    then
      _auto_limit_amount="${_AUTO_LIMIT_MAX}"
    fi

    _list_options+=("--limit" "${_auto_limit_amount:-1}")
  fi

  local _list_error=

  # NOTE: Pipeline structured to start List, Header, and Footer concurrently.
  {
    # List
    # ----
    {
      # Capture error to variable while preserving standard output. More info:
      # https://unix.stackexchange.com/a/474195
      _list_error="$(
        _list --error-on-empty "${_list_options[@]:-}" 2>&1 >&3 3>&-
      )"
    } 3>&1 || {
      if [[ -n  "${_arguments[0]:-}"        ]]  &&
         [[ !   "${_arguments[0]:-}" =~ ^-- ]]
      then
        local _maybe_notebook_name="${_arguments[0]:-}"

        _maybe_notebook_name="$(
          printf "%s\\n" "${_maybe_notebook_name}" | LC_ALL=C sed 's/\:$//'
        )"

        local _notebook_name=
        _notebook_name="$(
          _notebooks \
            show "${_maybe_notebook_name:-}" --name --no-color 2>/dev/null || :
        )"
      fi

      if [[ -n "${_notebook_name:-}"          ]]  &&
         ! _notebooks current --selected          &&
         [[ -d "${NB_DIR}/${_notebook_name}"  ]]
      then
        NB_NOTEBOOK_PATH="${NB_DIR}/${_notebook_name}"  \
          _ls "${_arguments[@]:1}"

        return 0
      else
        local _count_arguments=()

        if [[ -n "${_selector:-}"   ]]
        then
          _count_arguments+=("${_selector}")
        fi

        if [[ -n "${_maybe_type:-}" ]]
        then
          _count_arguments+=("--${_maybe_type}")
        fi

        local _local_count=
        _local_count="$(
          _count "${_count_arguments[@]:-}" --skip-unmatched-selector || :
        )"

        if ! ((_local_count))                           &&
           {
             [[ -n  "${_selector_folder_path:-}"    ]]  ||
             [[ !   "${_filter_patterns[*]:-}" =~ / ]]
           }
        then
          {
            _list "${_list_options[@]:-}"
          } | {
            if [[ -z "${_selector:-}"               ]]  ||
               {
                 [[ "${_selector:-}" =~ (/$|:$)     ]]  &&
                 [[ "${#_filter_patterns[@]}" -eq 1 ]]
               }
            then # only container arguments
              if ((NB_HEADER)) && [[ -n "${_maybe_type:-}"  ]]
              then
                _ls_print_header "${_header_flags[@]:-}"
              fi

              if ! ((${NB_FOLDER_HEADER:-0}))
              then
                _ls_print_folder_header "${_selector_folder_path:-}"
              fi

              cat

              if ((NB_FOOTER)) && [[ -n "${_maybe_type:-}"  ]]
              then
                _ls_print_footer "${_selector_folder_path:-}"
              fi
            else
              cat
            fi
          }
        else
          if [[ -n "${_list_error:-}" ]]
          then
            printf "%s\\n" "${_list_error}"

            return 1
          fi
        fi
      fi
    }
  } | {
    # Header
    # ------

    if ((NB_HEADER)) && ((_display_header_and_footer))
    then
      if [[ -n "${_header:-}"             ]]
      then
        printf "%s\\n" "${_header:-}"
      else
        _ls_print_header "${_header_flags[@]:-}"
      fi
    fi

    if [[ -n "${_selector_folder_path:-}" ]] &&
       ((${NB_FOLDER_HEADER:-0}))            &&
       ((_display_header_and_footer))
    then
      _ls_print_folder_header "${_selector_folder_path:-}"
    fi

    cat

  } | {
    # Footer
    # ------

    if ((NB_FOOTER))                  &&
       ((_display_header_and_footer)) &&
       [[ -z "${_footer:-}" ]]
    then
      _footer="$(_ls_print_footer "${_selector_folder_path:-}")"
    fi

    cat

    if [[ -n "${_footer:-}" ]]
    then # print preloaded footer
      printf "%s\\n" "${_footer}"
    fi
  } | {
    if ((_use_pager))
    then
      _pager
    else
      cat
    fi
  }

  if ((_fast_exit))
  then
    exit 0
  else
    return 0
  fi
}

# notebooks · ##################################################### · notebooks

_describe_notebooks() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} notebooks [<name> | <query>] [--ar | --archived] [--global] [--local]
               [--names] [--paths] [--unar | --unarchived]
  ${_ME} notebooks add ([<name>] [<remote-url> [<branch>... | --all]]) [--author]
                   [--email <email>] [--name <name>]
  ${_ME} notebooks (archive | open | peek | status | unarchive) [<name>]
  ${_ME} notebooks author [<name> | <path>] [--email <email>] [--name <name>]
  ${_ME} notebooks current [--path | --selected | --filename [<filename>]]
                       [--global | --local]
  ${_ME} notebooks delete <name> [-f | --force]
  ${_ME} notebooks (export <name> [<path>] | import <path>)
  ${_ME} notebooks init [<path> [<remote-url> [<branch>]]] [--author]
                    [--email <email>] [--name <name>]
  ${_ME} notebooks rename <old-name> <new-name>
  ${_ME} notebooks select <selector>
  ${_ME} notebooks show (<name> | <path> | <selector>) [--ar | --archived]
                    [--escaped | --name | --path | --filename [<filename>]]
  ${_ME} notebooks use <name>

$(_color_primary "Options"):
  --all                    Add notebooks from all remote branches.
  --ar, --archived         List archived notebooks, or return archival status
                           with \`show\`.
  --author                 Set the notebook's commit author email and name.
  --email <email>          Set the notebook's commit author email to <email>.
  --escaped                Print the notebook name with spaces escaped.
  --filename [<filename>]  Print an available filename for the notebooks. When
                           <filename> is provided, check for an existing file
                           and provide a filename with an appended sequence
                           number for uniqueness.
  -f, --force              Skip the confirmation prompt.
  --global                 List global notebooks or the notebook set globally
                           with \`use\`.
  --local                  Exit with 0 if current within a local notebook,
                           otherwise exit with 1.
  --name, --names          Print the notebook name.
  --name <name>            Set the notebook's commit author name to <name>.
  --path, --paths          Print the notebook path.
  --selected               Exit with 0 if the current notebook differs from
                           the current global notebook, otherwise exit with 1.
  --unar, --unarchived     Only list unarchived notebooks.

$(_color_primary "Subcommands"):
  (default)  List notebooks.
  add        Create a new global notebook. When <remote-url> is specified,
             create one or more new global notebook by cloning selected
             or specified <branch>es from <remote-url>.
             Aliases: \`${_ME} notebooks create\`, \`${_ME} notebooks new\`
  archive    Set the current notebook or notebook <name> to "archived" status.
  author     Configure the commit author email and name for the notebook.
  current    Print the current notebook name or path.
  delete     Delete a notebook.
  export     Export the notebook <name> to the current directory or <path>,
             making it usable as a local notebook.
  import     Import the local notebook at <path> to make it global.
  init       Create a new local notebook. Specify a <path> or omit to
             initialize the current working directory as a local notebook.
             Specify <remote-url> to clone an existing notebook.
  open       Open the current notebook directory or notebook <name> in the
             file browser, explorer, or finder.
             Shortcut Alias: \`o\`
  peek       Open the current notebook directory or notebook <name> in the
             first tool found in the following list:
             \`ranger\` [1], \`mc\` [2], \`vifm\` [3], \`joshuto\` [4], \`eza\` [5], or \`ls\`.
             Shortcut Alias: \`p\`
  rename     Rename a notebook. Aliases: \`move\`, \`mv\`
  select     Set the current notebook from a colon-prefixed selector.
             Not persisted. Selection format: <notebook>:<identifier>
  status     Print the archival status of the current notebook or
             notebook <name>.
  show       Show and return information about a specified notebook.
  unarchive  Remove "archived" status from the current notebook or notebook <name>.
  use        Switch to a notebook.

    1. https://ranger.github.io/
    2. https://en.wikipedia.org/wiki/Midnight_Commander
    3. https://vifm.info/
    4. https://github.com/kamiyaa/joshuto
    5. https://github.com/eza-community/eza

$(_color_primary "Description"):
  Manage notebooks.

$(_color_primary "Read More"):
  ${_README_URL}#-notebooks

$(_color_primary "See Also"):
  ${_ME} help archive
  ${_ME} help history
  ${_ME} help move
  ${_ME} help remote
  ${_ME} help status
  ${_ME} help sync
  ${_ME} help unarchive
  ${_ME} help use

$(_color_primary "Examples"):
  ${_ME} notebooks --names
  ${_ME} notebooks add sample
  ${_ME} notebooks add example https://github.com/example/example.git
  ${_ME} nb current --path
  ${_ME} nb archive example

$(_color_primary "Shortcut Aliases"):
  ${_ME} n
  ${_ME} nb
HEREDOC
}
_RESERVED_NOTEBOOK_NAMES=(
  ".cache"
  ".current"
  ".plugins"
  ".readme"
  "readme"
  "readme.md"
)
_notebooks() {
  # _notebooks_add()
  #
  # Usage:
  #   _notebooks_add ([<name>] [<remote_url> [<branch>... | --all]]) [--author]
  #                  [--email <email>] [--name <name>]
  _notebooks_add() {
    local _author=0
    local _author_arguments=()
    local _clone_all_branches=0
    local _name=
    local _print_default_feedback=1
    local _option_selected_remote_branches=()
    local _remote_url=

    while ((${#}))
    do
      case "${1:-}" in
        --all)    _clone_all_branches=1 ;;
        --author) _author=1             ;;
        --email|--name)
          _author=1
          _author_arguments+=("${1:-}")

          if _option_value_is_present "${2:-}"
          then
            _author_arguments+=("${2:-}")

            shift
          fi
          ;;
        *)
          if _string_is_url "${1:-}"
          then
            _remote_url="${1:-}"
          elif [[ -z "${_name:-}"         ]] &&
               [[ -z "${_remote_url:-}"   ]]
          then
            _name="${1:-}"
          else
            _option_selected_remote_branches+=("${1:-}")
          fi
          ;;
      esac

      shift
    done

    if [[ -z "${_name:-}"                 ]] &&
       [[ -z "${_remote_url:-}"           ]]
    then
      _exit_1 _help notebooks
    fi

    if   [[ -n "${_remote_url:-}"         ]]
    then
      local _git_options=(
        --no-local
        --single-branch
      )
    fi

    if [[ -n "${_name:-}"                 ]]
    then
      _notebooks_validate_name "${_name}"

      if [[ -e "${NB_DIR}/${_name}"       ]]
      then
        _exit_1 printf "Already exists: %s\\n" "$(_color_primary "${_name}")"
      fi
    fi

    if [[ -n "${_remote_url:-}"           ]]
    then
      if [[ -n "${_name:-}"               ]] &&
         ! ((${#_option_selected_remote_branches[@]}))
      then
        git clone "${_git_options[@]:-}"  \
          "${_remote_url}"                \
          "${NB_DIR}/${_name}"
      elif [[ -n "${_name:-}"                                 ]] &&
           [[ "${#_option_selected_remote_branches[@]}" -eq 1 ]]
      then
        git clone "${_git_options[@]:-}"                      \
          --branch "${_option_selected_remote_branches[0]:-}" \
          "${_remote_url}"                                    \
          "${NB_DIR}/${_name}"
      else
        local _current_notebook_path=
        _current_notebook_path="$(_notebooks current --path)"

        local _remote_branches=()

        if [[ -n "${_option_selected_remote_branches[*]:-}" ]]
        then
          _remote_branches=("${_option_selected_remote_branches[@]}")
        else
          _remote_branches=($(
            git -C "${_current_notebook_path}" ls-remote  \
              --heads "${_remote_url:-}"                  \
              2>/dev/null                                 \
              | LC_ALL=C sed "s/.*\///g"
          ))
        fi

        if ! ((${#_remote_branches[@]}))
        then
          _warn printf "No remote branches found.\\n"

          return 1
        else
          local _selected_branches=()

          _print_default_feedback=0

          if ((${#_option_selected_remote_branches[@]}))
          then
            _selected_branches=("${_option_selected_remote_branches[@]:-}")
          elif [[ "${#_remote_branches[@]}" -eq 1 ]]
          then
            _selected_branches=("${_remote_branches[0]:-}")
          elif ((_clone_all_branches))
          then
            _selected_branches=("${_remote_branches[@]:-}")
          fi

          if ! ((${#_selected_branches[@]}))
          then
            printf      "Choose a remote branch:\\n"

            _print_line "-----------------------"

            local i=
            for ((i=0; i < ${#_remote_branches[@]}; i++))
            do
              printf "%s %s\\n"                 \
                "$(_color_brackets "$((i+1))")" \
                "${_remote_branches[${i}]:-}"
            done

            printf "%s All Branches\\n"         \
              "$(_color_brackets "$((i+1))")"

            local _branch_prompt_response=

            while true
            do
              IFS='' read -r -e -d $'\n' -p                                               \
                "$(_color_primary "Choose a branch") or $(_color_primary "q") to quit: "  \
                _branch_prompt_response

              case "${_branch_prompt_response:-}" in
                q*|exit)
                  printf "Exiting%s\\n" "$(_color_muted "...")"

                  exit 0
                  ;;
                [0-9]*)
                  if [[ -n "${_remote_branches[$((_branch_prompt_response - 1))]:-}" ]]
                  then
                    _branch_prompt_response="${_remote_branches[$((_branch_prompt_response - 1))]:-}"

                    break
                  elif [[ "${_branch_prompt_response}" -eq "$((${#_remote_branches[@]} + 1))" ]]
                  then
                    _clone_all_branches=1

                    break
                  fi
                  ;;
                *)
                  if _contains "${_branch_prompt_response}" "${_remote_branches[@]}"
                  then
                    break
                  fi
              esac
            done

            if ((_clone_all_branches))
            then
              _selected_branches=("${_remote_branches[@]:-}")
            else
              _selected_branches=("${_branch_prompt_response:-}")
            fi

            _print_line "------------------------------------"
          fi

          if ! ((${#_selected_branches[@]}))
          then
            _selected_branches=("${_remote_branches[@]:-}")
          fi

          local _first=1

          local __selected_branch=
          for   __selected_branch in "${_selected_branches[@]:-}"
          do
            local _target_notebook_name=

            if _contains "${__selected_branch:-}" "main" "master"
            then
              _target_notebook_name="${_remote_url##*/}"
            else
              _target_notebook_name="${__selected_branch:-}"
            fi

            local _target_notebook_path=
            _target_notebook_path="$(
              _get_unique_path "${NB_DIR}/${_target_notebook_name}"
            )"

            _target_notebook_name="${_target_notebook_path##*/}"

            if ((_first))
            then
              _first=0
            else
              _print_line "------------------------------------"
            fi

            local _bk_name=  && _bk_name="$(_color_brackets "${_target_notebook_name}")"
            local _hi_enter= && _hi_enter="$(_color_primary 'enter')"
            local _hi_q=     && _hi_q="$(_color_primary 'q')"
            local _hi_type=  && _hi_type="$(_color_primary 'type')"

            cat <<HEREDOC
Press ${_hi_enter} to use the selected name, ${_hi_type} a new name, or press ${_hi_q} to quit.

HEREDOC

            while true
            do
              local _target_notebook_prompt_response=

              IFS='' read -r -e -d $'\n' -p \
                "Name ${_bk_name}: "        \
                _target_notebook_prompt_response

              case "${_target_notebook_prompt_response:-}" in
                '')
                  break
                  ;;
                q*|exit)
                  printf "Exiting%s\\n" "$(_color_muted "...")"

                  exit 0
                  ;;
                *)
                  _target_notebook_name="${_target_notebook_prompt_response}"

                  break
                  ;;
              esac
            done

            local _unique_notebook_path=
            _unique_notebook_path="$(
              _get_unique_path "${NB_DIR}/${_target_notebook_name:-}"
            )"

            _name="${_unique_notebook_path##*/}"

            _notebooks_validate_name "${_name}" || return 1

            git clone "${_git_options[@]:-}"    \
              "${_remote_url}"                  \
              --branch "${__selected_branch:-}" \
              "${NB_DIR}/${_name}"              &&
              printf "Added notebook: %s\\n" "$(_color_primary "${_name}")"
          done && return 0
        fi
      fi
    else
      mkdir -p "${NB_DIR}/${_name}"                   &&
        git -C "${NB_DIR}/${_name}" init &>/dev/null  &&
        {
          if ((_author))
          then
            _author_arguments+=("${NB_DIR}/${_name}")
            _notebooks author "${_author_arguments[@]:-}"
          fi
        }                                             &&
        touch "${NB_DIR}/${_name}/.index"             &&
        _temp cache clear                             &&
        _git checkpoint "${NB_DIR}/${_name}" "[${_ME}] Initialize"
      fi                            &&
        ((_print_default_feedback)) &&
        printf "Added notebook: %s\\n" "$(_color_primary "${_name}")"
  }

  # Usage: _notebooks_add_new [<notebook>...]
  _notebooks_add_new() {
    local _notebook_list=("${@:-}")

    [[ ! -d "${NB_DIR}" ]] && return 0

    if [[ -z "${1:-}"   ]]
    then
      _notebook_list=($(ls -1 "${NB_DIR}"))
    fi

    local __notebook_name=
    for   __notebook_name in "${_notebook_list[@]:-}"
    do
      if [[   -d "${NB_DIR}/${__notebook_name}"         ]]  &&
         [[ ! -e "${NB_DIR}/${__notebook_name}/.index"  ]]
      then
        {
          if ((_GIT_ENABLED))
          then
            git -C "${NB_DIR}/${__notebook_name}" init &>/dev/null
          fi
        } && touch "${NB_DIR}/${__notebook_name}/.index"    &&
        _temp cache clear                                   &&
        _git checkpoint "${NB_DIR}/${__notebook_name}" "[${_ME}] Initialize"
      fi
    done
  }

  # _notebooks_author()
  #
  # Usage:
  #   _notebooks_author [--name [<name>]] [--email [<email>]] [--unset]
  #                     [<notebook-path>]
  #
  # Description:
  #   Print, set, and delete the <email> and <name> for git commit attribution
  #   within the notebook.
  _notebooks_author() {
    local _email=0
    local _name=0
    local _new_local_email=
    local _new_local_name=
    local _print_current=0
    local _selector=
    local _skip_prompt=0
    local _unset=0

    while ((${#}))
    do
      case "${1:-}" in
        --email)
          _email=1

          if _option_value_is_present "${2:-}"
          then
            _new_local_email="${2:-}"

            shift
          fi
          ;;
        -f|--force|--skip*|-y|--yes)
          _skip_prompt=1
          ;;
        --name)
          _name=1

          if _option_value_is_present "${2:-}"
          then
            _new_local_name="${2:-}"

            shift
          fi
          ;;
        --print|--current)
          _print_current=1
          ;;
        --unset)
          _unset=1
          ;;
        *)
          if [[ -z "${_selector:-}"     ]]
          then
            _selector="${1:-}"
          fi
          ;;
      esac

      shift
    done

    local _notebook_path=

    if   [[ "${_selector:-}" =~ ^/      ]]
    then
      _notebook_path="${_selector:-}"
    elif [[ "${_selector:-}" == "local" ]]
    then
      _notebook_path="$(_notebooks_current --local --path || :)"
    elif [[ -n "${_selector:-}"         ]]
    then
      _notebook_path="${NB_DIR}/${_selector%%:*}"
    fi

    if [[ -z "${_notebook_path:-}"            ]]
    then
      _notebook_path="$(_notebooks_current --path)"
    fi

    if [[ "${_notebook_path:-}" =~ ^${NB_DIR} ]]
    then
      local _notebook_name="${_notebook_path##*/}"
    else
      local _notebook_name="local"
    fi

    local _global_email=
    _global_email="$(
      git -C "${_notebook_path:-}" config --global --includes user.email || :
    )"

    local _global_name=
    _global_name="$(
      git -C "${_notebook_path:-}" config --global --includes user.name  || :
    )"

    local _local_email=
    _local_email="$(
      git -C "${_notebook_path:-}" config --local user.email  || :
    )"

    local _local_name=
    _local_name="$(
      git -C "${_notebook_path:-}" config --local user.name   || :
    )"

    if ((_unset))
    then
      local _unset_output_present=0

      if [[ -n "${_local_email:-}"  ]] && {
           ((_email)) || ! ((_name))
         }
      then
        _warn printf "Unsetting local email.\\n"
        git -C "${_notebook_path:-}" config --unset user.email  || :
        _unset_output_present=1
      fi

      if [[ -n "${_local_name:-}"   ]] && {
           ((_name))  || ! ((_email))
         }
      then
        _warn printf "Unsetting local name.\\n"
        git -C "${_notebook_path:-}" config --unset user.name   || :
        _unset_output_present=1
      fi

      ((_unset_output_present)) && printf "\\n"

      printf "Updated author for: %s\\n" "$(
        _color_primary "${_notebook_name}"
      )"

      _print_line "-------------------"

      _notebooks_author "${_notebook_path}" --current

      return 0
    elif ((_print_current))
    then
      printf "%s" "$(_color_primary "email")"

      if [[ -n "${_local_email:-}"        ]]
      then
        printf " (%s):  %s\\n" "$(_color_primary "local")" "${_local_email:-}"
      else
        printf " (%s): %s\\n" "$(_color_primary "global")" "${_global_email:-}"
      fi

      printf "%s" "$(_color_primary "name")"

      if [[ -n "${_local_name:-}"         ]]
      then
        printf "  (%s):  %s\\n" "$(_color_primary "local")" "${_local_name:-}"
      else
        printf "  (%s): %s\\n" "$(_color_primary "global")" "${_global_name:-}"
      fi

      return 0
    else
      printf "Current author for: %s\\n" "$(
        _color_primary "${_notebook_name}"
      )"

      _print_line "-------------------"

      _notebooks_author "${_notebook_path}" --current

      if [[ -n "${_new_local_email:-}"    ]] || [[ -n "${_new_local_name:-}" ]]
      then
        printf    "\\nUpdate:\\n"
        _print_line  "-------"

        if [[ -n "${_new_local_email:-}"  ]]
        then
          printf "local %s: %s\\n" "$(_color_primary "email")" "${_new_local_email:-}"
        fi

        if [[ -n "${_new_local_name:-}"   ]]
        then
          printf "local %s:  %s\\n" "$(_color_primary "name")" "${_new_local_name:-}"
        fi
      fi

      if ! ((_skip_prompt))
      then
        while true
        do
          local __yn=
          IFS='' read -r -e -d $'\n' -p   \
"${_NEWLINE}$(_color_primary "Update?")  $(_color_brackets "y/N") " __yn

          case "${__yn}" in
            [Yy]*)
              break
              ;;
            *)
              printf "Exiting%s\\n" "$(_color_muted "...")"

              exit 0
              ;;
          esac
        done

        if [[ -z "${_new_local_email:-"${_new_local_name:-}"}" ]]
        then
          local _unset=
          _unset=$(_color_primary "unset")

          cat <<HEREDOC

Enter a new value, ${_unset} to use the global value,
or leave blank to keep the current value.

HEREDOC

          IFS='' read -r -e -d $'\n' -p             \
"local $(_color_primary "email:") " _new_local_email

          IFS='' read -r -e -d $'\n' -p             \
"local $(_color_primary "name:")  " _new_local_name
        fi
      fi

      if [[ -n "${_new_local_email:-}"    ]]
      then
        if _contains "${_new_local_email:-}" "global" "--unset" "unset"
        then
          git -C "${_notebook_path:-}" config --unset user.email  || :
        else
          git -C "${_notebook_path}" config --local \
            user.email "${_new_local_email:-}"
        fi
      fi

      if [[ -n "${_new_local_name:-}"     ]]
      then
        if _contains "${_new_local_name:-}" "global" "--unset" "unset"
        then
          git -C "${_notebook_path:-}" config --unset user.name   || :
        else
          git -C "${_notebook_path}" config --local \
            user.name "${_new_local_name:-}"
        fi
      fi

      if [[ -n "${_new_local_email:-"${_new_local_name:-}"}" ]]   || ! ((_skip_prompt))
      then
        printf "\\nUpdated author for: %s\\n" "$(
          _color_primary "${_notebook_name}"
        )"

        _print_line "-------------------"

        _notebooks_author "${_notebook_path}" --current
      fi
    fi
  }

  # _notebooks_current()
  #
  # Usage:
  #   _notebooks_current (<name> | <path> | <selector>) [--global | --local]
  #                      [--path | --scoped] [--filename]
  _notebooks_current() {
    local _file_path=
    local _print_global=0
    local _print_local=0
    local _print_path=0
    local _print_unique_file_path=0
    local _return_selected=0
    local _selector=

    while ((${#}))
    do
      case "${1:-}" in
        --global)
          _print_global=1
          ;;
        --local)
          _print_local=1
          ;;
        --path*)
          _print_path=1
          ;;
        --scoped|--selected)
          _return_selected=1
          ;;
        --filename|--basename|--file*path)
          _print_unique_file_path=1

          if _option_value_is_present "${2:-}"
          then
            _file_path="${2}"

            shift
          fi
          ;;
        [^-]*)
          _selector="${1}"
          ;;
      esac

      shift
    done

    if [[ -n "${_selector:-}" ]]
    then
      _notebooks_select "${_selector}" || :
    fi

    if ((_print_local))
    then
      if [[ -n "${_LOCAL_NOTEBOOK_PATH:-}" ]]
      then
        if ((_print_path))
        then
          printf "%s\\n" "${_LOCAL_NOTEBOOK_PATH}"
        else
          return 0
        fi
      else
        return 1
      fi
    elif ((_print_global))
    then
      if ((_print_path))
      then
        printf "%s\\n" "${_GLOBAL_NOTEBOOK_PATH}"
      else
        basename "${_GLOBAL_NOTEBOOK_PATH}"
      fi
    elif ((_print_path))
    then
      printf "%s\\n" "${NB_NOTEBOOK_PATH}"
    elif ((_return_selected))
    then
      [[ "${NB_NOTEBOOK_PATH}" != "${_GLOBAL_NOTEBOOK_PATH}" ]] &&
      [[ "${NB_NOTEBOOK_PATH}" != "${_LOCAL_NOTEBOOK_PATH}"  ]]
    elif ((_print_unique_file_path))
    then
      _notebooks_show "${NB_NOTEBOOK_PATH}" --filename "${_file_path:-}"
    else
      if [[ -n "${_LOCAL_NOTEBOOK_PATH:-}"                      ]] &&
         [[ "${NB_NOTEBOOK_PATH}" == "${_LOCAL_NOTEBOOK_PATH}"  ]]
      then
        printf "local\\n"
      else
        basename "${NB_NOTEBOOK_PATH}"
      fi
    fi
  }

  # _notebooks_delete()
  #
  # Usage:
  #   _notebooks_delete <name>
  _notebooks_delete() {
    local _force=0
    local _name=

    local __arg=
    for   __arg in "${@:-}"
    do
      case "${__arg}" in
        -f|--force|--skip*|-y|--yes)
          _force=1
          ;;
        *)
          [[ -z "${_name:-}"  ]] && _name="${__arg%%:*}"
          ;;
      esac
    done

    if [[   -z  "${_name}"    ]]
    then
      _exit_1 _help notebooks
    elif [[     "${_name}"    == "local"    ]] &&
         [[ -n  "${_LOCAL_NOTEBOOK_PATH:-}" ]]
    then
      _exit_1 cat <<HEREDOC
Use your system's shell or file explorer to delete local notebook directories.
HEREDOC
    fi

    _notebooks_validate_name "${_name}"

    if [[ ! -d "${NB_DIR}/${_name}"         ]] ||
       [[ ! -e "${NB_DIR}/${_name}/.git"    ]] ||
       [[ ! -e "${NB_DIR}/${_name}/.index"  ]]
    then
      _exit_1 printf "Notebook not found: %s\\n" "$(_color_primary "${_name}")"
    fi

    local _notebook_names=()
    _notebook_names=($(_notebooks --names --no-color))

    local _notebook_count=
    _notebook_count="${#_notebook_names[@]}"

    if ! ((_force))
    then
      if _command_exists "trash" && [[ "${OSTYPE}" =~ ^darwin ]]
      then
        printf "Moving to Trash: %s\\n" "$(_color_primary "${_name}")"
      else
        cat <<HEREDOC
Deleting $(_color_primary "${_name}").

This action cannot be undone. This will permanently delete the
$(_color_primary "${_name}") notebook, all notes and files it contains,
and the entire revision history.

HEREDOC
      fi

      while true
      do
        local __response=
        IFS='' read -r -e -d $'\n' -p \
"Please type $(_color_primary "${_name}") to confirm: " __response

        if [[ "${__response}"     == "${_name}"   ]]
        then
          break
        else
          printf "Exiting%s\\n" "$(_color_muted "...")"

          exit 0
        fi
      done
    fi

    if [[ "$(_notebooks current)" ==  "${_name}"  ]] &&
       [[ "${_notebook_count}"    -gt 1           ]]
    then
      if [[ "${_name}" != "home"  ]]
      then
        _notebooks use "home"
      else
        local __notebook=
        for   __notebook in "${_notebook_names[@]:-}"
        do
          if [[ "${__notebook}"   !=    "$(_notebooks current)"   ]]
          then
            _notebooks use "${__notebook}"

            break
          fi
        done
      fi
    fi

    if _command_exists "trash"    &&    [[ "${OSTYPE}" =~ ^darwin ]]
    then
      trash "${NB_DIR:?}/${_name:?}"
    else
      if [[ -e "${NB_DIR:?}/${_name:?}" ]]
      then
        rm -r -f "${NB_DIR:?}/${_name:?}"
      fi
    fi &&
      _temp cache clear &&
      printf "Notebook deleted: %s\\n" "$(_color_primary "${_name}")"
  }

  # _notebooks_export()
  #
  # Usage:
  #   _notebooks_export <name> [<path>]
  _notebooks_export() {
    local _name="${1:-}"

    if [[ -z "${_name:-}"           ]]
    then
      _exit_1 _help "notebooks"
    fi

    _notebooks_validate_name "${_name}"

    if [[ ! -d "${NB_DIR}/${_name}" ]]
    then
      _exit_1 printf "Notebook not found: %s\\n" "$(_color_primary "${_name}")"
    fi

    local _target_path="${2:-}"

    if [[ -n "${_target_path:-}"    ]] && [[ ! "${_target_path}" =~ ^/ ]]
    then
      _target_path="${_CURRENT_WORKING_DIR}/${_target_path}"
    fi

    if [[ -n "${_target_path:-}"              ]] &&
       [[ -d "${_target_path}"                ]] &&
       [[ ! "${_target_path}" =~ \/${_name}$  ]]
    then
      _target_path="${_target_path}/${_name}"
    fi

    if [[ -z "${_target_path}"      ]]
    then
      _target_path="${_CURRENT_WORKING_DIR}/${_name}"
    fi

    _target_path="$(_get_unique_path "${_target_path}")"

    cp -R "${NB_DIR}/${_name}" "${_target_path}"  &&
      _temp cache clear                           &&
      printf "Exported notebook %s to %s\\n"  \
        "$(_color_primary "${_name}")"        \
        "$(_color_primary "${_target_path}")"
  }

  # _notebooks_import()
  #
  # Usage:
  #   _notebooks_import <path> [<name>]
  _notebooks_import() {
    local _path="${1:-}"

    if [[ -z "${_path:-}"     ]]
    then
      _exit_1 _help "notebooks"
    fi

    local _basename=
    _basename="$(basename "${_path}")"

    if [[ ! "${_path}" =~ ^/  ]]
    then
      _path="${_CURRENT_WORKING_DIR}/${_path}"
    fi

    if [[ ! -d "${_path}"     ]]
    then
      _exit_1 printf "Not a directory: %s" "$(_color_primary "${_path}")"
    fi

    local _target_basename="${2:-}"

    if [[   -z "${_target_basename:-}"  ]]
    then
      _target_basename="${_basename}"
    fi

    _notebooks_validate_name "${_target_basename}"

    local _target_path=
    _target_path="$(_get_unique_path "${NB_DIR}/${_target_basename}")"

    cp -R "${_path}" "${_target_path}"  &&
      _temp cache clear                 &&
      _notebooks_add_new                &&
      printf "Imported notebook: %s\\n" \
        "$(_color_primary "$(basename "${_target_path}")")"
  }

  # _notebooks_init()
  #
  # Usage:
  #   _notebooks_init [<path> [<remote_url> [<branch>]]
  _notebooks_init() {
    local _author=0
    local _author_arguments=()
    local _path=
    local _remote_branch=
    local _remote_url=
    local _skip_prompt=0

    while ((${#}))
    do
      case "${1:-}" in
        --author) _author=1 ;;
        --email|--name)
          _author=1
          _author_arguments+=("${1:-}")

          if _option_value_is_present "${2:-}"
          then
            _author_arguments+=("${2:-}")

            shift
          fi
          ;;
        -f|--force|--skip*|-y|--yes)
          _skip_prompt=1
          ;;
        *)
          if _string_is_url "${1:-}"    && [[ -z "${_remote_url:-}" ]]
          then
            _remote_url="${1:-}"
          elif [[ -z "${_path:-}"   ]]  && [[ -z "${_remote_url:-}" ]]
          then
            _path="${1:-}"
          else
            _remote_branch="${1:-}"
          fi
          ;;
      esac

      shift
    done

    if [[ -n "${_remote_url:-}"     ]]  && [[ -z "${_path}"         ]]
    then
      _exit_1 printf                                                    \
        "Must specify a <path> when cloning from <remote-url>.\\n%s\\n" \
        "$(_help "notebooks")"
    fi

    if [[   -n "${_path:-}"         ]]
    then
      if [[ !   "${_path}" =~ ^/    ]]
      then
        _path="${_CURRENT_WORKING_DIR}/${_path}"
      fi
    else
      _path="${_CURRENT_WORKING_DIR}"
    fi

    if [[ -d "${_path}"             ]]  &&
       [[ -e "${_path}/.git"        ]]
    then
      local _error_message=

      if [[ -f "${_path}/.index"    ]]
      then
        _error_message="Notebook exists: $(_color_primary "${_path}")"
      else
        _error_message="Git repository exists: $(_color_primary "${_path}")"
      fi

      _exit_1 printf "%s\\n" "${_error_message}"
    fi

    if [[ ! -e "${_path}"           ]]
    then
      mkdir -p "${_path}"
    elif [[ "${HOME}" =~ ^${_path}  ]]
    then
      _exit_1 printf                                                    \
        "Unable to turn top-level directory into local notebook: %s\\n" \
        "$(_color_primary "${_path}")"
    elif [[ -f "${_path}"           ]]
    then
      _exit_1 printf "File exists: %s\\n" "$(_color_primary "${_path}")"
    elif [[ -d "${_path:-}"         ]]
    then
      printf "Directory exists: %s\\n" "$(_color_primary "${_path}")"

      if [[ -n "${_remote_url:-}"   ]]
      then
        _exit_1 printf "Unable to clone to existing directory.\\n"
      else
        local _git_repository_count=0
        _git_repository_count="$(
          find "${_path}" -name .git -prune | wc -l | awk '$1=$1'
        )"

        if ((_git_repository_count))
        then
          _warn printf "This directory contains %s git repositories.\\n" \
            "$(_color_primary "${_git_repository_count}")"
        fi

        if ! ((_skip_prompt))
        then
          while true
          do
            local __yn=
            IFS='' read -r -e -d $'\n' -p \
              "Initialize directory as a local notebook? $(_color_brackets "y/N") " __yn

            case "${__yn}" in
              [Yy]*)
                break
                ;;
              *)
                printf "Exiting%s\\n" "$(_color_muted "...")"

                exit 0
                ;;
            esac
          done
        fi
      fi
    fi

    if [[ "${_path}" != "${_CURRENT_WORKING_DIR}" ]] &&
       [[ -n "${_remote_url:-}"                   ]]
    then
      if [[ -n "${_remote_branch:-}"      ]]
      then
        git clone --no-local --single-branch --branch "${_remote_branch:-}" \
          "${_remote_url}"                                                  \
          "${_path}"
      else
        git clone --no-local --single-branch "${_remote_url}" "${_path}"
      fi
    else
      git -C "${_path}" init &>/dev/null  &&
        {
          if ((_author))
          then
            _author_arguments+=("${_path}")
            _notebooks author "${_author_arguments[@]:-}"
          fi
        } &&
        touch "${_path}/.index"           &&
        _git checkpoint "${_path}" "[${_ME}] Initialize"
    fi

    printf "Initialized local notebook: %s\\n" "$(_color_primary "${_path}")"
  }

  # _notebooks_list()
  #
  # Usage:
  #   _notebooks_list [<name> | <query>] [--ar | --archived] [--local]
  #                   [--global] [--names] [--paths] [--unar | --unarchived]
  _notebooks_list() {
    local _counter=0
    local _notebook_color_enabled="${_COLOR_ENABLED}"
    local _notebook_names=()
    local _notebook_paths=()
    local _only_archived=0
    local _only_global=0
    local _only_local=0
    local _only_names=0
    local _only_paths=0
    local _only_unarchived=0
    local _options=()
    local _query_names=()

    local __arg=
    for   __arg in "${@:-}"
    do
      case "${__arg}" in
        --archived|--global|--local|--name*|--no*color|--path*|--unarchived)
          _options+=("${__arg}")
          ;;
      esac

      case "${__arg}" in
        --ar|--archived)
          _only_archived=1
          ;;
        --global)
          _only_global=1
          ;;
        --local)
          _only_local=1
          ;;
        --name*)
          _only_names=1
          ;;
        --no*color)
          _notebook_color_enabled=0
          ;;
        --path*)
          _only_paths=1
          ;;
        --unar|--unarchived)
          _only_unarchived=1
          ;;
        *)
          _query_names+=("${__arg}")
          ;;
      esac
    done

    if [[ -z "${NB_DIR}" ]] || [[ ! -e "${NB_DIR}"  ]]
    then
      exit 1
    fi

    _current_notebook_name="$(_notebooks current --name)"

    if [[ -z "${_query_names[*]:-}"         ]]
    then
      _notebook_names=($(ls -1 "${NB_DIR}"))

      _notebooks_add_new "${_notebook_names[@]:-}"

      set +f
      _notebook_paths=($(ls -1 -d "${NB_DIR}"/*))
      set -f

      if [[ -n "${_LOCAL_NOTEBOOK_PATH:-}"  ]]
      then
        _notebook_names=("local" "${_notebook_names[@]:-}")
        _notebook_paths=("${_LOCAL_NOTEBOOK_PATH}" "${_notebook_paths[@]:-}")
      fi
    else
      _notebooks_add_new

      local __name=
      for   __name in "${_query_names[@]}"
      do
        __name="${__name%:}"

        _notebook_names+=("${__name}")

        if [[ "${__name}" == "local"        ]]
        then
          _notebook_paths+=("${_LOCAL_NOTEBOOK_PATH}")
        else
          _notebook_paths+=("${NB_DIR}/${__name}")
        fi
      done
    fi

    local i=
    for ((i=0; i < ${#_notebook_names[@]}; i++))
    do
      if [[ -e "${_notebook_paths[i]}/.git"                 ]]
      then # it's a git repository.
        local _notebook_line=
        local _origin_url=

        if [[     "${i}"                        == "0"      ]]  &&
           [[     "${_notebook_names[i]:-}"     == "local"  ]]  &&
           [[ -n  "${_LOCAL_NOTEBOOK_PATH:-}"               ]]
        then # local notebook as first notebook
          if ((_only_global))
          then
            continue
          else
            if ((_only_paths))
            then
              _notebook_line="${_notebook_paths[i]}"
            elif ((_notebook_color_enabled))                    &&
                 [[ "${_current_notebook_name}" == "local"  ]]
            then
              _notebook_line="$(_color_primary "local" --underline)"
            else
              _notebook_line="local"
            fi
          fi
        elif ((_only_local))
        then
          if [[ -z "${_LOCAL_NOTEBOOK_PATH:-}"      ]]
          then
            return 1
          else
            continue
          fi
        else
          if ((_only_paths))
          then
            _notebook_line="${_notebook_paths[i]}"
          elif ! ((_notebook_color_enabled))
          then
            _notebook_line="${_notebook_names[i]}"
          else
            if [[ "${_current_notebook_name}" == "${_notebook_names[i]}" ]]
            then # it's the current repository.
              _notebook_line="$(_color_primary "${_notebook_names[i]}")"

              if [[ "${#_notebook_names[@]}" -gt 1  ]]
              then
                _notebook_line="$(
                  _color_primary "${_notebook_names[i]}" --underline
                )"
              fi
            else
              _notebook_line="${_notebook_names[i]}"
            fi
          fi
        fi

        if [[ -e "${_notebook_paths[i]}/.archived"  ]]
        then
          if ((_only_unarchived))
          then
            continue
          elif ! ((_only_names)) && ! ((_only_paths))
          then
            _notebook_line="${_notebook_line} (archived)"
          fi
        elif ((_only_archived))
        then
          continue
        fi

        if ! ((_only_names)) && ! ((_only_paths))
        then
          _origin_url="$(
            git -C "${_notebook_paths[i]}" config --get remote.origin.url || echo ''
          )"

          if [[ -n "${_origin_url:-}"   ]]
          then
            _notebook_line="${_notebook_line} (${_origin_url})"
          fi
        fi

        if [[ -n "${_notebook_line:-}"  ]]
        then
          printf "%s\\n" "${_notebook_line:-}"

          _counter=$((_counter+1))
        fi
      fi
    done

    if ! ((_counter))
    then
      if [[ -n "${_query_names[*]:-}"   ]]
      then
        {
          local _query_pattern=
          _query_pattern="$(_join "|" "${_query_names[@]:-}")"

          {
            _notebooks_list "${_options[@]:-}"  2>/dev/null
          } | {
            grep -i "${_query_pattern:-}"       2>/dev/null
          }
        } || {
          _warn printf                  \
            "Notebook not found: %s\\n" \
            "$(_color_primary "${_query_names[*]}" | tr '\r\n' ' ')" &&
              return 1
        }
      else
        return 1
      fi
    fi
  }

  # _notebooks_notebook()
  #
  # Usage:
  #   _notebooks_notebook [archive | open | peek | status | unarchive] <name>
  _notebooks_notebook() {
    local _notebook_name="${2%:}"
    local _notebook_path=
    local _subcommand="${1:-}"

    if [[ -n "${_notebook_name:-}"  ]]
    then
      _notebooks_validate_name "${_notebook_name}"

      _notebook_path="$(_notebooks "${_notebook_name}" --path)"
    else
      _notebook_name="$(_notebooks current)"
      _notebook_path="$(_notebooks current --path)"
    fi

    if [[ -z "${_notebook_name:-}"  ]]
    then
      _exit_1 printf "Unable to determine notebook name.\\n"
    fi

    if [[ -z "${_notebook_path:-}"  ]]
    then
      _exit_1 printf "Unable to determine notebook path.\\n"
    fi

    if [[ -z "${_subcommand}"       ]]
    then
      printf "%s\\n" "${_notebook_name}"

      return 0
    fi

    if [[ "${_subcommand:-}"    =~ (^open$|^o$) ]]
    then
      if _open_in_gui_app "${_notebook_path:-}"
      then
        return 0
      else
        _exit_1 printf                                                  \
          "%s doesn't know how to open directories on this system.\\n"  \
          "$(_color_primary "${_ME}")"
      fi
    elif [[ "${_subcommand:-}"  =~ (^peek$|^p$) ]]
    then
      if [[ -n "${NB_DIRECTORY_TOOL:-}" ]]
      then
        "${NB_DIRECTORY_TOOL}" "${_notebook_path}"
      elif _command_exists "ranger"
      then
        ranger "${_notebook_path}"
      elif _command_exists "mc"
      then
        mc "${_notebook_path}"
      elif _command_exists "vifm"
      then
        vifm "${_notebook_path}"
      elif _command_exists "exa"
      then
        exa -lah --git "${_notebook_path}"
      else
        # gnu || bsd
        ls -lah --color=always "${_notebook_path}" 2>/dev/null ||
          ls -lah -G "${_notebook_path}"
      fi
    else
      local _dotfile_path="${_notebook_path}/.archived"

      if [[   "${_subcommand}" == "archive"   ]]
      then
        if [[ ! -e "${_dotfile_path}"         ]]
        then
          touch "${_dotfile_path}" &&
            _git checkpoint "${_notebook_path}" "[${_ME}] Archived"
        fi

        printf "%s archived.\\n" "$(_color_primary "${_notebook_name}")"
      elif [[ "${_subcommand}" == "status"    ]]
      then
        if [[   -e "${_dotfile_path}"         ]]
        then
          printf "%s is archived.\\n" "$(_color_primary "${_notebook_name}")"
        else
          printf "%s is not archived.\\n" "$(_color_primary "${_notebook_name}")"
        fi
      elif [[ "${_subcommand}" == "unarchive" ]]
      then
        if [[   -e "${_dotfile_path}"         ]]
        then
          rm "${_dotfile_path:?}" &&
            _git checkpoint "${_notebook_path}" "[${_ME}] Unarchived"
        fi

        printf "%s unarchived.\\n" "$(_color_primary "${_notebook_name}")"
      fi
    fi
  }

  # _notebooks_rename()
  #
  # Usage:
  #   _notebooks_rename <old> <new>
  _notebooks_rename() {
    local _new="${2:-}"
    local _old="${1:-}"

    _notebooks_validate_name "${_old}"
    _notebooks_validate_name "${_new}"

    if [[ -z "${_old}" ]] || [[ -z "${_new}"  ]]
    then
      _exit_1 _help notebooks
    elif [[ -n "${_LOCAL_NOTEBOOK_PATH:-}"    ]]
    then
      if [[ "${_old}" == "local" ]] || [[ "${_new}" == "local" ]]
      then
        _exit_1 cat <<HEREDOC
"local" refers to the local notebook and can not be renamed.
HEREDOC
      fi
    elif [[ ! -d "${NB_DIR}/${_old}"  ]]
    then
      _exit_1 printf "%s is not a valid notebook name.\\n"        \
        "$(_color_primary "${_old}")"
    elif [[ -e "${NB_DIR}/${_new}"    ]]
    then
      _exit_1 printf "A notebook named \"%s\" already exists.\\n" \
        "$(_color_primary "${_new}")"
    fi

    mv "${NB_DIR}/${_old}" "${NB_DIR}/${_new}"

    if [[ "$(cat "${NB_DIR}/.current")" == "${_old}" ]]
    then
      printf "%s\\n" "${_new}" > "${NB_DIR}/.current"
    fi

    _temp cache clear

    printf "%s is now named %s\\n"  \
      "$(_color_primary "${_old}")" \
      "$(_color_primary "${_new}")"
  }

  # _notebooks_select()
  #
  # Usage:
  #   _notebook_select <selector>
  _notebooks_select() {
    local _selector="${1:-}"

    if [[ -z "${_selector:-}"       ]]
    then
      _exit_1 _help "notebooks"
    fi

    local _notebook_path=
    _notebook_path="$(
      _notebooks_show "${_selector:-}" --path 2>/dev/null || :
    )"

    if [[ -n "${_notebook_path:-}"  ]] &&
       [[ -d "${_notebook_path:-}"  ]]
    then
      NB_NOTEBOOK_PATH="${_notebook_path}"

      return 0
    else
      return 1
    fi
  }

  # _notebooks_show()
  #
  # Usage:
  #   _notebooks_show (<name> | <path> | <selector>) [--archived]
  #                   [--escaped | --name | --path | --filename [<filename>]]
  _notebooks_show() {
    local _file_path=
    local _local_notebook_path="${_LOCAL_NOTEBOOK_PATH:-}"
    local _notebook_color_enabled=1
    local _notebook_path=
    local _only_name=0
    local _only_path=0
    local _print_escaped_name=0
    local _print_unique_file_path=0
    local _selector=
    local _test_archived=0

    while ((${#}))
    do
      case "${1:-}" in
        --archived)
          _test_archived=1
          ;;
        --escaped)
          _print_escaped_name=1
          ;;
        --name)
          _only_name=1
          ;;
        --no*color)
          _notebook_color_enabled=0
          ;;
        --path)
          _only_path=1
          ;;
        --filename|--basename|--file*path)
          _print_unique_file_path=1

          if _option_value_is_present "${2:-}"
          then
            _file_path="${2}"

            shift
          fi
          ;;
        *)
          if [[ -z "${_selector}"   ]]
          then
            _selector="${1:-}"
          fi
          ;;
      esac

      shift
    done

    if [[ -z "${_selector:-}"       ]]
    then
      _exit_1 _help "notebooks"
    elif [[ "${_selector:-}" =~ ^/  ]]
    then
      local _maybe_notebook_path="${_selector}"

      while [[ -n "${_maybe_notebook_path:-}"         ]] &&
            ! {
              [[ -d "${_maybe_notebook_path}/.git"    ]] &&
              [[ -f "${_maybe_notebook_path}/.index"  ]]
            } && {
              {
                [[    "${_maybe_notebook_path:-}"   =~ ^${NB_DIR}     ]]  &&
                [[ !  "${_maybe_notebook_path%/*}"  == "${NB_DIR}"    ]]
              } || {
                [[ !  "${_maybe_notebook_path:-}"   =~ ^${NB_DIR}     ]]
              }
            }
      do
        _maybe_notebook_path="${_maybe_notebook_path%/*}"
      done

      if [[ -n "${_maybe_notebook_path:-}"    ]]
      then
        if [[ -n "${_local_notebook_path:-}"                          ]] &&
           [[ "${_maybe_notebook_path}" == "${_local_notebook_path}"  ]]
        then
          _notebook_path="${_local_notebook_path%/}"
        else
          _notebook_path="${_maybe_notebook_path%/}"
        fi
      fi
    elif [[ -n "${_selector:-}"               ]]
    then
      local _selector_notebook="${_selector%%:*}"

      if [[ -n "${_selector_notebook:-}"      ]]
      then
        if [[ "${_selector_notebook:-}" == "local"  ]] &&
           [[ -n "${_local_notebook_path:-}"        ]]
        then
          _notebook_path="${_local_notebook_path%/}"
        elif [[ -e "${NB_DIR}/${_selector_notebook:-}/.git"    ]] &&
             [[ -f "${NB_DIR}/${_selector_notebook:-}/.index"  ]]
        then
          _notebook_path="${NB_DIR}/${_selector_notebook%/}"
        fi
      fi
    fi

    if [[ -z "${_notebook_path:-}"            ]]
    then
      _warn \
        printf "Notebook not found: %s\\n" "$(_color_primary "${_selector}")"

      return 1
    fi

    if ((_only_path))
    then
      printf "%s\\n" "${_notebook_path}"

      return 0
    fi

    if ((_test_archived))
    then
      if [[ -d "${_notebook_path}/.archived"  ]]
      then
        return 0
      else
        return 1
      fi
    fi

    if ((_print_unique_file_path))
    then
      _get_unique_relative_path "${_file_path:-".${NB_DEFAULT_EXTENSION}"}"

      return 0
    fi

    local _notebook_name=

    if [[   "${_notebook_path}"   == "${_LOCAL_NOTEBOOK_PATH:-}"  ]] ||
       [[ ! "${_notebook_path:-}" =~ ^${NB_DIR}                   ]]
    then
      _notebook_name="local"
    else
      _notebook_name="$(basename "${_notebook_path}")"
    fi

    if ((_only_name))
    then
      printf "%s\\n" "${_notebook_name}"

      return 0
    fi

    local _escaped_name="${_notebook_name}"

    if [[ "${_escaped_name}" =~ \         ]]
    then
      _escaped_name="$(
        printf "%s\\n" "${_escaped_name}" | LC_ALL=C sed -e "s/ /\\\ /g"
      )"
    fi

    if ((_print_escaped_name))
    then
      printf "%s\\n" "${_escaped_name:-}"

      return 0
    fi

    if ((_notebook_color_enabled))        &&
       [[ "${_notebook_path}" == "${NB_NOTEBOOK_PATH}"  ]]
    then
      _escaped_name="$(_color_primary "${_escaped_name}")"
    fi

    local _notebook_line="${_escaped_name}"

    if [[ -e "${_notebook_path}/.archived"              ]]
    then
      _notebook_line="${_notebook_line} (archived)"
    fi

    local _remote_url=
    _remote_url="$(
      git -C "${_notebook_path}" config --get remote.origin.url || echo ''
    )"

    if [[ -n "${_remote_url:-}"           ]]
    then
      _notebook_line="${_notebook_line} (${_remote_url})"
    fi

    printf "%s\\n" "${_notebook_line}"
  }

  # _notebooks_use()
  #
  # Usage:
  #   _notebooks_use <name>
  _notebooks_use() {
    local _name="${1%:}"

    if [[ -z "${_name}"                   ]]
    then
      _exit_1 _help notebooks
    fi

    _notebooks_validate_name "${_name}"

    if [[ -n "${_LOCAL_NOTEBOOK_PATH}"    ]]
    then
      _exit_1 cat <<HEREDOC
Currently in a local notebook. To run a command in a global notebook,
add the notebook name before the command name, separated by a colon:
  ${_ME} <notebook>:<command> [options...]

$(_color_primary "Examples"):
  ${_ME} home:list
  ${_ME} example:add --title "Example Title"
  ${_ME} example:search "sample query"
HEREDOC
    fi

    if [[ -e "${NB_DIR}/${_name}/.index"  ]]
    then
      printf "%s\\n" "${_name}" > "${NB_DIR}/.current"

      _GLOBAL_NOTEBOOK_PATH="${NB_DIR}/${_name}"
      NB_NOTEBOOK_PATH="${_GLOBAL_NOTEBOOK_PATH}"

      printf "Now using: %s\\n" "$(_color_primary "${_name}")"
    else
      _exit_1 printf "Not found: %s\\n" "$(_color_primary "${_name}")"
    fi
  }

  # Usage: _notebooks_validate_name <name>
  _notebooks_validate_name() {
    if _contains                                                \
      "$(printf "%s\\n" "${1:-}" | tr '[:upper:]' '[:lower:]')" \
      "${_RESERVED_NOTEBOOK_NAMES[@]}"
    then
      _warn printf "Name reserved: %s\\n" "$(_color_primary "${1:-}")"

      return 1
    else
      return 0
    fi
  }

  local _name="${2:-}"
  local _subcommand="${1:-}"

  if ! _contains "${_subcommand:-}" "add" "author" "current" "init" "list" "show"
  then
    _notebooks_add_new
  fi

  case "${_subcommand}" in
    a|add|create|new|+)
      shift

      _notebooks_add      "${@:-}"
      ;;
    author|config*)
      shift

      _notebooks_author   "${@:-}"
      ;;
    export)
      _notebooks_export   "${2:-}" "${3:-}"
      ;;
    import)
      _notebooks_import   "${2:-}" "${3:-}"
      ;;
    init)
      shift

      _notebooks_init     "${@:-}"
      ;;
    current)
      shift

      _notebooks_current  "${@:-}"
      ;;
    d|delete|remove|rm|trash|-)
      _notebooks_delete   "${_name:-}" "${3:-}"
      ;;
    list)
      shift

      _notebooks_list     "${@:-}"
      ;;
    rename|mv|move)
      _notebooks_rename   "${_name:-}" "${3:-}"
      ;;
    select)
      _notebooks_select   "${2:-}"
      ;;
    s|show)
      shift

      _notebooks_show     "${@:-}"
      ;;
    u|use)
      _notebooks_use      "${_name:-}"
      ;;
    archive|open|o|peek|p|status|unarchive)
      _notebooks_notebook "${_subcommand}" "${_name:-}"
      ;;
    *)
      _notebooks_list     "${@}"
      ;;
  esac
}
_alias_subcommand "notebooks" "n"
_alias_subcommand "notebooks" "nb"
_alias_subcommand "notebooks" "nbs"
_alias_subcommand "notebooks" "notebook"
_alias_subcommand "notebooks" "ns"

# subcommands · ################################################# · subcommands

_describe_subcommands() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} subcommands [add <name>...] [alias <name> <alias>]
                 [describe <name> <usage>]

$(_color_primary "Subcommands"):
  add       Add a new subcommand.
  alias     Create an <alias> of a given subcommand <name>, with linked help.
            Note that aliases must also be added with \`subcommands add\`.
  describe  Set the usage text displayed with \`${_ME} help <subcommand>\`.
            This can be assigned as a heredoc, which is recommended, or
            as a string argument.

$(_color_primary "Description"):
  List, add, alias, and describe subcommands. New subcommands, aliases, and
  descriptions are not persisted, so \`add\`, \`alias\`, \`describe\` are
  primarily for plugins.

$(_color_primary "Read More"):
  ${_README_URL}#-plugins

$(_color_primary "See Also"):
  ${_ME} help plugins
HEREDOC
}
_subcommands() {
  case "${1:-}" in
    add)
      if [[ -n "${2:-}" ]]
      then
        shift

        NB_PLUGIN_SUBCOMMANDS+=("${@:-}")
      fi
      ;;
    alias)
      if [[ -n "${2:-}" ]] &&
         [[ -n "${3:-}" ]]
      then
        _alias_subcommand "${2:-}" "${3:-}"
      fi
      ;;
    describe)
      shift

      describe "${@:-}"
      ;;
    *)
      printf "%s\\n" "${_DOCUMENTED_SUBCOMMANDS[*]}"
      ;;
  esac
}
_alias_subcommand "subcommands" "commands"

###############################################################################
# Plugins
###############################################################################

# $NB_PLUGIN_SUBCOMMANDS
#
# The list of subcommands exposed by plugins.
NB_PLUGIN_SUBCOMMANDS=()

# User defined plugins can be installed in the $NB_DIR/.plugins directory.
# Plugins have a .nb-plugin or .nb-theme extension and are written in a
# Bash-compatible shell scripting language.
#
# NOTE: Themes are loaded separately.
__load_plugins() {
  if [[ -d "${NB_DIR}/.plugins" ]]
  then
    set +f
    local __file=
    for   __file in "${NB_DIR}/.plugins"/*."${_ME}"-plugin*
    do
      [[ -f "${__file}"                           ]] || continue
      [[    "${__file}"  =~ /copy.${_ME}-plugin$  ]] && continue

      source "${__file}" 2>/dev/null || :
    done
    set -f
  fi
}; __load_plugins

###############################################################################
# Program Option Parsing
###############################################################################

# _normalize_options()
#
# Usage:
#   _normalize_options <option>...
#
# Description:
#   Iterate over options, breaking -ab into -a -b and --foo=bar into --foo bar
#   also turns -- into --endopts to avoid issues with things like '-o-', the
#   '-' should not indicate the end of options, but be an invalid option (or
#   the argument to the option, such as wget -qO-)
#
# Source:
#   https://github.com/e36freak/templates/blob/master/options
_NORMALIZED_OPTIONS=()
_normalize_options() {
  local _character=
  local _character_string=
  local _options=()

  while ((${#}))
  do
    case "${1}" in
      # if option is of type -ab
      -[!-]?*)
        if  [[ -n "${_options[*]:-}" ]]                 &&
            _contains "${_options[${#_options[@]}-1]}"  \
              "--append"                                \
              "--content"                               \
              "--overwrite"                             \
              "--prepend"                               \
              "add"                                     \
              "a"                                       \
              "+"                                       \
              "new"
        then
          _options+=("${1}")

          shift
        else
          # loop over each character starting with the second
          local i=
          for ((i=1; i < ${#1}; i++))
          do
            _character="${1:i:1}"
            _character_string+="${_character}"

            if [[ ! "${_character}"     =~ [0-9]  ]] ||
               [[ ! "${1:$((i + 1)):1}" =~ [0-9]  ]]
            then
              _options+=("-${_character_string}")
              _character_string=
            fi
          done

          shift
        fi
        ;;
      # if option is of type --foo=bar, split on first '='
      --?*=*)
        _options+=("${1%%=*}" "${1#*=}")

        shift
        ;;
      # end of options, stop breaking them up
      --)
        _options+=(--endopts)

        shift

        _options+=("${@}")

        break
        ;;
      # otherwise, nothing special
      *)
        _options+=("${1}")

        shift
        ;;
    esac
  done

  _NORMALIZED_OPTIONS=("${_options[@]}")
}; _normalize_options "${@:-}"

# set new positional parameters to altered options. Set default to blank.
set -- "${_NORMALIZED_OPTIONS[@]:-}"

# Usage: _print_normalized_options
_print_normalized_options() {
  printf "%s\\n" "${_NORMALIZED_OPTIONS[@]}"
}

# Parse Options ###############################################################

# Initialize program option variables.
_ARGUMENTS=()
_QUIET=0
_SUBCOMMAND=
_USE_DEBUG=0

# $_SUBCOMMANDS
#
# All available subcommands.
_SUBCOMMANDS=(
  a
  add
  ar
  archive
  b
  bk
  bm
  bookmark
  bookmarks
  br
  browse
  browser
  close
  commands
  completions
  config
  copy
  count
  create
  d
  delete
  "do"
  "done"
  duplicate
  e
  edit
  export
  env
  f
  folder
  folders
  git
  grep
  h
  help
  helpers
  history
  i
  import
  index
  init
  list
  ls
  move
  mv
  n
  nb
  nbs
  new
  notebook
  notebooks
  ns
  o
  open
  p
  peek
  pin
  plugin
  plugins
  preview
  q
  r
  remote
  rename
  reset
  rm
  run
  s
  search
  set
  settings
  shell
  show
  st
  stat
  status
  subcommands
  sync
  t
  task
  tasks
  trash
  to
  todo
  todos
  u
  unar
  unarchive
  undo
  undone
  unpin
  unset
  update
  upgrade
  use
  version
  view
  ${NB_PLUGIN_SUBCOMMANDS[@]:-}
)

# $_DOCUMENTED_SUBCOMMANDS
#
# Primary subcommands that appear in documentation. For example, some aliases
# are omitted from this list. This list is also used for tab completion.
_DOCUMENTED_SUBCOMMANDS=(
  +
  -
  add
  archive
  b
  bookmark
  browse
  commands
  completions
  copy
  count
  delete
  "do"
  edit
  export
  env
  folders
  git
  help
  history
  import
  init
  list
  ls
  move
  mv
  notebooks
  open
  peek
  pin
  plugins
  preview
  q
  remote
  rename
  run
  search
  set
  settings
  shell
  show
  st
  status
  subcommands
  sync
  tasks
  todo
  u
  unarchive
  undo
  unpin
  unset
  update
  use
  version
  ${NB_PLUGIN_SUBCOMMANDS[@]:-}
)

# $_GIT_SUBCOMMANDS
#
# Subcommands that initiate background cleanup commits and sync with remotes.
_GIT_SUBCOMMANDS=(
  a
  add
  ar
  archive
  b
  bk
  bm
  bookmark
  bookmarks
  br
  browse
  browser
  close
  copy
  count
  create
  d
  delete
  "do"
  "done"
  duplicate
  e
  edit
  export
  f
  folder
  folders
  grep
  i
  import
  list
  ls
  move
  mv
  n
  nb
  nbs
  new
  notebook
  notebooks
  ns
  o
  open
  p
  peek
  pin
  preview
  q
  rename
  rm
  s
  show
  search
  t
  task
  tasks
  to
  todo
  todos
  u
  unar
  unarchive
  undo
  undone
  unpin
  use
  view
  ${NB_PLUGIN_SUBCOMMANDS[@]:-}
)

# $_SUBCOMMANDS_PATTERN
#
# The contents of the `$_SUBCOMMANDS` array, joined with '|'.
_SUBCOMMANDS_PATTERN="^$(_join '$|^' "${_SUBCOMMANDS[@]}")$|^\+$|^\-$"

# $_GIT_SUBCOMMANDS_PATTERN
#
# The contents of the `$_GIT_SUBCOMMANDS` array, joined with '|'.
_GIT_SUBCOMMANDS_PATTERN="^$(_join '$|^' "${_GIT_SUBCOMMANDS[@]}")$|^\+$|^\-$"

# _is_valid_subcommand()
#
# Usage:
#   _is_valid_subcommand <name>
#
# Exit / Error / Return Status:
#   0 (success, true)  If the given <name> is a valid subcommand name.
#   1 (error,  false)  If not.
_is_valid_subcommand() {
  [[ -n "${1:-}" ]] &&  [[ "${1:-}" =~ ${_SUBCOMMANDS_PATTERN} ]]
}

# _parse_options()
#
# Usage:
#   _parse_options <option>...
#
# Description:
#   Parse program options.
_parse_options() {
  local _current_option=
  local _non_option_arguments=()
  local _previous_option=

  while ((${#}))
  do
    _previous_option="${_current_option:-}"

    _current_option="${1:-}"

    shift

    case "${_current_option}" in
      -)
        if [[ -z "${_SUBCOMMAND:-}"     ]]
        then
          _SUBCOMMAND="delete"
        else
          _ARGUMENTS+=("delete")
        fi
        ;;
      +)
        if [[ -z "${_SUBCOMMAND:-}"     ]]
        then
          _SUBCOMMAND="add"
        else
          _ARGUMENTS+=("add")
        fi
        ;;
      -h|--help)
        case "${_SUBCOMMAND:-}" in
          git|run)
            _ARGUMENTS+=("${_current_option}")
            ;;
          *)
            if [[ -n "${_SUBCOMMAND:-}" ]]
            then
              _ARGUMENTS+=("${_SUBCOMMAND}")
            fi

            _SUBCOMMAND="help"
            ;;
        esac
        ;;
      --debug)
        _USE_DEBUG=1
        ;;
      --no*color)
        _COLOR_ENABLED=0
        ;;
      --no*git|--skip*git)
        _GIT_ENABLED=0
        ;;
      --quiet)
        _QUIET=1
        ;;
      --version)
        if [[ -n "${_SUBCOMMAND:-}"     ]]
        then
          _ARGUMENTS+=("${_current_option}")
        else
          _SUBCOMMAND="version"
        fi
        ;;
      -i|--interactive)
        case "${_SUBCOMMAND:-}" in
          git|run)
            _ARGUMENTS+=("${_current_option}")
            ;;
          *)
            _SUBCOMMAND="shell"
            ;;
        esac
        ;;
      --welcome)
        _print_welcome
        ;;
      *:*)
        if [[ ! "${_current_option:-}"  =~ ^-         ]] &&
           [[ ! "${_previous_option:-}" =~ ^-         ]]
        then
          _non_option_arguments+=("${_current_option}")
        fi

        if [[ -z "${_SUBCOMMAND:-}"                   ]] &&
            _string_is_url "${_current_option}"
        then
          _SUBCOMMAND="bookmark"
          _ARGUMENTS+=("${_current_option}")
        elif _notebooks current --selected
        then
          _ARGUMENTS+=("${_current_option}")
        elif _contains "${_SUBCOMMAND:-"${1:-}"}" "copy" "move" "mv" "rename" &&
             (($((${#_non_option_arguments[@]} - 1))))
        then
          _ARGUMENTS+=("${_current_option}")
        elif [[ "${_SUBCOMMAND:-}" == "delete"        ]]
        then
          _ARGUMENTS+=("${_current_option}")
        elif _contains "${_previous_option:-}" "-r" "--related" "--via" "--also"
        then
          _ARGUMENTS+=("${_current_option}")
        else
          local _selector_suffix="${_current_option#*:}"

          if [[ -z "${_selector_suffix:-}"            ]] &&
             [[ -n "${_SUBCOMMAND:-}"                 ]] &&
             [[ ! "${_SUBCOMMAND}" =~ (^ls$|^list$)   ]]
          then
            _ARGUMENTS+=("${_current_option}")
          else
            if ! _notebooks select "${_current_option}"
            then
              if [[ -n "${_SUBCOMMAND:-}"             ]] ||
                 [[    "${_previous_option}" =~ ^-    ]]
              then
                _ARGUMENTS+=("${_current_option}")

                continue
              else
                _exit_1 printf                \
                  "Notebook not found: %s\\n" \
                  "$(_color_primary "${_current_option%%:*}")"
              fi
            fi

            if _is_valid_subcommand "${_selector_suffix}"
            then
              _SUBCOMMAND="${_selector_suffix}"
            else
              if _string_is_url "${_selector_suffix}"
              then
                _SUBCOMMAND="bookmark"
                _ARGUMENTS+=("${_selector_suffix}")
              elif [[ "${_selector_suffix}" =~ ^-   ]]
              then
                _ARGUMENTS+=("${_selector_suffix}")
              else
                _ARGUMENTS+=("${_current_option}")
              fi
            fi
          fi
        fi
        ;;
      --endopts)
        # Terminate option parsing.
        break
        ;;
      *)
        if [[     ! "${_previous_option}"   =~ ^-   ]]
        then
          if [[ -z "${_SUBCOMMAND:-}"               ]] &&
             _is_valid_subcommand "${_current_option}"
          then
            _SUBCOMMAND="${_current_option}"
          else
            if [[ ! "${_current_option:-}"  =~ ^-   ]]
            then
              _non_option_arguments+=("${_current_option}")
            fi

            _ARGUMENTS+=("${_current_option}")
          fi
        else
          _ARGUMENTS+=("${_current_option}")
        fi
        ;;
    esac
  done
}; _parse_options "${@:-}"

_debug printf "\${_SUBCOMMAND}:           '%s'\\n"  "${_SUBCOMMAND}"
_debug printf "\${NB_NOTEBOOK_PATH}:      '%s'\\n"  "${NB_NOTEBOOK_PATH}"
_debug printf "\${_LOCAL_NOTEBOOK_PATH}:  '%s'\\n"  "${_LOCAL_NOTEBOOK_PATH}"
_debug printf "\${_ARGUMENTS[*]:-}:       '%s'\\n"  "${_ARGUMENTS[*]:-}"

###############################################################################
# Deprecated Functions and Variables
#
# TODO: Remove
###############################################################################

# _get_notebook_identifier()
_get_notebook_identifier()  { _notebooks show "${@}" --escaped;   }

# _get_selection_basename()
_get_selection_basename()   { _show "${@}" --filename;            }

# _get_unique_basename()
_get_unique_basename()      { _get_unique_relative_path "${@:-}"; }

# _set_selection_notebook() <selector>
_set_selection_notebook()   {
  if [[ "${1:-}" =~ : ]]
  then
    if _notebooks select "${1:-}"
    then
      _NOTEBOOK_PATH="${NB_NOTEBOOK_PATH}"
    fi
  elif [[ "${_NOTEBOOK_PATH:-}" != "${NB_NOTEBOOK_PATH}" ]]
  then
    _NOTEBOOK_PATH="${NB_NOTEBOOK_PATH}"
  fi
}

# $_NOTEBOOK_PATH
# shellcheck disable=SC2034
export _NOTEBOOK_PATH="${_NOTEBOOK_PATH:-"${NB_NOTEBOOK_PATH}"}"

# $_SCOPE
# shellcheck disable=SC2034
# _SCOPE="$(_notebooks current --name)"
_SCOPE="$(basename "${NB_NOTEBOOK_PATH}")"

# $_SCOPED
# shellcheck disable=SC2034
_SCOPED="$(
  # if _notebooks current --selected
  if [[ "${NB_NOTEBOOK_PATH}" != "${_GLOBAL_NOTEBOOK_PATH}" ]]
  then
    printf "1\\n"
  else
    printf "0\\n"
  fi
)"

# color functions
_color_dim()          { _color_muted    "${@:-}"; }
_highlight()          { _color_primary  "${@:-}"; }
_id_brackets_color()  { _color_brackets "${@:-}"; }

###############################################################################
# _defer()
###############################################################################

# $_DEFERRED_COMMAND
#
# The function and arguments to run after the script has loaded.
_DEFERRED_COMMAND=()

# _defer()
#
# Usage:
#   _defer <name> [<argument>...]
#
# Description:
#   Assign a command to run after the script has loaded.
_defer() {
  _DEFERRED_COMMAND=("${@:-}")
}

# _call_deferred_command()
#
# Usage:
#   _call_deferred_command --group <num>
#
# Description:
#   Call the deferred command.
_call_deferred_command() {
  [[ -z "${_DEFERRED_COMMAND[0]:-}" ]] && exit 0

  local _group="${2:-}"
  local _group_3_names=(
    _ar _archive _b _bookmark _br _browse _browser _close _config _copy _do   \
    _done _duplicate _f _folder _folders _h _help _helpers _set _plugin       \
    _plugins _remote _reset _settings _shell _st _stat _status _sync _t _task \
    _tasks _to _todo _todos _unar _unarchive _undo _undone _unset _update     \
    _upgrade
  )

  if {
       [[ "${_group:-}" -eq 2 ]] &&
         _contains "${_DEFERRED_COMMAND[0]:-}" "${_group_3_names[@]}"
     } || {
       [[ "${_group:-}" -eq 3 ]] &&
       ! _contains "${_DEFERRED_COMMAND[0]:-}" "${_group_3_names[@]}"
     }
  then
    return 0
  else
    "${_DEFERRED_COMMAND[@]:-}"

    return 0
  fi
}

###############################################################################
# _main()
###############################################################################

# _main()
#
# Usage:
#   _main "$@"
#
# Description:
#   Primary entry point for the program logic. Call this function at the end
#   of the script after everything has been defined.
_main() {
  if [[ -z "${_SUBCOMMAND:-}" ]]
  then
    _SUBCOMMAND="ls"
  fi

  case "${_SUBCOMMAND}" in
    init|sync)
      _git required
      _defer "_${_SUBCOMMAND}" "${@:-}"
      ;;
    commands|completions|env|git|h|help*|r|run|set|settings|subcommands|update|version)
      _defer "_${_SUBCOMMAND}" "${@:-}"
      ;;
    *)
      _git required

      # Call `_init()` if configuration hasn't been initialized.
      if [[ ! -e "${NB_DIR}"            ]] ||
         [[ ! -e "${NB_NOTEBOOK_PATH}"  ]]
      then
        _init "${@:-}"

        _ls || true # returns 0 due to empty repository.

        return 0
      fi

      if [[ "${_SUBCOMMAND}" =~ ${_GIT_SUBCOMMANDS_PATTERN} ]]
      then
        if _git dirty "${NB_NOTEBOOK_PATH}"
        then
          _index reconcile

          _git checkpoint "${NB_NOTEBOOK_PATH}" --wait
        elif _git autosyncable "${NB_NOTEBOOK_PATH}" && _git out_of_sync
        then
          _git checkpoint "${NB_NOTEBOOK_PATH}" --wait
        fi
      fi

      if [[ "${_SUBCOMMAND}" == "ls" ]]
      then
        # Run `ls` on its own, exiting at the end in order to avoid running /
        # loading the rest of the script.
        "_${_SUBCOMMAND}" "${@}" --exit
      else
        # Defer subcommand call until the rest of the script has been loaded.
        _defer "_${_SUBCOMMAND}" "${@:-}"

        return 0
      fi
      ;;
  esac
}

_main "${_ARGUMENTS[@]:-}"

###############################################################################
# Configuration: Group 2                                 Configuration: Group 2
# ----------------------                                 ----------------------
###############################################################################
# --------------------------------------------------------------------------- #

# $NB_BROWSE_MARKDOWN_READER
#
# Default: 'markdown+emoji+raw_html+east_asian_line_breaks'
#
# The Pandoc reader, including extensions, to use for converting Markdown to
# HTML in `nb browse`.
#
# More information:
# https://pandoc.org/MANUAL.html#extensions
# https://pandoc.org/MANUAL.html#general-options-1
export NB_BROWSE_MARKDOWN_READER="${NB_BROWSE_MARKDOWN_READER:-"markdown+emoji+raw_html+east_asian_line_breaks"}"

# $NB_BROWSE_SERVER_TOOL
#
# Default: '' (automatically assigned)
#
# Supported Values: accept, bash, ncat, nc, netcat
export NB_BROWSE_SERVER_TOOL="${NB_BROWSE_SERVER_TOOL:-}"

__set_browse_server_tool() {
  if [[ -z "${NB_BROWSE_SERVER_TOOL:-}"     ]]
  then
    if [[ "${OSTYPE}" =~ cygwin|msys|win32  ]]
    then
      if _command_exists "socat"
      then
        NB_BROWSE_SERVER_TOOL="socat"
      elif _command_exists "ncat"
      then
        NB_BROWSE_SERVER_TOOL="ncat"
      fi
    elif _command_exists "ncat"
    then
      NB_BROWSE_SERVER_TOOL="ncat"
    elif _command_exists "socat"
    then
      NB_BROWSE_SERVER_TOOL="socat"
    elif _command_exists "nc" && nc --help &>/dev/null
    then # GNU nc / netcat is present
      NB_BROWSE_SERVER_TOOL="nc"
    elif [[ "${BASH_VERSINFO[0]}" -ge 5             ]] &&
         [[ "${BASH_VERSINFO[1]}" -ge 2             ]] &&
         [[ -f "${BASH%/bin/bash}/lib/bash/accept"  ]]
    then
      NB_BROWSE_SERVER_TOOL="accept"
    fi
  fi
}; __set_browse_server_tool

###############################################################################
# Helpers: Group 2                                             Helpers: Group 2
# ----------------                                             ----------------
###############################################################################
# --------------------------------------------------------------------------- #

# _build_related_list()
#
# Usage:
#   _build_related_list (<url> | <selector>)...
#
# Description:
#   Build a Markdown-formatted list of <url>s and <selector>s for bookmarks
#   and todos.
_build_related_list() {
  local _list_content=
  local _related_identifiers=("${@:-}")

  local __identifier=
  for   __identifier in "${_related_identifiers[@]:-}"
  do
    [[ -n "${__identifier:-}" ]] || continue

    if _string_is_url "${__identifier:-}"
    then
      _list_content+="- <${__identifier:-}>${_NEWLINE}"
    else
      if [[ "${__identifier:-}" =~ \[\[.*\]\] ]]
      then
        __identifier="$(
          LC_ALL=C sed -E -e "s/\[\[(.*)\]\]/\1/g" <<< "${__identifier:-}"
        )"
      fi

      _list_content+="- [[${__identifier:-}]]${_NEWLINE}"
    fi
  done

  printf "%s\\n" "${_list_content:-}"
}

# _decrypt_file()
#
# Usage:
#   _decrypt_file <path> <password>
_decrypt_file() {
  local _encrypted_path="${1:-}"
  local _password="${2:-}"

  if [[ -z "${_encrypted_path}" ]]
  then
    return 1
  fi

  local _notebook_and_relative_path="${_encrypted_path#"${NB_DIR}"/}"

  local _unencrypted_path=
  _unencrypted_path="$(_temp file "${_notebook_and_relative_path%.enc}")"

  local _file_command_response=
  _file_command_response="$(file "${_encrypted_path}" 2>/dev/null || :)"

  local _decryption_tool=
  _decryption_tool="$(_get_decryption_tool "${_encrypted_path:-}")"

  case "${_decryption_tool:-}" in
    age)
      if _command_exists "age"
      then
        age                                 \
          --decrypt                         \
          --output "${_unencrypted_path}"   \
          "${_encrypted_path}"
      else
        _exit_1 printf                      \
"This item was encrypted with \`age\`, but the \`age\` command was not found.\\n"
      fi
      ;;
    gpg)
      if _command_exists "gpg"
      then
        printf "%s\\n" "${_password}"       \
          | gpg                             \
            --batch                         \
            --quiet                         \
            --passphrase-fd 0               \
            --output "${_unencrypted_path}" \
            --decrypt "${_encrypted_path}"
      else
        _exit_1 printf                      \
"This item was encrypted with GPG, but the GPG command was not found.\\n"
      fi
      ;;
    openssl)
      openssl enc                           \
        -d                                  \
        -aes-256-cbc                        \
        -in   "${_encrypted_path}"          \
        -md   sha256                        \
        -out  "${_unencrypted_path}"        \
        -pass file:<(printf "%s\\n" "${_password}") 2> /dev/null      || {
          if [[ -f "${_unencrypted_path:?}" ]]
          then
            rm "${_unencrypted_path:?}"
          fi

          openssl enc                       \
            -d                              \
            -aes-256-cbc                    \
            -in   "${_encrypted_path}"      \
            -md   md5                       \
            -out  "${_unencrypted_path}"    \
            -pass file:<(printf "%s\\n" "${_password}") 2> /dev/null  ||
              if [[ -f "${_unencrypted_path:?}" ]]
              then
                rm "${_unencrypted_path:?}"
              fi
        }
      ;;
    *)
      _exit_1 printf "Unable to decrypt file.\\n"
      ;;
  esac

  if [[ ! -e "${_unencrypted_path}" ]]
  then
    _exit_1 printf "Decryption error.\\n" 1>&2
  fi

  printf "%s\\n" "${_unencrypted_path}"
}

# _download_from()
#
# Usage:
#   _download_from <url> [<outfile>] [--no-chrome]
#
# Description:
#   Download the file at <url> and print to standard output or <outfile>, if
#   present.
_download_from() {
  local _download_command="${NB_DOWNLOAD_TOOL:-}"
  local _downloaded=0
  local _no_chrome=0
  local _target_path=
  local _timeout=15
  local _url=

  while ((${#}))
  do
    case "${1:-}" in
      --no*chrome|--skip*chrome)
        _no_chrome=1
        ;;
      *)
        if [[   -z "${_url:-}"          ]]
        then
          _url="${1:-}"
        elif [[ -z "${_target_path:-}"  ]]
        then
          _target_path="${1:-}"
        fi
        ;;
    esac

    shift
  done

  if [[ -z "${_url}" ]] ||
     [[ !  "${_url}" =~ (^https\:|^http\:|^file\:|^ftp\:|^sftp\:) ]]
  then
    return 1
  fi

  if  ! ((_no_chrome))                          &&
      [[ -z "${_download_command:-}"        ]]  &&
      {
        [[ "${_url}"    =~ \.html$          ]]  ||
        [[ "${_url}"    =~ \.php$           ]]  ||
        [[ ! "${_url}"  =~ \.[a-zA-Z0-9]+$  ]]
      }                                         &&
      [[ ! "${_url}" =~ ^https://www.reddit.com ]]
  then
    if _command_exists "google-chrome"
    then
      _download_command="google-chrome"
    elif _command_exists "chromium"
    then
      _download_command="chromium"
    elif _command_exists "chromium-browser"
    then
      _download_command="chromium-browser"
    elif [[ -x "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" ]]
    then
      _download_command="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
    elif [[ -x "/Applications/Chromium.app/Contents/MacOS/Chromium"           ]]
    then
      _download_command="/Applications/Chromium.app/Contents/MacOS/Chromium"
    fi
  fi

  if ((_no_chrome)) && [[ "${_download_command:-}" =~ hrome|hromium ]]
  then
    _download_command=
  fi

  if [[ -z "${_download_command:-}" ]]
  then
    if _command_exists "curl"
    then
      _download_command="curl"
    elif _command_exists "wget"
    then
      _download_command="wget"
    fi
  fi

  case "${_download_command:-}" in
    *hrome*|*hromium*)
      {
        "${_download_command:-}"  \
          --dump-dom              \
          --headless              \
          "${_url}"               \
          2>/dev/null
      } | {
        if [[ -n "${_target_path:-}" ]]
        then
          cat > "${_target_path:-}"
        else
          cat
        fi
      } && _downloaded=1
      ;;
    curl*)
      local _curl_options=(
        --silent
        --location
        --connect-timeout "${_timeout}"
        --compressed
        "${_url}"
      )

      [[ -n "${NB_USER_AGENT:-}" ]]   &&
        _curl_options+=(--user-agent "${NB_USER_AGENT}")

      if [[ -n "${_target_path}" ]]
      then
        curl                          \
          "${_curl_options[@]}"       \
          --output "${_target_path}"  \
          && _downloaded=1
      else
        curl                          \
          "${_curl_options[@]}"       \
          && _downloaded=1
      fi
      ;;
    wget*)
      local _wget_options=(
        --quiet
        --connect-timeout="${_timeout}"
        --dns-timeout="${_timeout}"
        --compression=auto
        "${_url}"
      )

      [[ -n "${NB_USER_AGENT:-}" ]]   &&
        _wget_options+=(--user-agent="${NB_USER_AGENT}")

      if [[ -n "${_target_path}" ]]
      then
        wget                          \
          "${_wget_options[@]}"       \
          -O "${_target_path}"        \
          2>/dev/null                 \
          && _downloaded=1
      else
        wget                          \
          "${_wget_options[@]}"       \
          -O -                        \
          2>/dev/null                 \
          && _downloaded=1
      fi
      ;;
  esac

  if ! ((_downloaded))
  then
    return 1
  fi
}

# _edit_file()
#
# Usage:
#   _edit_file <path> [--no-wait]
#
# Description:
#   Open the file in $EDITOR. Use the `-f` option in vim and `--wait` option in
#   other GUI editors to wait until the file is closed in the editor before
#   continuing, unless `--no-wait`.
_edit_file() {
  local _file_path="${1:-}"
  local _wait=1

  local __arg=
  for   __arg in "${@:-}"
  do
    case "${__arg}" in
      --no-wait)
        _wait=0
        ;;
      *)
        if [[ -z "${_file_path}"  ]]
        then
          _file_path="${__arg}"
        fi
        ;;
    esac
  done

  if [[ -z "${_file_path}"        ]]
  then
    return 1
  fi

  local _current_notebook_path=
  _current_notebook_path="$(_notebooks current --path)"

  cd "${_current_notebook_path}"  ||  return 1

  if [[ -e "${_file_path}"            ]]
  then
    if _file_is_encrypted "${_file_path}"
    then
      _exit_1 printf                  \
"File must be decrypted before editing.\\n"
    fi

    if _file_is_archive "${_file_path}"   &&
       [[ ! "${_file_path}" =~ docx$  ]]
    then
      _exit_1 printf                  \
"Can't edit archives. Export archive and expand to edit.\\n"
    fi

    if ! _file_is_text "${_file_path}"    &&
       [[ ! -d "${_file_path}"        ]]
    then
      if _open_in_gui_app "${_file_path:-}"
      then
        return 0
      else
        _exit_1 printf                                \
          "%s doesn't know how to edit this file.\\n" \
          "$(_color_primary "${_ME}")"
      fi
    fi
  fi

  local _editor_command="${NB_EDITOR}"

  # turn on case-insensitive matching
  shopt -s nocasematch

  if ((_wait))
  then
    case "${NB_EDITOR}" in
      *gvim*|*mvim*)
        _editor_command="${_editor_command} -f"
        ;;
      *code*|*mate*|*subl*)
        _editor_command="${_editor_command} --wait"
        ;;
    esac
  fi

  if [[ -d "${_file_path}"    ]] &&
     [[ "${NB_EDITOR}" =~ vim ]]
  then
    cd "${_file_path}" && "${_editor_command:-}"
  else
    if [[ "${NB_EDITOR}" =~ typora  ]] &&
       [[ ! -f "${_file_path:-}"    ]]
    then
      touch "${_file_path:-}"
    fi

    eval "${_editor_command} \"${_file_path}\""

    if [[ "${NB_EDITOR}" =~ (typora|open\ -a) ]]
    then
      printf "Editing with %s\\n" "$(_color_primary "${NB_EDITOR}")"

      while true
      do
        read -n 1 -s -r -p "Press any key to save changes and exit$(_color_muted "...")"

        printf "\\n"

        break
      done
    fi
  fi

  # turn off case-insensitive matching
  shopt -u nocasematch

  return 0
}

# _encrypt_file()
#
# Usage:
#   _encrypt_file <unencrypted-path> <encrypted-path>
#                 [--password <password>] [--tool <tool>]
_encrypt_file() {
  local _encrypted_path="${2:-}"
  local _password=
  local _tool="${NB_ENCRYPTION_TOOL}"
  local _unencrypted_path="${1:-}"

  while ((${#}))
  do
    case "${1:-}" in
      --password)
        if _option_value_is_present "${2:-}"
        then
          _password="${2:-}"

          shift
        fi
        ;;
      --tool)
        if _option_value_is_present "${2:-}"
        then
          _tool="${2:-}"

          shift
        fi
        ;;
    esac

    shift
  done

  if [[ -z "${_password:-}"       ]]  &&
     [[    "${_tool}" != "age"    ]]
  then
    _exit_1 printf "Password required.\\n"
  fi

  if [[ -z "${_unencrypted_path}" ]]  ||
     [[ -z "${_encrypted_path}"   ]]
  then
    _exit_1 printf "Encrypted and unencrypted paths required.\\n"
  fi

  if [[   "${_tool}" == "age"         ]]
  then
    age                               \
      --encrypt                       \
      --output "${_encrypted_path}"   \
      --passphrase                    \
      "${_unencrypted_path}"
  elif [[ "${_tool}" == "gpg"         ]]
  then
    printf "%s\\n" "${_password}"     \
      | gpg                           \
        --batch                       \
        --cipher-algo AES256          \
        --quiet                       \
        --output "${_encrypted_path}" \
        --passphrase-fd 0             \
        --symmetric                   \
        "${_unencrypted_path}"
  elif [[ "${_tool}" == "openssl"     ]]
  then
    openssl enc                       \
      -aes-256-cbc                    \
      -in   "${_unencrypted_path}"    \
      -md   sha256                    \
      -out  "${_encrypted_path}"      \
      -pass file:<(printf "%s\\n" "${_password}") 2>/dev/null
  else
    _exit_1 printf                    \
      "\$NB_ENCRYPTION_TOOL must be set to 'gpg' or 'openssl'.\\n"
  fi

  if [[ ! -e "${_encrypted_path}"     ]]
  then
    _exit_1 printf "Encryption error.\\n"
  fi
}

# _get_decryption_tool()
#
# Usage:
#   _get_decryption_tool <path>
#
# Description:
#   Print the name of the tool to use to decrypt the file at <path>.
_get_decryption_tool() {
  local _decryption_tool=
  local _encrypted_path="${1:-}"

  if _command_exists "file"
  then
    local _file_command_response=
    _file_command_response="$(file "${_encrypted_path}" 2>/dev/null || :)"

    if [[   "${_file_command_response}" =~ (GPG|PGP)  ]]
    then
      _decryption_tool="gpg"
    elif [[ "${_file_command_response}" =~ openssl    ]]
    then
      _decryption_tool="openssl"
    elif [[ "${_file_command_response}" =~ data       ]]
    then
      local         __first_line=
      IFS=  read -r __first_line < "${_encrypted_path}"

      if [[ "${__first_line:-}" =~ age-encryption     ]]
      then
        _decryption_tool="age"
      fi
    fi
  else
    # Read the first line and first 16 bytes (for binary signatures)
    local _first_line=
    IFS= read -r _first_line < "${_encrypted_path}"

    local _first_bytes=
    _first_bytes="$(head -c 16 "${_encrypted_path}" | xxd -p)"

    if [[ "${_first_line}" == age-encryption* ]]
    then # age
      _decryption_tool="age"
    elif [[ "${_first_line}" == "-----BEGIN PGP MESSAGE-----" ]] ||
         [[ "${_first_line}" == "-----BEGIN GPG MESSAGE-----" ]]
    then # GPG/PGP ASCII armored header
      _decryption_tool="gpg"
    elif [[ "${_first_bytes}" =~ ^8c ]] || [[ "${_first_bytes}" =~ ^99 ]]
    then # GPG binary (magic number: 0x8c/0x99 at start, but can be more complicated)
      _decryption_tool="gpg"
    elif head -c 8 "${_encrypted_path}" | grep -q "^Salted__"
    then # OpenSSL (Salted__ in ASCII at start)
      _decryption_tool="openssl"
    fi
  fi

  printf "%s\\n" "${_decryption_tool:-}"
}

# _get_hash()
#
# Usage:
#   _get_hash <path>
#
# Description:
#   Generate a hash for the file or directory at <path>.
_get_hash() {
  # Usage: _get_hash_with_command <path> <command>
  _get_hash_with_command() {
    local _command=
    IFS=' ' read -ra _command <<< "${2:-}"

    local _path="${1:-}"

    [[ -n "${_command[*]:-}" ]] && [[ -n "${_path}" ]] || return 1

    if [[ -d "${_path}" ]]
    then
      tar -P -cf - "${_path}"     \
        | "${_command[@]}"        \
        | awk '{ print $1 }'
    else
      "${_command[@]}" "${_path}" \
        | awk '{print $1}'
    fi
  }

  local _path="${1:-}"
  [[ -n "${_path:-}" ]] || return 1

  if _command_exists "shasum"
  then
    _get_hash_with_command "${_path}" "shasum -a 256"
  elif _command_exists "md5sum"
  then
    _get_hash_with_command "${_path}" "md5sum"
  elif _command_exists "md5"
  then
    _get_hash_with_command "${_path}" "md5 -q"
  else
    _exit_1 printf "No hashing tool found.\\n"
  fi
}

# _get_http_status()
#
# Usage:
#   _get_http_status <url>
#
# Description:
#   Print the http status response code for <url>.
_get_http_status() {
  local _url="${1:-}"
  [[ -n "${_url:-}" ]] || return 1

  if _command_exists "curl"
  then
    local _curl_options=(
      --head
      --silent
      --output /dev/null
      -w "%{http_code}\\n"
    )

    [[ -n "${NB_USER_AGENT:-}" ]] &&
      _curl_options+=(--user-agent "${NB_USER_AGENT}")

    curl "${_curl_options[@]}" "${_url}" || return 0
  elif _command_exists "wget"
  then
    local _wget_options=(
      --server-response
    )

    [[ -n "${NB_USER_AGENT:-}" ]] &&
      _wget_options+=(--user-agent="${NB_USER_AGENT}")

    wget "${_wget_options[@]}" "${_url}" 2>&1 \
      | grep "HTTP/" | awk '{print $2}' || return 0
  fi
}

# _get_sanitized_filename()
#
# Usage:
#   _get_sanitized_file_name <input>
#
# Description:
#   Get a santized filename derived from an input string, such as a title.
_get_sanitized_filename() {
  printf "%s" "${1:-}"                          \
    | LC_ALL=C sed -E                           \
        -e 's/^[[:space:]]+//g'                 \
        -e 's/[[:space:]]+$//g'                 \
        -e 's/\[[[:space:]]*\][[:space:]]*//g'  \
        -e 's/\[x\][[:space:]]*//g'             \
    | tr '[:upper:]' '[:lower:]'                \
    | tr '[:space:]:*/\\<>?|' '_'               \
    | tr "\"" '_'
}

# _get_unique_path()
#
# Usage:
#   _get_unique_path <path>
#
# Description:
#   Get a unique full path that doesn't conflict with any existing file.
_get_unique_path() {
  local _path="${1:-}"

  local _dir_path=
  _dir_path="$(dirname "${_path}")"

  local _basename=
  _basename="$(basename "${_path}")"

  local _file_name="${_basename%%.*}"
  local _file_extension="${_basename#*.}"

  if [[ -n "${_file_extension:-}"               ]] &&
     [[ "${_basename}"  =~ \.                   ]] &&
     [[ "${_file_name}" != "${_file_extension}" ]]
  then
    _file_extension=".${_file_extension}"
  else
    _file_extension=
  fi

  local _unique_file_name="${_file_name}"
  local _uniqueness_counter=0

  while [[ -e "${_dir_path}/${_unique_file_name}${_file_extension}"     ]] ||
        [[ -e "${_dir_path}/${_unique_file_name}${_file_extension}.enc" ]]
  do
    _uniqueness_counter="$((_uniqueness_counter+1))"

    printf -v _unique_file_name -- "%s-%01d"  \
      "${_file_name}"                         \
      "${_uniqueness_counter}"
  done

  printf "%s\\n" "${_dir_path}/${_unique_file_name}${_file_extension}"
}

# _get_unique_relative_path()
#
# Usage:
#   _get_unique_relative_path [<file-path>[<extension>] [<notebook-path>]
#
# Description:
#   Get a unique basename that doesn't conflict with any existing file.
_get_unique_relative_path() {
  local _file_path="${1:-}"
  local _notebook_path="${2:-"$(_notebooks current --path)"}"

  local _file_basename="${_file_path##*/}" # strip ancestors
  local _file_name="${_file_basename%%.*}" # strip extension
  local _folder_path=
  local _target_basename=
  local _unique_path=

  if [[ -z "${_file_name:-}"    ]]
  then
    _file_name="$(date "+%Y%m%d%H%M%S")"
  fi

  if [[ "${_file_path:-}" =~ /  ]]
  then
    _folder_path="${_file_path%\/*}"
  fi

  if [[ "${_file_basename:-}" =~ ^\.  ]]
  then
    local _file_type="${_file_basename#*.}"

    _target_basename="${_file_name}.${_file_type}"
  elif [[ -n "${_file_basename:-}"    ]]
  then
    _target_basename="${_file_basename}"
  else
    _target_basename="${_file_name}"
  fi

  _unique_path="$(
    if [[ -n "${_folder_path:-}" ]]
    then
      _get_unique_path "${_notebook_path}/${_folder_path}/${_target_basename}"
    else
      _get_unique_path "${_notebook_path}/${_target_basename}"
    fi
  )"

  printf "%s" "${_unique_path#"${_notebook_path}"/}"
}

# _get_uri()
#
# Usage:
#   _get_uri [--encode | --decode] <string>
#
# Description:
#   Encode or decode a URI.
_get_uri() {
  # Usage: _get_uri_decode <string>
  _get_uri_decode() {
    # https://unix.stackexchange.com/a/187256
    local _input="${1:-}"

    _input="${_input//+/ }"
    _input="${_input//$'\r'}"

    printf "%b\\n" "${_input//%/\\x}"
  }

  # Usage: _get_uri_encode <string>
  _get_uri_encode() {
    local _encoding="${1//'%'/%25}"

    _encoding="${_encoding//' '/%20}"
    _encoding="${_encoding//'"'/%22}"
    _encoding="${_encoding//'#'/%23}"
    _encoding="${_encoding//'$'/%24}"
    _encoding="${_encoding//'&'/%26}"
    _encoding="${_encoding//'+'/%2B}"
    _encoding="${_encoding//','/%2C}"
    _encoding="${_encoding//${_SLASH}/%2F}"
    _encoding="${_encoding//':'/%3A}"
    _encoding="${_encoding//';'/%3B}"
    _encoding="${_encoding//'='/%3D}"
    _encoding="${_encoding//'?'/%3F}"
    _encoding="${_encoding//'@'/%40}"
    _encoding="${_encoding//'['/%5B}"
    _encoding="${_encoding//'\n'/%0A}"

    local _encoded="${_encoding//']'/%5D}"

    printf "%s\\n" "${_encoded:-}"
  }

  case "${1:-}" in
    --decode)                 _get_uri_decode "${2:-}"  ;;
    --encode)                 _get_uri_encode "${2:-}"  ;;
    http%3A%2F*|https%3A%2F*) _get_uri_decode "${1:-}"  ;;
    http://*|https://*)       _get_uri_encode "${1:-}"  ;;
  esac
}

# _normalize_encoding()
#
# Usage:
#   _normalize_encoding <input>
#
# Description:
#   Use python3 or perl to normalize encoding of a string.
_normalize_encoding() {
  {
    printf "%s" "${1:-}"
  } | {
    if _command_exists "python3"
    then
      python3 -c "import sys,unicodedata; print(unicodedata.normalize('NFC', sys.stdin.read()), end='')"
    elif _command_exists "perl"
    then
      perl -MUnicode::Normalize -CS -ne 'print NFC($_)'
    else
      cat
    fi
  }
}

# _option_get_tags()
#
# Usage:
#   _option_get_tags <option> <comma,separated,tags>
#
# Description:
#   Convert a comma-separated list of tags to a string of hashtags.
_option_get_tags() {
  local _tag_list=
  _tag_list="$(_option_get_value "${1:-}" "${2:-}")" || return 1

  local _tags=()
  IFS=',' read -ra _tags <<< "${_tag_list}"

  local _normalized_tags=()

  local __tag=
  for   __tag in "${_tags[@]:-}"
  do
    _normalized_tags+=("#${__tag#\#}")
  done

  local _tag_string=
  _tag_string="$(_join " " "${_normalized_tags[@]-}")"

  printf "%s\\n" "${_tag_string:-}"
}

# _render()
#
# Usage:
#   [<input> |] _render [<path>] [--body] [--from] [--pandoc]
#                       [--source-extension] [--title <title>]
#                       [<pandoc-option>...]
#
# Options:
#   --body              Only render body, without <head> and <body> opening
#                       or closing tags.
#   --from              The format to convert content from.
#   --pandoc            Use pandoc to convert file.
#   --source-extension  The extension of the original file. Used to select
#                       syntax mode in Ace.
#   --title             <title> content.
_render() {
  # Usage: _render_prepare_file <path> <pandoc-enabled>
  _render_prepare_file() {
    local _input_file_path="${1:?}"
    local _prepared_file_path="${_input_file_path:-}"
    local _use_pandoc="${2:-0}"

    local _code_extensions=(
      asm aspx awd awk bash bat bats bib c c++ cc cgi class cls cmake coffee
      cpp cs cson cxx d diff "do" el f fs gcl go h hs haml hbs hx j jade java
      jl js json jsp jsx kts ksh "less" lsp lua m matlab ml mk mm perl php pl
      pm prl pug py rb r rh rs sass scala scpt scss sh sql styl swift tcl toml
      tpl ts tsx vb vba vbscript vim xml xsl xslt yaml yml zsh
    )

    if ((_use_pandoc))
    then
      _code_extensions+=($(
        pandoc --list-highlight-languages \
          | sed -e "/html/d" -e "/latex/d" -e "/markdown/d"
      ))
    fi

    local _source_extension="${_input_file_path##*\.}"

    if _contains "${_source_extension}" "${_code_extensions[@]:-}"
    then
      if ((_use_pandoc))
      then
        local _code_block_temp_path=
        _code_block_temp_path="$(_temp file ".md" --touch)"

        printf "${_BT}${_BT}${_BT}%s\\n%s\\n${_BT}${_BT}${_BT}\\n"  \
          "${_source_extension}"                                    \
          "$(cat "${_input_file_path:-}")" >> "${_code_block_temp_path:-}"
      else
        local _code_block_temp_path=
        _code_block_temp_path="$(_temp file ".html" --touch)"

        printf "<code>\\n%s\\n</code>\\n" \
          "$(cat "${_input_file_path:-}")" >> "${_code_block_temp_path:-}"
      fi

      _prepared_file_path="${_code_block_temp_path:-}"
    fi

    printf "%s\\n" "${_prepared_file_path:-}"
  }

  # Usage: _render_print_head [--title <title>]
  _render_print_head() {
    local _custom_css="${NB_CUSTOM_CSS:-}"
    local _custom_css_element=
    local _custom_css_url="${NB_CUSTOM_CSS_URL:-}"
    local _custom_javascript="${NB_CUSTOM_JAVASCRIPT:-${NB_CUSTOM_JS:-}}"
    local _custom_javascript_element=
    local _custom_javascript_url="${NB_CUSTOM_JAVASCRIPT_URL:-${NB_CUSTOM_JS_URL:-}}"
    local _html_title="${_ME}"

    if [[ "${1:-}" == "--title" ]] && [[ -n "${2:-}" ]]
    then
      _html_title="${2:-}"
    fi

    local _ansi_hex_values=(
      '000000' '800000' '008000' '808000' '000080' '800080' '008080' 'c0c0c0'
      '808080' 'ff0000' '00ff00' 'ffff00' '0000ff' 'ff00ff' '00ffff' 'ffffff'
      '000000' '00005f' '000087' '0000af' '0000d7' '0000ff' '005f00' '005f5f'
      '005f87' '005faf' '005fd7' '005fff' '008700' '00875f' '008787' '0087af'
      '0087d7' '0087ff' '00af00' '00af5f' '00af87' '00afaf' '00afd7' '00afff'
      '00d700' '00d75f' '00d787' '00d7af' '00d7d7' '00d7ff' '00ff00' '00ff5f'
      '00ff87' '00ffaf' '00ffd7' '00ffff' '5f0000' '5f005f' '5f0087' '5f00af'
      '5f00d7' '5f00ff' '5f5f00' '5f5f5f' '5f5f87' '5f5faf' '5f5fd7' '5f5fff'
      '5f8700' '5f875f' '5f8787' '5f87af' '5f87d7' '5f87ff' '5faf00' '5faf5f'
      '5faf87' '5fafaf' '5fafd7' '5fafff' '5fd700' '5fd75f' '5fd787' '5fd7af'
      '5fd7d7' '5fd7ff' '5fff00' '5fff5f' '5fff87' '5fffaf' '5fffd7' '5fffff'
      '870000' '87005f' '870087' '8700af' '8700d7' '8700ff' '875f00' '875f5f'
      '875f87' '875faf' '875fd7' '875fff' '878700' '87875f' '878787' '8787af'
      '8787d7' '8787ff' '87af00' '87af5f' '87af87' '87afaf' '87afd7' '87afff'
      '87d700' '87d75f' '87d787' '87d7af' '87d7d7' '87d7ff' '87ff00' '87ff5f'
      '87ff87' '87ffaf' '87ffd7' '87ffff' 'af0000' 'af005f' 'af0087' 'af00af'
      'af00d7' 'af00ff' 'af5f00' 'af5f5f' 'af5f87' 'af5faf' 'af5fd7' 'af5fff'
      'af8700' 'af875f' 'af8787' 'af87af' 'af87d7' 'af87ff' 'afaf00' 'afaf5f'
      'afaf87' 'afafaf' 'afafd7' 'afafff' 'afd700' 'afd75f' 'afd787' 'afd7af'
      'afd7d7' 'afd7ff' 'afff00' 'afff5f' 'afff87' 'afffaf' 'afffd7' 'afffff'
      'd70000' 'd7005f' 'd70087' 'd700af' 'd700d7' 'd700ff' 'd75f00' 'd75f5f'
      'd75f87' 'd75faf' 'd75fd7' 'd75fff' 'd78700' 'd7875f' 'd78787' 'd787af'
      'd787d7' 'd787ff' 'd7af00' 'd7af5f' 'd7af87' 'd7afaf' 'd7afd7' 'd7afff'
      'd7d700' 'd7d75f' 'd7d787' 'd7d7af' 'd7d7d7' 'd7d7ff' 'd7ff00' 'd7ff5f'
      'd7ff87' 'd7ffaf' 'd7ffd7' 'd7ffff' 'ff0000' 'ff005f' 'ff0087' 'ff00af'
      'ff00d7' 'ff00ff' 'ff5f00' 'ff5f5f' 'ff5f87' 'ff5faf' 'ff5fd7' 'ff5fff'
      'ff8700' 'ff875f' 'ff8787' 'ff87af' 'ff87d7' 'ff87ff' 'ffaf00' 'ffaf5f'
      'ffaf87' 'ffafaf' 'ffafd7' 'ffafff' 'ffd700' 'ffd75f' 'ffd787' 'ffd7af'
      'ffd7d7' 'ffd7ff' 'ffff00' 'ffff5f' 'ffff87' 'ffffaf' 'ffffd7' 'ffffff'
      '080808' '121212' '1c1c1c' '262626' '303030' '3a3a3a' '444444' '4e4e4e'
      '585858' '626262' '6c6c6c' '767676' '808080' '8a8a8a' '949494' '9e9e9e'
      'a8a8a8' 'b2b2b2' 'bcbcbc' 'c6c6c6' 'd0d0d0' 'dadada' 'e4e4e4' 'eeeeee'
    )

    # #1a1a1a #1b1b20 #17171c #19191f #18181c
    local _color_background_hex="#141418"
    local _color_background_alt_hex="#17171c" # #1b1b20 #1e1e25 #212121
    local _color_muted_hex="#626480"
    local _color_primary_hex="#7593eb"
    # TODO: local _color_secondary_hex=
    local _color_text_hex="#c5c4cc"           # #e6e6e6 #dedede

    if [[ "${NB_COLOR_PRIMARY}" -lt 256 ]]
    then
      _color_primary_hex="#${_ansi_hex_values[${NB_COLOR_PRIMARY}]}"
      # TODO: _color_secondary_hex="#${_ansi_hex_values[${NB_COLOR_SECONDARY}]}"

      # desaturate select colors
      case "${_color_primary_hex}" in
        \#5f87ff) _color_primary_hex="#7593eb" ;;
        \#ffff5f) _color_primary_hex="#ebeb75" ;;
      esac
    fi

    if [[ -n "${_custom_javascript:-}"      ]]
    then
      _custom_javascript_element="\
<script>${_NEWLINE}${_custom_javascript:-}${_NEWLINE}</script>"
    fi

    if [[ -n "${_custom_javascript_url:-}"  ]]
    then
      _custom_javascript_url_element="\
<script src=\"${_custom_javascript_url:-}\"></script>"
    fi

    if [[ -n "${_custom_css:-}"             ]]
    then
      _custom_css_element="\
<style>${_NEWLINE}${_custom_css:-}${_NEWLINE}</style>"
    fi

    if [[ -n "${_custom_css_url:-}"         ]]
    then
      _custom_css_url_element="\
<link rel=\"stylesheet\" href=\"${_custom_css_url:-}\"/>"
    fi

    cat <<HEREDOC
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">

<title>${_html_title}</title>

<link rel="icon" type="image/x-icon" href="data:image/x-icon;base64,\
AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAACQWAAAkFgAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAon8IB59/AlSegwFunYgCVJ+RBhGdlAFcnZkAbp2eAkqc\
pwMxm6sBaJuxAzCbtwJim7wChZrAAlCaxgUHmsQEAKN+CQafgQJqnYUB2p6JA2WfkQYPnpYDdp2aAd\
mengNXnKgEMZutAsCbsgHNm7cCiZu9AnGZwwG8mMcCbo6pAACehgIAnYYCIJ2HAbeeigMYnpUFAJ6c\
BSednQK1nqAEE5irAACbsQKTm7MBlp++DwKZxgIAmccCPZjKAbuZzQQXnogCAJ2IAiCdigG8no0EHZ\
6XBQCenwUnnZ8CtZ6iBBOZrgAAm7MCkZu1AmqatAAAmcsEAJnLAx2YzQG9mc8EKJ2LAgCdigIenY0B\
152RAlqdlwAAnqEEL52iAbaepQQQmLAAAJu2ApObuAGbncQKBJjLAQCZzQJBmM8BupnRBBafiQUOnY\
sBep2OAdOdlAKsnZoChZ2gAaidowKVoKwOA5a3AACbuAKQm7sC0ZrCApCYyAF8mM0Bv5jPAmeTxgAA\
n4oGDJ6MA1WekANJnpcEIp2cAmudoAJsnaQDGp2jAgCVuwAAm7sCkJu9A3GZxAJUmcgCe5nNAkaa0Q\
UGmdAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKjBJwCZuwAAnLkFFZu9AqSbvwNkmr4AAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACowSYAl7sAAJu6A1iavQGym8EDQprAAQ\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqcMpAJu9AACcvAUEnMAECJ3E\
CAKcwwcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AAD//wAA//8AAAABAAAAAQAAiI\
gAAIiYAACIiAAAAIEAAAGBAAD/HwAA/x8AAP8fAAD//wAA//8AAA==">

<style>
html {
  background-color:   ${_color_background_hex};
  color:              ${_color_text_hex};
  font-size:          16px;
  line-height:        1.5;
}

@media (min-width: 992px) {
  html {
    font-size:        17px;
  }
}

html,
input,
textarea {
  font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
}

body {
  font-kerning:       normal;
  hyphens:            none;
  margin:             0;
  text-rendering:     optimizeLegibility;
  word-wrap:          break-word;
}

@media (max-width: 600px) {
  body {
    font-size:        0.9em;
  }
}

@media print {
  body {
    background-color: transparent;
    color:            black;
    font-size:        12pt;
  }

  h2, h3, p {
    orphans:          3;
    widows:           3;
  }

  h2, h3, h4 {
    page-break-after: avoid;
  }
}

h1, h2, h3, h4, h5, h6 {
  margin-bottom:      1rem;
  margin-top:         1rem;
}

h1  { font-size:      1.5rem;   }
h2  { font-size:      1.3rem;   }
h3  { font-size:      1.17rem;  }

h5, h6 {
  font-size: 1em;
  font-style: italic;
}

h6  {  font-weight:   normal; }

p {
  margin:             1em 0;
  overflow:           hidden;
}

a         {  color:   ${_color_primary_hex}; text-decoration: none;       }
a:hover   {  color:   ${_color_primary_hex}; text-decoration: underline;  }
a:visited {  color:   ${_color_primary_hex}; text-decoration: none;       }

:focus {
  outline:            1px solid #2d2d2d;
}

body.using-mouse a:focus,
body.using-mouse input:focus {
  outline:            none;
}

h1 a,
h1 a:hover,
h1 a:visited,
nav a,
nav a:hover,
nav a:visited,
a.list-item,
a.list-item:hover,
a.list-item:visited {
  color:              ${_color_text_hex};
  text-decoration:    none;
}

blockquote {
  border-left:        2px solid #4d4d4d;
  color:              #878787;            /* #606060 */
  margin:             1em 0 1em 1.7em;
  padding-left:       1em;
}

code {
  background-color:   ${_color_background_alt_hex};
  font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
  font-size:          85%;
  margin:             0;
  padding:            0.2em 0.4em;
  white-space:        pre-wrap;
}

pre {
  background-color:   ${_color_background_alt_hex};
  border:             1px solid ${_color_background_alt_hex};
  border-radius:      1px;
  margin:             1rem 0;
  overflow:           auto;
  padding:            1rem;
}

pre.sourceCode {
  padding:            1rem;
}

pre code {
  overflow:           visible;
  padding:            0;
}

hr  {
  background-color:   #4d4d4d;
  border:             none;
  height:             1px;
  margin:             1em 0;
}

img {
  border-radius:      1px;
  max-width:          100%;
}

ol, ul {
  padding-left:       1.7em;
  margin-top:         1em;
}

li > ol, li > ul {
  margin-top:         0;
}

table {
  border-collapse:    collapse;
  border-color:       transparent;
  display:            block;
  font-variant-numeric: lining-nums tabular-nums;
  margin:             1em 0;
  overflow-x:         auto;
  width:              100%;
}

th {
  border-top:         1px solid #4d4d4d;
  padding:            0.25em 0.5em 0.25em 0.5em;
}

tbody {
  border: none;
  border-bottom:      1px solid #4d4d4d;
  margin-top:         0.5em;
}

td {
  padding:            0 0 1rem 0;
}

td > table {
  margin:             0;
}

table caption {
  margin-bottom:      0.75em;
}

col {
  width:              auto !important;
}

audio {
  padding:            1rem 0;
}

audio,
video {
  margin:             0 auto;
  width:              100%;
}

audio:focus,
video:focus {
  outline:            ${_color_background_hex};
}

video {
  height:             auto;
  max-height:         50rem;
}

.media-item {
  padding:            2rem 0 1rem;
}

header {
  margin-bottom:      4em;
  text-align:         center;
}

.center {
  text-align:         center;
}

.header-crumbs {
  font-size:          1rem;
  font-weight:        normal;
  line-height:        2;
  margin:             0 auto;
  max-width:          45rem;
  padding:            1.75rem 2rem 0rem;
  text-align:         left;
}

/* <strong> for bold in terminal browsers only */
.header-crumbs strong {
  font-weight:        normal;
}

.header-crumbs-spacer {
  display:            none;
}

.main {
  margin:             0 auto;
  max-width:          45rem;
  padding:            0rem 2rem 2rem;
}

.main h1:first-child {
  padding-top:        0.35rem;
}

.main p:first-child,
.main .sourceCode:first-child {
  padding-top:        0.5rem;
}

.math.display:focus,
.MathJax:focus {
  outline:            none;
}

.item-list {
  margin-top:         0;
}

.list-item  {
  display:            inline-block;
  max-width:          45rem;
  overflow:           hidden;
  text-overflow:      ellipsis;
  white-space:        nowrap;
  vertical-align:     top;
}

.identifier {         color: ${_color_primary_hex}; }
.muted      {         color: ${_color_muted_hex};   }

form {
  padding-top:        1rem;
}

#search {
  position:           relative;
}

label[for=search-input] {
  display:            none;
}

#search-input {
  background-color:   ${_color_background_hex};
  border:             none;
  border-bottom:      1px solid #4d4d4d;
  color:              ${_color_text_hex};
  font-size:          1rem;
  padding:            0.5rem 0;
  width:              100%;
}

#search-input:focus {
  outline:            0;
}

.search-spacer {
  display:            none;
}

#search	i {
  animation-name:     blink;
  animation-duration: 3000ms;
  animation-iteration-count: infinite;
  background-color:   #a6a659;
  display:            none;
  height:             80%;
  left:               5px;
  opacity:            0.5;
  position:           absolute;
  top:                10%;
  width:              1em;
}

#search input:focus + i {
  display:            none;
}

@keyframes blink {
  from  { opacity:    1; }
  to    { opacity:    0; }
}

form br {
  display:            none;
}

input[type="submit"] {
  background:         none;
  border:             none;
  color:              ${_color_primary_hex};
  font-size:          1rem;
  outline:            0 solid ${_color_background_hex};
  padding:            1rem;
}

input[type="submit"]:active {
  border-bottom:      1px solid #bae7ff;
  color:              #bae7ff;
}

input[type="submit"]:focus {
  outline:            1px solid #2d2d2d;
}

input[type="submit"]:hover {
  border-bottom:      1px solid ${_color_primary_hex};
}

.last-saved {
  padding-left:       1rem;
}

textarea,
.ace_editor {
  background-color:   ${_color_background_alt_hex};
  border:             none;
  box-sizing:         border-box;
  color:              #dddddd;
  font-size:          0.875rem;
  line-height:        1.5;
  margin-bottom:      1rem;
  margin-top:         1rem;
  outline:            1px solid ${_color_background_hex};
  padding:            0;
  vertical-align:     top;
  width:              100%;
}

textarea {
  padding:            1rem;
}

#TOC li {
  list-style:         none;
}

#TOC a:not(:hover) {
  text-decoration:    none;
}

div.column {
  display:            inline-block;
  vertical-align:     top;
  width:              50%;
}

div.hanging-indent {
  margin-left:        1.5em;
  text-indent:        -1.5em;
}

span.smallcaps {
  font-variant:       small-caps;
}

span.underline {
  text-decoration:    underline;
}

ul.task-list {
  list-style:         none;
}

ul.task-list input[type="checkbox"] {
  -webkit-appearance: none;
  -moz-appearance:    none;
  background-color:   #2d2d2d;
  border-radius:      3px;
  font-size:          1.2rem;
  padding:            0 0.3rem;
}

ul.task-list input[type="checkbox"]:before {
  color:              transparent;
  content:            "\0000A0";
}

ul.task-list input[type="checkbox"]:checked:before {
  color:              ${_color_primary_hex};
  content:            "x";
}

/*
 * #93a5cc #ffcfaf #7f9f7f #dca3a3 #f0dfaf #dfdfbf #dcdccc #c3bf9f #c0bed1
 * #efef8f #b7bcd8 #cccc96 #7290b1
 * /

/* Ace Editor & Syntax */

.ace_editor {
  /* border:             1rem solid ${_color_background_alt_hex}; */
}

.ace_gutter {
  padding:            1rem 0;
}

.ace_gutter-cell {
  padding:            0 0.5rem;
}

.ace_content {
  padding:            1rem 0.5rem;
}

.ace_scroller.ace_scroll-left {
  box-shadow:         initial !important;
}

.ace-twilight .ace_constant,
.ace-twilight .ace_constant.ace_character,
.ace-twilight .ace_constant.ace_character.ace_escape,
.ace-twilight .ace_constant.ace_other,
.ace-twilight .ace_heading,
.ace-twilight .ace_markup.ace_heading,
.ace-twilight .ace_support.ace_constant {
  color:              #9191a1;
}

.ace-tm .ace_gutter,
.ace-tm .ace_gutter-active-line,
.ace-twilight .ace_gutter {
  color:              #E2E2E2;
  background-color:   ${_color_background_hex};
}

.ace-tm .ace_gutter-active-line {
  filter:             brightness(1.25);
}

.ace-twilight .ace_indent-guide-active {
  filter: invert(1) grayscale(100%) brightness(0.75);
}

.ace-twilight .ace_invisible {
  color:              #333333;
}

.ace-twilight .ace_list,
.ace-twilight .ace_markup.ace_list,
.ace-twilight .ace_storage,
.ace-twilight .ace_string.ace_strong {
  color:              #cccc96;
}

.ace-twilight .ace_print-margin {
  background:         none;
}

.ace_separator {
  color:              #7290b1;
}

.ace-twilight .ace_keyword,
.ace-twilight .ace_meta {
  color:              #7290b1;
}

.ace-twilight .ace_string {
  color:              ${_color_primary_hex};
}

.normal-mode .ace_cursor {
  background-color:   rgba(255,255,0,0.5);
}

.normal-mode .ace_hidden-cursors .ace_cursor {
  border:             1px solid yellow;
}

/* Pandoc Syntax */

pre > code.sourceCode {
  position:           relative;
  white-space:        pre;
}

pre > code.sourceCode > span  {
  display:            inline-block;
  line-height:        1.25;
}

pre > code.sourceCode > span:empty {
  height:             1.2em;
}

code.sourceCode > span {
  color:              inherit;
  text-decoration:    inherit;
}

@media screen {
  div.sourceCode {
    overflow:         auto;
  }
}

@media print {
  pre > code.sourceCode {
    white-space:      pre-wrap;
  }

  pre > code.sourceCode > span {
    padding-left:     5em;
    text-indent:      -5em;
  }
}

pre.numberSource code {
  counter-reset:      source-line 0;
}

pre.numberSource code > span {
  counter-increment:  source-line;
  left:               -4em;
  position:           relative;
}

pre.numberSource code > span > a:first-child::before {
  border:             none;
  content:            counter(source-line);
  display:            inline-block;
  left:               -1em;
  padding:            0 4px;
  position:           relative;
  text-align:         right;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select:   none;
  -ms-user-select:    none;
  user-select:        none;
  vertical-align:     baseline;
  width:              4em;
}

pre.numberSource {
  margin-left:        3em;
  padding-left:       4px;
}

div.sourceCode {
  color:              #cccccc;
}

@media screen {
  pre > code.sourceCode > span > a:first-child::before {
    text-decoration:  underline;
  }
}

code span.al { color: #ffcfaf;                          } /*     Alert      */
code span.an { color: #7f9f7f;      font-weight: bold;  } /*   Annotation   */
code span.at {                                          } /*   Attribute    */
code span.bn { color: #dca3a3;                          } /*     BaseN      */
code span.bu {                                          } /*    BuiltIn     */
code span.cf { color: #7290b1;                          } /*  ControlFlow   */
code span.ch { color: #8987a0;                          } /*      Char      */
code span.cn { color: #8987a0;      font-weight: bold;  } /*    Constant    */
code span.co { color: ${_color_muted_hex};              } /*    Comment     */
code span.cv { color: #7f9f7f;      font-weight: bold;  } /*   CommentVar   */
code span.do { color: ${_color_muted_hex};              } /* Documentation  */
code span.dt { color: #cccc96;                          } /*    DataType    */
code span.dv { color: #cccc96;                          } /*     DecVal     */
code span.er { color: #cccc96;                          } /*     Error      */
code span.ex {                                          } /*   Extension    */
code span.fl { color: #c0bed1;                          } /*     Float      */
code span.fu { color: #7290b1;                          } /*    Function    */
code span.im {                                          } /*     Import     */
code span.in { color: #7f9f7f;      font-weight: bold;  } /*  Information   */
code span.kw { color: #7290b1;                          } /*    Keyword     */
code span.op { color: #f0efd0;                          } /*   Operator     */
code span.ot { color: #cccc96;                          } /*     Other      */
code span.pp { color: #ffcfaf;      font-weight: bold;  } /*  Preprocessor  */
code span.sc { color: #8987a0;                          } /*  SpecialChar   */
code span.ss { color: ${_color_primary_hex};            } /* SpecialString  */
code span.st { color: ${_color_primary_hex};            } /*     String     */
code span.va {                                          } /*    Variable    */
code span.vs { color: ${_color_primary_hex};            } /* VerbatimString */
code span.wa { color: #93a5cc;      font-weight: bold;  } /*    Warning     */
</style>

<script>
// hide broken images
document.addEventListener("DOMContentLoaded", function(event) {
  document.querySelectorAll('img').forEach(function(img) {
    img.onerror = function() { this.style.display = 'none'; };
  })
});

// let the document know when the mouse is being used
document.addEventListener('mousedown', function() {
  document.body.classList.add('using-mouse');
});

// re-enable focus styling when <tab> is pressed
document.addEventListener('keydown', function(event) {
  if (event.keyCode === 9) {
    document.body.classList.remove('using-mouse');
  }
});
</script>
${_custom_css_url_element:-}
${_custom_javascript_url_element:-}
${_custom_css_element:-}
${_custom_javascript_element:-}
<meta name="referrer" content="no-referrer" />
</head>
<body>
HEREDOC
  }

  local _from=
  local _html_title=
  local _input_file_path=
  local _input_string=
  local _only_body=0
  local _pandoc_arguments=("--highlight-style=zenburn")
  local _source_extension="${NB_DEFAULT_EXTENSION:-md}"
  local _filter_bookmark_content=0
  local _use_pandoc=0

  while ((${#}))
  do
    case "${1:-}" in
      "")         :                                           ;;
      --body)     _only_body=1                                ;;
      --bookmark) _filter_bookmark_content=1                  ;;
      --from)     _from="${2:?}" && _use_pandoc=1   && shift  ;;
      --*pandoc)  _use_pandoc=1                               ;;
      --source*)  _source_extension="${2:?}"        && shift  ;;
      --title)    _html_title="${2:?}"              && shift  ;;
      -*)         _pandoc_arguments+=("${1:-}")               ;;
      *)
        if [[ -z "${_input_file_path:-}"  ]] &&
           [[ -f "${1:-}"                 ]]
        then
          _input_file_path="${1:-}"
        elif [[ -z "${_input_string:-}"   ]]
        then
          _input_string="${1:-}"
        else
          _pandoc_arguments+=("${1:-}")
        fi
        ;;
    esac

    shift
  done

  local _prepared_file_path="${_input_file_path:-}"

  if ! _command_exists "pandoc"
  then
    _use_pandoc=0
  fi

  if [[ -n "${_input_file_path:-}"  ]]
  then
    _prepared_file_path="$(
      _render_prepare_file "${_input_file_path:-}" "${_use_pandoc:-0}"
    )"
  fi

  {
    # body
    if ((_use_pandoc))
    then
      if [[ -n "${_from:-}"                   ]]
      then
        _pandoc_arguments+=("--from=${_from:-}")
      elif [[ -z "${_prepared_file_path:-}"   ]] ||
           _contains "${_prepared_file_path##*.}" "md" "markdown"
      then
        _pandoc_arguments+=("--from=${NB_BROWSE_MARKDOWN_READER:-}")
      fi

      if ((${NB_MATHJAX_ENABLED:-0}))
      then
        _pandoc_arguments+=("--mathjax=/--mathjax/tex-chtml.js")
      fi

      {
        if _piped_input
        then
          _pandoc                             \
            --standard-input                  \
            "${_pandoc_arguments[@]:-}"       \
            2>/dev/null
        fi

        if [[ -n "${_prepared_file_path:-}"   ]]
        then
          _pandoc                             \
            "${_prepared_file_path:-}"        \
            "${_pandoc_arguments[@]:-}"       \
            2>/dev/null
        fi
      } | {
        if [[ -n "${_input_string}"           ]]
        then
          printf "%s\\n" "${_input_string}"   \
            | _pandoc                         \
                --standard-input              \
                "${_pandoc_arguments[@]:-}"   \
                2>/dev/null
        fi

        cat
      }
    else
      {
        if _piped_input
        then
          cat
        fi

        if [[ -n "${_prepared_file_path:-}"   ]]
        then
          if _file_is_text "${_prepared_file_path}"
          then
            cat "${_prepared_file_path}"
          else
            cat <<HEREDOC
File type not yet supported: ${_prepared_file_path##*.}
HEREDOC
          fi
        fi
      } | {
        if [[ -n "${_input_string}"           ]]
        then
          printf "%s\\n" "${_input_string}"
        fi

        cat
      }
    fi
  } | {
    # head
    if ! ((_only_body))
    then
      _render_print_head --title "${_html_title}"
    fi

    cat
  } | {
    # footer / tail
    cat

    if ! ((_only_body))
    then
      if ((${NB_ACE_ENABLED:-0}))
      then
        cat <<HEREDOC
<script src="/--ace/ace.js"></script>
<script src="/--ace/ext-modelist.js"></script>
<script>
  function initializeAceEditor() {
    var aceModeList = ace.require("ace/ext/modelist");

    var textarea    = document.querySelector('textarea');

    if (!textarea) return;

    var editDiv = document.createElement('div');

    editDiv.setAttribute(
      'style',
      'height:' + textarea.offsetHeight + 'px;' +
      'width:'  + textarea.offsetWidth  + 'px;'
    )

    editDiv.style.height    = textarea.offsetHeight + 'px';
    editDiv.style.width     = textarea.offsetWidth  + 'px';
    editDiv.classList.add(textarea.classList[0]);

    textarea.parentNode.insertBefore(editDiv, textarea);

    textarea.style.display  = 'none';

    var editor = ace.edit(editDiv);

    editor.getSession().setValue(textarea.value);

    var mode = aceModeList.getModeForPath('example.${_source_extension:-md}').mode;
    editor.getSession().setMode(mode);

    editor.setOptions({
      autoScrollEditorIntoView: true,
      copyWithEmptySelection:   true,
      displayIndentGuides:      true,
      fadeFoldWidgets:          true,
      fixedWidthGutter:         true,
      highlightActiveLine:      true,
      navigateWithinSoftTabs:   true,
      newLineMode:              'unix',
      printMargin:              false,
      relativeLineNumbers:      false,
      scrollPastEnd:            0.5,
      showFoldWidgets:          true,
      showGutter:               true,
      showInvisibles:           true,
      showLineNumbers:          true,
      tabSize:                  2,
      useSoftTabs:              true,
      wrap:                     false
    });

    if ('${_source_extension:-md}' === 'md') {
      if ('${NB_ACE_MD_GUTTER:-1}' === '1') {
        editor.setOptions({
          wrap:                 true
        });
      } else {
        editor.setOptions({
          wrap:                 true,
          showFoldWidgets:      false,
          showLineNumbers:      false,
          showGutter:           false
        });
      }
    }

    if ('${NB_ACE_RELATIVE_LINE_NUMBERS:-0}' === '1') {
      editor.setOptions({
        relativeLineNumbers:    true
      })
    }

    if ('${NB_ACE_SOFT_TABS:-0}' === '0') {
      editor.setOptions({
        useSoftTabs:            false
      })
    }

    var keyboard = '${NB_ACE_KEYBOARD:-ace}';

    if (['emacs', 'sublime', 'vim', 'vscode'].indexOf(keyboard) !== -1) {
      editor.setKeyboardHandler('ace/keyboard/' + keyboard);
    }

    editor.setTheme('ace/theme/${NB_ACE_THEME:-twilight}');

    textarea.form.addEventListener('submit', function() {
      textarea.value = editor.getSession().getValue();
    });
  }

  (function() {
    if (document.readyState !== 'loading') {
      setTimeout(initializeAceEditor, 0);
    } else {
      document.addEventListener('DOMContentLoaded', initializeAceEditor);
    }
  }());
</script>
HEREDOC
      fi

      if ((${NB_MATHJAX_ENABLED:-0}))
      then
        cat <<HEREDOC
<script id="MathJax-script" async src="/--mathjax/tex-chtml.js"></script>
HEREDOC
      fi

      cat <<HEREDOC
</body>
</html>
HEREDOC
    fi
  } | {
    if ((_filter_bookmark_content))
    then
      local _in_content=0

      {
        local               __line=
        while IFS= read -r  __line
        do
          if ! ((_in_content))  &&
             [[ "${__line:-}" =~  (^\<h2\ id=\"content\"|^\<h2\ id=\"page-content\") ]]
          then
            _in_content=1
          fi

          if ((_in_content))
          then
            # add line marker
            printf "%s-content-%s%s\\n" "${_ME}" "${_ME}" "${__line:-}"
          else
            printf "%s\\n" "${__line:-}"
          fi
        done
      } | {
        # strip bookmark <img> images
        LC_ALL=C sed -E -e "/^${_ME}-content-${_ME}/ s/<img[^>]*>//g"
      } | {
        # remove empty <p> paragraph elements
        LC_ALL=C sed -E -e "/^${_ME}-content-${_ME}/ s/.*<p>[ ]*<\/p>$//g"
      } | {
        # remove line marker
        LC_ALL=C sed -E -e "s/^${_ME}-content-${_ME}//g"
      }
    else
      cat
    fi
  } | {
    LC_ALL=C sed -e "s/<a\ /<a\ rel=\"noopener\ noreferrer\"\ /g"
  } | {
    # mark up checkboxes
    local _checkbox_pattern_open="<span class=\"muted\">[<\/span><span class=\"identifier\">"
    local _checkbox_pattern_close="<\/span><span class=\"muted\">\]<\/span>"

    LC_ALL=C sed -E                                                                       \
-e "1, /<textarea/ s/\[x\]/${_checkbox_pattern_open}x${_checkbox_pattern_close}/g"        \
-e "1, /<textarea/ s/\[ \]/${_checkbox_pattern_open}${_NBSP}${_checkbox_pattern_close}/g" \
-e "1, /<textarea/ s/\[\]/${_checkbox_pattern_open}${_NBSP}${_checkbox_pattern_close}/g"
  }
}

# _resolve_links()
#
# Usage:
#   <input> | _resolve_links <notebook-path> [--browse] [--limit <limit>]
#                            [--terminal] [--type <type>]
#
# Options:
#   --browse  Link to web server, link #tags, and redirect outbound links.
#
# Description:
#   Read standard input, resolve all [[wiki-style links]] and wrap each
#   one in a link to the target item, then print the updated file contents.
#   When the --browse option is specified, #tags are linked to the search
#   page for each tag and outbound links are updated to redirect through the
#   root level of the app to avoid leaking information via the referer header.
#
#   By default, links are created with file:// URLs to the item on the
#   local filesystem. With --browse, links are created with internal web
#   server URLs.
_resolve_links() {
  # Usage: <input> | _resolve_links_get_matches <pattern> [<path>]
  _resolve_links_get_matches() {
    local _arguments=()

    case "${1:-}" in
      '') return 1 ;;
      *)
        _arguments+=("-e" "${1:?}")
        [[ -n "${2:-}" ]] && _arguments+=("${2:-}")
        ;;
    esac

    if _command_exists "rg"
    then
      rg                      \
        --color=never         \
        --no-filename         \
        --only-matching       \
        --text                \
        "${_arguments[@]:-}"  \
        2>/dev/null || :
    else
      grep                    \
        --extended-regexp     \
        -h                    \
        --only-matching       \
        --text                \
        "${_arguments[@]:-}"  \
        2>/dev/null || :
    fi
  }

  local _bookmark=0
  local _columns="${NB_BROWSE_COLUMNS:-70}"
  local _for_browsing=0
  local _input_type="html"
  local _limit=
  local _terminal=0

  while ((${#}))
  do
    case "${1:-}" in
      --bookmark) _bookmark=1                                 ;;
      --browse)   _for_browsing=1                             ;;
      --col*)     _columns="${2:?}"                 && shift  ;;
      --limit|-n|--num|--number|--per*)
        _limit="${2:?}"

        shift
        ;;
      --page)     _option_value_is_present "${2:-}" && shift  ;;
      --terminal) _terminal=1                                 ;;
      --type)     _input_type="${2:?}"              && shift  ;;
      *)
        if [[ -z "${_notebook_path:-}"  ]]
        then
          _notebook_path="${1:-}"
        fi
        ;;
    esac

    shift
  done

  [[ ! -d "${_notebook_path:-}" ]] && return 1

  local _url_params_pattern=

  if ((_terminal))
  then
    _url_params_pattern="?--columns=${_columns:-}\&--limit=${_limit:-}"
  fi

  local _notebook_name="${_notebook_path##*/}"

  if [[ ! "${_notebook_path:-}" =~ ^${NB_DIR} ]]
  then
    _notebook_name="local"

    local _encoded_local_notebook_path=
    _encoded_local_notebook_path="$(
      _get_uri --encode "${_notebook_path:-}"
    )"

    case "${_url_params_pattern:-}" in
      '') _url_params_pattern+="?--local=${_encoded_local_notebook_path:-}"   ;;
      *)  _url_params_pattern+="\&--local=${_encoded_local_notebook_path:-}"  ;;
    esac
  fi

  # hashtag patterns

  local _hashtag_match_pattern="(^|${_ME}-linkable-${_ME}|[>|\ ])\#([A-Za-z0-9_\/\-]+)"
  local _hashtag_replacement_url="\/\/${NB_SERVER_HOST}:${NB_SERVER_PORT}\/${_notebook_name}:"

  case "${_url_params_pattern:-}" in
    '') _hashtag_replacement_url+="?--query=%23\\2"                         ;;
    *)  _hashtag_replacement_url+="${_url_params_pattern}\&--query=%23\\2"  ;;
  esac

  local _hashtag_pattern=

  case "${_input_type:-}" in
    html) _hashtag_pattern="<a\ href=\"${_hashtag_replacement_url//' '/%20}\">\#\\2<\/a>" ;;
    org)  _hashtag_pattern="[[${_hashtag_replacement_url//' '/%20}][\#\\2]]"              ;;
    *)    _hashtag_pattern="\#\\2"                                                        ;;
  esac

  # temp file

  local _input_temp_file_path=
  _input_temp_file_path="$(_temp file ".${_input_type}" --touch)"

  cat >> "${_input_temp_file_path}"

  {
    cat "${_input_temp_file_path}"
  } | {
    # link #hashtags to internal search URLs

    if ! ((_for_browsing)) || [[ "${_input_type:-}" == "html" ]]
    then
      cat
    else
      LC_ALL=C sed -E -e "s/${_hashtag_match_pattern}/\1${_hashtag_pattern}/g"
    fi
  } | {
    # resolve and link [[wiki-style links]]
    # TODO: HTML uses `sed` streaming replacement. The current Org
    # implementation uses querying to ensure link is not an
    # outbound URL, which requires a separate matching operation. The
    # match replacement code supports both HTML and Org, with HTML unused.

    if ((_for_browsing)) && [[ "${_input_type:-}" == "html" ]]
    then
      # patterns for wrapping [[wiki-style links]] in HTML links
      local _host_port_pattern="${NB_SERVER_HOST}:${NB_SERVER_PORT}"
      local _link_match_pattern="\[\[([^#|][^]|]*)\]\]"
      local _url_pattern="\/\/${_host_port_pattern}\/\1${_url_params_pattern:-}"
      local _replacement_pattern="<a\ href=\"${_url_pattern}\">[[\1]]<\/a>"

      local _labeled_link_match_pattern="\[\[([^#][^]|]+)\|([^]]+)\]\]"
      local _labeled_url_pattern="\/\/${_host_port_pattern}\/\1${_url_params_pattern:-}"
      local _labeled_replacement_pattern="<a\ href=\"${_labeled_url_pattern}\">[[\2]]<\/a>"

      # patterns for adding notebook prefixes to just-linked URLs
      local _notebookless_pattern="${_host_port_pattern}\/([^:?\"-]+[\?\"])"
      local _notebookless_replacement_pattern="${_host_port_pattern}\/${_notebook_name}:\1"

      local _linkable_initial=1

      if grep -q "<\/body>" "${_input_temp_file_path}"
      then
        _linkable_initial=0
      fi

      {
        local _linkable="${_linkable_initial}"

        local               __line=
        while IFS= read -r  __line
        do
          if ((_linkable))
          then
            if [[ "${__line:-}" =~ ^[[:space:]]*(<p[[:space:]]*>)?(<pre[[:space:]]*>)?\<(nav|code)  ]]
            then
              _linkable=0
            elif ((_bookmark)) && [[ "${__line:-}" =~ ^[[:space:]]*\<h2[^\<]*\>(Content|Source)     ]]
            then
              _linkable=0
            fi
          elif ! ((_linkable))
          then
            if [[ "${__line:-}" =~ ^[[:space:]]*\<body ]]
            then
              _linkable=1
            fi
          fi

          if ((_linkable))
          then
            printf "%s-linkable-%s%s\\n" "${_ME}" "${_ME}" "${__line:-}"
          else
            printf "%s\\n" "${__line:-}"
          fi

          if ((_linkable))
          then
            if [[ "${__line:-}" =~ ^[[:space:]]*\</body ]]
            then
              _linkable=0
            fi
          else
            if [[ "${__line:-}" =~ \<\/(nav|code)[[:space:]]*\>(</pre[[:space:]]*>)?(</p[[:space:]]*>)?[[:space:]]*$ ]]
            then
              _linkable=1
            fi
          fi
        done
      } | {
        # Replace [[ with placeholder INSIDE <code>...</code> (including <p><code>)
        LC_ALL=C sed -E                                                         \
          -e 's/(<code[^>]*>[^<]*)\[\[([^<]*<\/code>)/\1__LEFTDBLBRACKET__\2/g' \
          -e 's/(<p[[:space:]]*><code[^>]*>[^<]*)\[\[([^<]*<\/code>[[:space:]]*<\/p>)/\1__LEFTDBLBRACKET__\2/g'
      } | {
        # Replace # with placeholder INSIDE <code>...</code> (including <p><code>)
        LC_ALL=C sed -E                                                         \
          -e 's/(<code[^>]*>[^<]*)\#([^<]*<\/code>)/\1__HASH_PLACEHOLDER__\2/g' \
          -e 's/(<p[[:space:]]*><code[^>]*>[^<]*)\#([^<]*<\/code>[[:space:]]*<\/p>)/\1__HASH_PLACEHOLDER__\2/g'
      } | {
        # wrap [[wiki-style links]] in HTML links and add missing notebooks
        LC_ALL=C sed -E                                                                           \
-e "/^${_ME}-linkable-${_ME}/ s/${_link_match_pattern}/${_replacement_pattern}/g"                 \
-e "/^${_ME}-linkable-${_ME}/ s/${_labeled_link_match_pattern}/${_labeled_replacement_pattern}/g" \
-e "/^${_ME}-linkable-${_ME}/ s/${_notebookless_pattern}/${_notebookless_replacement_pattern}/g"  \
-e "/^${_ME}-linkable-${_ME}/ s/${_hashtag_match_pattern}/\1${_hashtag_pattern}/g"
      } | {
        LC_ALL=C sed -E                   \
          -e 's/__LEFTDBLBRACKET__/[[/g'  \
          -e 's/__HASH_PLACEHOLDER__/#/g'
      } | {
        LC_ALL=C sed -E -e "s/^${_ME}-linkable-${_ME}//g"
      }
    else
      local __match=
      for   __match in  $(_resolve_links_get_matches  \
                          "\[\[[^\[]+\]\]"            \
                          "${_input_temp_file_path}")
      do
        local _link=
        local _link_label=

        [[ -z "${__match:-}" ]] && continue

        local _selector="${__match#[[}"

        if [[ "${__match}" =~ \| ]]
        then
          _selector="${_selector%%|*}"

          _link_label="${__match##*|}"
          _link_label="${_link_label%]]}"
        else
          _selector="${_selector%]]}"
          _link_label="${_selector}"
        fi

        if ((_for_browsing))
        then
          if [[ -z "${_selector:-}" ]]
          then
            _link="${__match}"
          else
            local _link_notebook_name=
            local _query_selector=

            if [[ "${_selector:-}" =~ : ]] && [[ ! "${_selector:-}" =~ :// ]]
            then
              _link_notebook_name="${_selector%%:*}"
              _query_selector="${_selector}"
            else
              _link_notebook_name="${_notebook_name}"
              _query_selector="${_link_notebook_name}:${_selector}"
            fi

            local _selector_path=
            _selector_path="$(_selector_resolve_path "${_query_selector:-}")"

            local _id_selector=
            _id_selector="$(
              _get_id_selector "${_link_notebook_name}:${_selector_path}" 2>/dev/null || :
            )"

            if [[ -n "${_selector#*:}" ]] && [[ -z "${_selector_path:-}" ]]
            then
              _link="[[${_selector:-}]]"
            else
              local _target_url="//${NB_SERVER_HOST}:${NB_SERVER_PORT}/${_id_selector}${_url_params_pattern:-}"

              case "${_input_type:-}" in
                html)
                  _link="<a href=\"${_target_url//' '/%20}\">[[${_link_label:-}]]</a>"
                  ;;
                org)
                  _link="[[${_target_url:-}][[[${_link_label:-}]]]]"
                  ;;
                *)
                  _link="[[${_selector:-}]]"
                  ;;
              esac
            fi
          fi
        else
          local _link_path=
          _link_path="$(_show "${_selector}" --path 2>/dev/null || :)"

          if [[ -z "${_link_path:-}" ]]
          then
            _link="[[${_selector}]]"
          else
            case "${_input_type:-}" in
              html)
                _link="<a href=\"file://${_link_path//' '/%20}\">[[${_link_label:-}]]</a>"
                ;;
              org)
                _link="[[file://${_link_path//' '/%20}][[[${_link_label:-}]]]]"
                ;;
              *)
                _link="[[${_selector:-}]]"
                ;;
            esac
          fi
        fi

        local _escaped_match="${__match//${_SLASH}/\\/}"
        _escaped_match="${_escaped_match//\[/\\[}"
        _escaped_match="${_escaped_match//\]/\\]}"
        _escaped_match="${_escaped_match//\(/\(}"
        _escaped_match="${_escaped_match//\)/\)}"

        local _escaped_replacement="${_link//${_SLASH}/\\/}"
        _escaped_replacement="${_escaped_replacement//\[/\\[}"
        _escaped_replacement="${_escaped_replacement//\]/\\]}"
        _escaped_replacement="${_escaped_replacement//\(/\(}"
        _escaped_replacement="${_escaped_replacement//\)/\)}"

        if [[ -n "${_escaped_match:-}"        ]] &&
           [[ -n "${_escaped_replacement:-}"  ]] &&
           ! _contains "${_escaped_match}" "${_seen_matches[@]:-}"
        then
          _sed_arguments+=("-e" "s/${_escaped_match}/${_escaped_replacement}/g")
          _seen_matches+=("${_escaped_match}")
        fi
      done

      LC_ALL=C sed "${_sed_arguments[@]:-}"
    fi
  } | {
    # rewrite outbound links to use an exit page

    if ! ((_for_browsing))
    then
      cat
    else
      local _outbound_url_pattern=

      case "${_input_type:-}" in
        org)  _outbound_url_pattern="\[\[https?://[^]]+"      ;;
        html) _outbound_url_pattern="href=\"https?://[^\"]+"  ;;
      esac

      local _sed_arguments=()
      local _seen_matches=()

      local __match=
      for   __match in  $(_resolve_links_get_matches    \
                          "${_outbound_url_pattern:-}"  \
                          "${_input_temp_file_path}")
      do
        [[ -z "${__match:-}" ]] && continue

        if [[ "${__match}" =~ https?://${NB_SERVER_HOST} ]]
        then
          continue
        fi

        case "${_input_type:-}" in
          org)  local _target_url="${__match#\[\[}"     ;;
          html) local _target_url="${__match#href=\"}"  ;;
        esac

        # NOTE: skip _get_uri() for performance
        # use ${_SLASH} for macOS bash support

        local _encoding="${_target_url//'%'/%25}"
        _encoding="${_encoding//' '/%20}"
        _encoding="${_encoding//'"'/%22}"
        _encoding="${_encoding//'#'/%23}"
        _encoding="${_encoding//'$'/%24}"
        _encoding="${_encoding//'&'/%26}"
        _encoding="${_encoding//'+'/%2B}"
        _encoding="${_encoding//','/%2C}"
        _encoding="${_encoding//${_SLASH}/%2F}"
        _encoding="${_encoding//':'/%3A}"
        _encoding="${_encoding//';'/%3B}"
        _encoding="${_encoding//'='/%3D}"
        _encoding="${_encoding//'?'/%3F}"
        _encoding="${_encoding//'@'/%40}"
        _encoding="${_encoding//'['/%5B}"
        local _encoded_url="${_encoding//']'/%5D}"

        local _replacement_url="//${NB_SERVER_HOST}:${NB_SERVER_PORT}?url=${_encoded_url}"
        local _replacement="${_replacement_url}"

        case "${_input_type:-}" in
          org)
            if [[ "${__match:-}" =~ ^\[\[ ]]
            then
              _replacement="[[${_replacement}"
            fi
            ;;
          html)
            _replacement="href=\"${_replacement}"
            ;;
        esac

        local _escaped_match="${__match//${_SLASH}/\\/}"
        _escaped_match="${_escaped_match//\[/\\[}"
        _escaped_match="${_escaped_match//\]/\\]}"
        _escaped_match="${_escaped_match//\(/\(}"
        _escaped_match="${_escaped_match//\)/\)}"

        local _escaped_replacement="${_replacement//${_SLASH}/\\/}"
        _escaped_replacement="${_escaped_replacement//\[/\\[}"
        _escaped_replacement="${_escaped_replacement//\]/\\]}"
        _escaped_replacement="${_escaped_replacement//\(/\(}"
        _escaped_replacement="${_escaped_replacement//\)/\)}"

        if [[ -n "${_escaped_match:-}"        ]] &&
           [[ -n "${_escaped_replacement:-}"  ]] &&
           ! _contains "${_escaped_match}" "${_seen_matches[@]:-}"
        then
          _sed_arguments+=("-e" "s/${_escaped_match}/${_escaped_replacement}/g")
          _seen_matches+=("${_escaped_match}")
        fi
      done

      LC_ALL=C sed "${_sed_arguments[@]:-}"
    fi
  }
}

# _web_browser()
#
# Usage:
#   _web_browser [[<url>] [--dump] | --check]
#
# Options:
#   --check   Return with status 0 if a browser is available, or 1 if not.
#   --dump    Print the page to standard output.
#
# Description:
#   Interact with the preferred or available terminal web browser. When called
#   with no input or arguments, or with only the --check option, test if a
#   terminal web browser is available. With <url> or standard input, view in
#   the preferred or available browser.
#
# Exit / Error / Return Status:
#   0 (success, true)  If a terminal browser is available.
#   1 (error,  false)  if not.
_web_browser() {
  local _arguments=()
  local _check=0
  local _check_gui=0
  local _dump=0
  local _url=
  local _web_browser_command=()

  local __arg=
  for   __arg in "${@:-}"
  do
    case "${__arg}" in
      --check)
        _check=1
        ;;
      --dump|--print)
        _dump=1
        ;;
      --gui)
        _check_gui=1
        ;;
      *)
        [[ -z "${_url:-}" ]] && _url="${__arg}"
        ;;
    esac
  done

  if [[ -n "${NB_BROWSER:-}" ]]
  then
    _web_browser_command=("${NB_BROWSER}")
  else
    if _command_exists "w3m"
    then
      _web_browser_command+=("w3m")
    elif _command_exists "links"
    then
      _web_browser_command+=("links")
    fi
  fi

  # checks

  if [[ -z "${_web_browser_command[*]:-}" ]]
  then
    _warn cat <<HEREDOC
Web browser not found. Try \`w3m\`: $(_color_primary "http://w3m.sourceforge.net")
HEREDOC
    exit 1
  fi

  if ((_check_gui))
  then
    shopt -s nocasematch

    if [[ "${_web_browser_command[*]}" =~ (firefox|chrom|brave|edg) ]]
    then
      return 0
    else
      return 1
    fi

    shopt -u nocasematch
  fi

  if ((_check))
  then
    if ((_dump)) && [[ -n "${_web_browser_command[*]:-}" ]]
    then
      printf "%s\\n" "${_web_browser_command[*]:-}"
    fi

    return 0
  fi

  # behaviors

  if ! _piped_input && [[ -z "${_url:-}"        ]]
  then
    return 0
  else
    if [[ "${_web_browser_command[*]:-}" =~ w3m ]]
    then
      _web_browser_command+=("-I" "UTF-8")
      _web_browser_command+=("-O" "UTF-8")

      if [[ -n "${_url:-}" ]]
      then
        _web_browser_command+=("${_url:-}")
      fi

      if ((_dump))
      then
        "${_web_browser_command[@]:-}" -T text/html -dump
      else
        "${_web_browser_command[@]:-}" -T text/html 2>/dev/null
      fi

      return 0
    elif [[ "${_web_browser_command[*]:-}" =~ lynx    ]]
    then
      ((_dump)) && _arguments+=("-dump")

      if [[ -n "${_url:-}" ]]
      then
        _arguments+=("${_url:-}")
      else
        _arguments+=("-stdin")
      fi

      _arguments+=("-nomargins")
      _arguments+=("-noreferer")
      _arguments+=("-notitle")

      "${_web_browser_command[@]:-}" "${_arguments[@]:-}"

      return 0
    elif [[ "${_web_browser_command[*]:-}" =~ links   ]]
    then
      ((_dump)) && _arguments+=("-dump")

      if [[ ! "${_web_browser_command[*]}" =~ elinks  ]]
      then # links
        _arguments+=("-html-assume-codepage" "Unicode UTF-8")
      fi

      if [[ -n "${_url:-}" ]]
      then
        _arguments+=("${_url:-}")
      fi

      "${_web_browser_command[@]:-}" "${_arguments[@]:-}"
    else
      if [[ -n "${_url:-}" ]]
      then
        _web_browser_command+=("${_url:-}")
      fi

      "${_web_browser_command[@]}"

      return 0
    fi
  fi
}

###############################################################################
# Subcommands: Group 2                                     Subcommands: Group 2
# --------------------                                     --------------------
###############################################################################
# --------------------------------------------------------------------------- #

# add ##################################################################### add

_describe_add() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} add [<notebook>:][<folder-path>/][<filename>] [<content>]
         [-b | --browse] [-c <content> | --content <content>] [--edit]
         [-e | --encrypt] [-f <filename> | --filename <filename>]
         [--folder <folder-path>] [--no-template] [--tags <tag1>,<tag2>...]
         [--template <template>] [-t <title> | --title <title>] [--type <type>]
  ${_ME} add bookmark [<bookmark-options>...]
  ${_ME} add folder [<name>]
  ${_ME} add todo [<todo-options>...]

$(_color_primary "Options"):
  -b, --browse                Add using a terminal or GUI web browser.
  -c, --content <content>     The content for the new note.
  --edit                      Open the note in the editor before saving when
                              content is piped or passed as an argument.
  -e, --encrypt               Encrypt the note with a password.
  -f, --filename <filename>   The filename for the new note.
  --folder <folder-path>      Add within the folder located at <folder-path>.
  --no-template               Skip the template when one is assigned.
  --tags <tag1>,<tag2>...     A comma-separated list of tags.
  --template <template>       A string template or path to a template file.
  -t, --title <title>         The title for a new note. If \`--title\` is
                              present, the filename is derived from the
                              title, unless \`--filename\` is specified.
  --type <type>               The file type for the new note, as a file
                              extension.

$(_color_primary "Description"):
  Create a new note or folder.

  If no arguments are passed, a new blank note file is opened with \`\$EDITOR\`,
  currently set to: ${NB_EDITOR}

  If a non-option argument is passed, \`${_ME}\` will treat it as a <filename≥
  if a file extension is found. If no file extension is found,  \`${_ME}\` will
  treat the string as <content> and will create a new note without opening the
  editor. \`${_ME} add\` can also create a new note with piped content.

  \`${_ME}\` creates Markdown files by default. To create a note with a
  different file type, use the extension in the filename or use the \`--type\`
  option. To change the default file type, use \`${_ME} set default_extension\`.

  When the \`-e\` / \`--encrypt\` option is used, \`${_ME}\` will encrypt the
  note with AES-256 using OpenSSL by default, or GPG, if configured in
  \`${_ME} set encryption_tool\`.

$(_color_primary "Read More"):
  ${_README_URL}#adding

$(_color_primary "See Also"):
  ${_ME} help bookmark
  ${_ME} help browse
  ${_ME} help delete
  ${_ME} help edit
  ${_ME} help folders
  ${_ME} help import
  ${_ME} help show
  ${_ME} help todo

$(_color_primary "Examples"):
  ${_ME} add
  ${_ME} add example.md
  ${_ME} add "Note content."
  ${_ME} add example.md --title "Example Title" --content "Example content."
  echo "Note content." | ${_ME} add
  ${_ME} add -t "Secret Document" --encrypt
  ${_ME} add example/document.md
  ${_ME} add folder sample/demo
  ${_ME} example:add
  ${_ME} example:add -t "Title"
  ${_ME} a
  ${_ME} a "Note content."
  ${_ME} example:a
  ${_ME} example:a -t "Title"

$(_color_primary "Aliases"):
  ${_ME} create
  ${_ME} new

$(_color_primary "Shortcut Aliases"):
  ${_ME} a
  ${_ME} +
HEREDOC
}
_add() {
  local _add_type=
  local _arguments=()
  local _browse=0
  local _defer_arguments=()
  local _edit_before_commit=0
  local _encrypt=0
  local _file_type="${NB_DEFAULT_EXTENSION}"
  local _folder_prompt=0
  local _no_template=0
  local _option_content=
  local _option_folder_relative_path=
  local _option_relative_path=
  local _password=
  local _skip_standard_input=0
  local _tag_list=
  local _template=
  local _title=

  while ((${#}))
  do
    case "${1:-}" in
      -b|-br|--browse)
        _browse=1
        ;;
      -c|--content)
        if [[ -z "${2:-}"                   ]]
        then
          _exit_1 printf                          \
            "%s requires a valid argument.\\n"    \
            "$(_color_primary "${1:-}")"
        else
          if [[ -n "${_option_content:-}"   ]]
          then
            _option_content+="${_NEWLINE}${_NEWLINE}"
          fi

          _option_content+="$(printf "%s\\n" "${2:-}")"
          _defer_arguments+=("${1}" "${2:-}")

          shift
        fi
        ;;
      --edit)
        _edit_before_commit=1
        ;;
      -e|--encrypt*)
        if [[ -z "${NB_ENCRYPTION_TOOL:-}"  ]]  ||
           ! _command_exists "${NB_ENCRYPTION_TOOL:-}"
        then
          _exit_1 printf                        \
            "Encryption tool not found: %s\\n"  \
            "$(_color_primary "${NB_ENCRYPTION_TOOL:-}")"
        else
          _encrypt=1
        fi
        ;;
      -f|--file*|--*path|--target*)
        _option_relative_path="$(_option_get_value "${1}" "${2:-}")"
        _defer_arguments+=("${1}" "${2:-}")

        shift
        ;;
      --folder)
        _option_folder_relative_path="$(
          _option_get_value "${1}" "${2:-}" | LC_ALL=C sed -e 's/\/$//'
        )"
        _defer_arguments+=("${1}" "${_option_folder_relative_path:-}")

        shift
        ;;
      --folder*prompt)
        _folder_prompt=1
        ;;
      --no*color)
        _COLOR_ENABLED=0
        ;;
      --no*template|--skip*template)
        _no_template=1
        ;;
      --password)
        _password="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      --quiet)
        _QUIET=1
        ;;
      --skip*standard*input)
        _skip_standard_input=1
        ;;
      --tag*)
        [[ -n "${_tag_list:-}" ]] && _tag_list+=" "
        _tag_list+="$(_option_get_tags "${1}" "${2:-}")"
        _defer_arguments+=("${1}" "${2:-}")

        shift
        ;;
      --template)
        _template="${2:-}"
        _defer_arguments+=("${1}" "${2:-}")

        [[ -z "${2:-}" ]] && _no_template=1

        shift
        ;;
      -t|--title|--name)
        # TODO: Detect tag list for dynamic -t for --titles and --tags?
        _title="$(_option_get_value "${1}" "${2:-}")"
        _defer_arguments+=("${1}" "${2:-}")

        shift
        ;;
      --type)
        _file_type="$(_option_get_value "${1}" "${2:-}")"
        _defer_arguments+=("${1}" "${2:-}")

        shift
        ;;
      bookmark)
        _add_type="bookmark"
        ;;
      folder|folders|directory)
        _file_type="folder"
        _defer_arguments+=("${1}")
        ;;
      todo)
        _add_type="todo"
        ;;
      *)
        _arguments+=("${1:-}")
        ;;
    esac

    shift
  done

  case "${_add_type:-}" in
    bookmark)
      _defer "_bookmark"    "${_arguments[@]:-}" "${_defer_arguments[@]:-}"

      return 0
      ;;
    todo)
      _defer "_todo" "add"  "${_arguments[@]:-}" "${_defer_arguments[@]:-}"

      return 0
      ;;
  esac

  if ((_browse))
  then
    _defer "_browse" "add"  "${_arguments[@]:-}" "${_defer_arguments[@]:-}"

    return 0
  fi

  local _common_tlds_excluding_text_file_extensions=(
    app agency au com company biz blog buzz ca cloud club de design dev cf ch
    cn edu email es fr fun ga gov guru icu info it jp link life live ly media
    mil net new nl no online nyc page rocks ru se shop site solutions space
    store tech top tk tv uk us vip wang website work xyz
  )

  local _notebook_path=
  _notebook_path="$(_notebooks current --path)"

  local _selector_content=
  local _selector_filename=
  local _selector_folder_relative_path=

  local i=
  for ((i=0; i < ${#_arguments[@]}; i++))
  do
    local _argument_content=

    if [[ -n "${_arguments[i]:-}"         ]]
    then # argument is not blank
      if [[ -z "${_selector_content:-}"   ]]  &&
         [[ -n "${_selector_filename:-}"  ]]
      then # argument #2 and the first argument was a selector with filename
        _argument_content+="${_arguments[i]:-}"
      else
        local _content_or_filename_extension=
        local _selector_notebook_path=
        local _selector_relative_path="${_arguments[i]}"

        if [[ "${_arguments[i]:-}" =~ \.[A-Za-z0-9]+$ ]]
        then # argument appears to be a file extension
          _content_or_filename_extension="${_arguments[i]##*\.}"
        fi

        if _string_is_url    "${_arguments[i]:-}"           ||
           _string_is_email  "${_arguments[i]:-}"           ||
           _contains "${_content_or_filename_extension:-}"  \
                     "${_common_tlds_excluding_text_file_extensions[@]}"
        then # argument contains content
          _argument_content+="${_arguments[i]:-} "
        else
          if [[ "${_arguments[i]}" =~ (:|^/)                ]]
          then
            if [[ -n "${_selector_filename:-}"              ]] ||
               [[ -n "${_selector_folder_relative_path:-}"  ]]
            then
              _argument_content+="${_arguments[i]:-} "
            else
              _selector_notebook_path="$(
                _notebook show "${_arguments[i]%%:*}" --path 2>/dev/null || :
              )"

              if [[ -n "${_selector_notebook_path}"         ]]
              then # argument is a selector with a valid notebook
                _notebook_path="${_selector_notebook_path}"

                if [[ "${_arguments[i]:-}" =~ ^/            ]]
                then
                  _selector_relative_path="${_arguments[i]#${_notebook_path}/}"
                else
                  _selector_relative_path="${_arguments[i]#*:}"
                fi
              else # argument is not a selector
                _argument_content+="${_arguments[i]:-} "
              fi
            fi
          fi

          if [[ -z "${_argument_content:-}"                 ]]
          then # still a candidate selector
            if [[ "${_selector_relative_path:-}" =~ /       ]] &&
               [[ -z "${_selector_folder_relative_path:-}"  ]]
            then # argument appears to contain a relative path
              _selector_folder_relative_path="${_selector_relative_path%\/*}"
            fi

            if [[ -z "${_option_relative_path}"                     ]]  &&
               [[ -z "${_selector_filename}"                        ]]  &&
               {
                 _contains "${_file_type:-}" "folder" "directory"       ||
                 [[ "${_arguments[i]:-}" =~ (\.[A-Za-z0-9]+$|/|:)   ]]
               }
            then
              _selector_filename="${_selector_relative_path##*\/}"
            elif [[ -n "${_selector_content:-}"             ]]
            then
              _argument_content+="${_arguments[i]:-} "
            elif [[ !   "${_selector_relative_path}" =~ /$  ]] &&
                 [[ -z  "${_selector_notebook_path:-}"      ]]
            then
              _selector_folder_relative_path=""
              _argument_content+="${_arguments[i]:-} "
            fi
          fi
        fi
      fi
    fi

    if [[ -n "${_argument_content:-}" ]]
    then
      _selector_content+="${_argument_content}"
    fi
  done

  if [[ -n "${_selector_content:-}"   ]]
  then
    _selector_content="${_selector_content%\ }"
  fi

  # Filename
  # --------

  local _target_filename=

  if [[ -n "${_option_relative_path:-}"   ]]
  then
    _target_filename="${_option_relative_path##*\/}"
  elif [[ -n "${_selector_filename:-}"    ]]
  then
    _target_filename="${_selector_filename:-}"
  fi

  if [[ -z "${_target_filename:-}"        ]] &&
     [[ -z "${_option_relative_path:-}"   ]]
  then
    if [[ -n "${_title:-}" ]] &&
       ! _contains "${_file_type:-}" "folder" "directory"
    then
      _target_filename="$(_get_sanitized_filename "${_title}")"
    fi

    if [[ -n "${_file_type}"              ]] &&
       [[ "${_file_type:-}" != "folder"   ]]
    then
      # NOTE: ${_target_filename} can be blank, resulting in '.type'
      _target_filename="${_target_filename:-}.${_file_type}"
    elif [[ "${_file_type:-}" == "folder" ]] &&
         [[ -z "${_target_filename:-}"    ]]
    then
      _target_filename="folder"
    fi
  fi

  _target_filename="$(_normalize_encoding "${_target_filename}")"

  # Folder
  # ------

  local _target_folder_relative_path=

  if [[ "${_option_relative_path}" =~ /           ]]
  then
    _target_folder_relative_path="${_option_relative_path%%\/*}"
  fi

  if [[ -n "${_option_folder_relative_path:-}"    ]]
  then
    _target_folder_relative_path="${_option_folder_relative_path}/${_target_folder_relative_path:-}"
  fi

  if [[ -n "${_selector_folder_relative_path:-}"  ]]
  then
    _resolved_selector_folder_relative_path="$(
      _selector_resolve_folders               \
        "${_selector_folder_relative_path}/"  \
        --build || :
    )"

    if [[ -n "${_resolved_selector_folder_relative_path:-}" ]]
    then
      _target_folder_relative_path="${_resolved_selector_folder_relative_path:-}/${_target_folder_relative_path}"
    fi
  fi

  _target_folder_relative_path="${_target_folder_relative_path%/}"

  # Target
  # ------

  local _target_relative_path="${_target_folder_relative_path:-}/${_target_filename:-}"
  _target_relative_path="${_target_relative_path#/}"

  local _target_unique_relative_path=

  if [[     "${_target_relative_path}" =~ ^\..* ]] &&
     [[ -n  "${_option_relative_path:-}"        ]]
  then
    local _target_unique_path=
    _target_unique_path="$(
      _get_unique_path "${_notebook_path}/${_target_relative_path}"
    )"

    _target_unique_relative_path="${_target_unique_path#"${_notebook_path}"/}"
  else
    _target_unique_relative_path="$(
      _notebooks current --filename "${_target_relative_path}"
    )"
  fi

  local _target_basename=
  _target_basename="$(basename "${_target_unique_relative_path}")"

  local _target_path="${_notebook_path}/${_target_unique_relative_path}"

  if _contains "${_file_type:-}" "folder" "directory"
  then
    if ! mkdir -p "${_target_path:?}" 2>/dev/null
    then
      _exit_1 printf "Unable to create folder: %s\\n"       \
        "$(_color_primary "${_target_unique_relative_path}")"
    fi

    touch "${_target_path:?}/.index"

    if [[ -n "${_target_folder_relative_path:-}" ]]
    then
      _index reconcile                                      \
        "${_notebook_path}/${_target_folder_relative_path}" \
        --ancestors
    fi
  else
    if ((_encrypt))
    then
      if [[ -z "${_password}"                   ]] &&
         [[ "${NB_ENCRYPTION_TOOL:-}" != "age"  ]]
      then
        # request password without displaying it
        printf "%s: " "$(_color_primary "Password")"

        local _password=
        IFS='' read -r -e -d $'\n' -s _password </dev/tty

        if [[ -z "${_password:-}"               ]]
        then
          _exit_1 printf "Password required.\\n"
        fi

        local _password_confirmation=

        # request password without displaying it
        printf "%s: " "$(_color_primary "Confirm Password")"

        local _password_confirmation=
        IFS='' read -r -e -d $'\n' -s _password_confirmation </dev/tty

        if [[ "${_password}" != "${_password_confirmation}" ]]
        then
          _exit_1 printf "Password mismatch.\\n"
        fi
      fi

      if [[ -n "${_target_folder_relative_path:-}"  ]]
      then
        if ! mkdir -p "$(_temp directory)/${_target_folder_relative_path}" 2>/dev/null
        then
          _exit_1 printf "Unable to create temporary folder: %s\\n" \
            "$(_color_primary "$(_temp directory)/${_target_folder_relative_path}")"
        fi
      fi

      _target_path="$(_temp directory)/${_target_unique_relative_path}"
    fi

    if [[ -n "${_target_folder_relative_path:-}"                      ]] &&
       [[ ! -d "${_notebook_path}/${_target_folder_relative_path:-}"  ]]
    then
      if [[ -e "${_notebook_path}/${_target_folder_relative_path:-}"  ]]
      then
        _exit_1 printf "File exists at: %s\\n"  \
          "$(_color_primary "${_target_folder_relative_path:-}")"
      else
        if ((_folder_prompt))
        then
          local _target_folder_selector="${_target_folder_relative_path:-}/"

          if _notebooks current --selected
          then
            _target_folder_selector="$(_notebooks current --name):${_target_folder_selector}"
          fi

          printf "Creating new folder: %s\\n"   \
            "$(_color_primary "${_target_folder_selector}")"

          while true
          do
            local __yn=
            IFS='' read -r -e -d $'\n' -p       \
"$(_color_primary "Proceed?") $(_color_brackets "y/N") " __yn

            case "${__yn}" in
              [Yy]*)
                break
                ;;
              *)
                printf "Exiting...\\n"

                exit 0
                ;;
            esac
          done
        fi

        if ! mkdir -p "${_notebook_path:?}/${_target_folder_relative_path}" 2>/dev/null
        then
          _exit_1 printf "Unable to create folder: %s\\n" \
            "$(_color_primary "${_target_folder_relative_path}")"
        fi
      fi
    fi

    local _title_prefix=

    case "${_target_path:-}" in
      *.adoc|*.asciidoc)
        _title_prefix="="
        ;;
      *.org)
        _title_prefix="#+TITLE:"
        ;;
      *)
        _title_prefix="#"
        ;;
    esac

    # prepare content

    local _content_temp_file_path=
    _content_temp_file_path="$(_temp file --touch)"

    local _piped_content_temp_file_path=
    _piped_content_temp_file_path="$(_temp file --touch)"

    local _print_content_spacing=0

    if [[ -n "${_selector_content:-}"   ]]
    then # argument content
      printf "%s\\n" "${_selector_content}"   >> "${_content_temp_file_path}"
      _print_content_spacing=1
    fi

    if [[ -n "${_option_content:-}"     ]]
    then # argument content
      ((_print_content_spacing)) &&
        printf "\\n"                          >> "${_content_temp_file_path}"

      printf "%s\\n" "${_option_content}"     >> "${_content_temp_file_path}"
      _print_content_spacing=1
    fi

    if _piped_input && ! ((_skip_standard_input))
    then # piped input
      ((_print_content_spacing)) &&
        printf "\\n"                          >> "${_content_temp_file_path}"

      cat                                     >> "${_piped_content_temp_file_path}"
      cat "${_piped_content_temp_file_path}"  >> "${_content_temp_file_path}"
    fi

    # set default template

    if [[ -z "${_template:-}"           ]]  &&
       [[ -n "${NB_DEFAULT_TEMPLATE:-}" ]]
    then
      _template="${NB_DEFAULT_TEMPLATE}"
    fi

    # build document

    if [[ -z "${_template:-}"           ]] ||
       ((_no_template))
    then # no template
      if [[ -n "${_title}"              ]]
      then
        printf "%s\\n\\n" "${_title_prefix} ${_title}" >> "${_target_path}"
      fi

      local _print_spacing=0

      if [[ -n "${_tag_list:-}"         ]]
      then
        printf "%s\\n" "${_tag_list}"       >> "${_target_path}"
        _print_spacing=1
      fi

      if [[ -s "${_content_temp_file_path:-}"          ]]
      then
        ((_print_spacing)) && printf "\\n"  >> "${_target_path}"

        cat "${_content_temp_file_path}"    >> "${_target_path}"
      fi
    else # template
      local _template_content=
      _template_content="$(cat "${_content_temp_file_path}")"

      local _piped_template_content=
      _piped_template_content="$(cat "${_piped_content_temp_file_path}")"

      {
        if [[ -f "${_template}" ]] && _file_is_text "${_template}"
        then
          cat "${_template}"
        else
          printf "%s\\n" "${_template}"
        fi
      } | {
        # shellcheck disable=SC2016
        LC_ALL=C sed -E                                           \
          -e 's/\{\{title_prefix}}/${_title_prefix}/g'            \
          -e 's/\{\{title}}/${_title}/g'                          \
          -e 's/\{\{tags}}/${_tag_list}/g'                        \
          -e 's/\{\{content}}/${_template_content}/g'             \
          -e 's/\{\{selector_content}}/${_selector_content}/g'    \
          -e 's/\{\{option_content}}/${_option_content}/g'        \
          -e 's/\{\{piped_content}}/${_piped_template_content}/g' \
          -e 's/\{\{(date[^}]+)}}/$(\1)/g'
      } | {
        eval "echo \"$(cat)\""
      } >> "${_target_path}"
    fi

    if ((_edit_before_commit))              ||
       {
         ! _piped_input                     &&
         [[ -z "${_selector_content:-}" ]]  &&
         [[ -z "${_option_content:-}"   ]]
       }
    then
      _edit_file "${_target_path}"
    fi

    # walk up and delete empty directories when file not created
    if [[ ! -e "${_target_path:?}"                                    ]] &&
       [[   -n "${_target_folder_relative_path:-}"                    ]] &&
       [[   -e "${_notebook_path:?}/${_target_folder_relative_path}"  ]]
    then
      cd "${_notebook_path:?}/${_target_folder_relative_path:?}"

      while [[ "${PWD:?}" =~ ^${_notebook_path:?}       ]] &&
            [[ "${PWD:?}" != "${_notebook_path:?}"      ]] &&
            [[ -z "$(find "${PWD}/." ! -name . -prune)" ]]
      do
        local _empty_directory_path="${PWD:?}"

        cd ..

        if [[ -d "${_empty_directory_path:?}"                             ]] &&
           [[ -z "$(find "${_empty_directory_path}/." ! -name . -prune)"  ]]
        then
          rm -r "${_empty_directory_path:?}"
        fi
      done
    fi

    if ((_encrypt)) && [[ -e "${_target_path}" ]]
    then
      _target_basename="${_target_basename}.enc"

      local _decrypted_path="${_target_path}"
      local _encrypted_path="${_notebook_path}/${_target_unique_relative_path}.enc"

      _encrypt_file           \
        "${_decrypted_path}"  \
        "${_encrypted_path}"  \
        --password "${_password}"

      if [[ -n "${_decrypted_path}" ]] && [[ -e "${_decrypted_path}" ]]
      then
        rm "${_decrypted_path:?}"
      fi

      _target_unique_relative_path="${_target_unique_relative_path}.enc"
      _target_path="${_encrypted_path}"
    fi
  fi

  if [[ -e "${_target_path}"              ]]
  then
    if [[ ! "${_target_path##*/}" =~ ^\.  ]]
    then
      _index add                          \
        "${_target_basename}"             \
        "${_notebook_path:?}/${_target_folder_relative_path:-}"
    fi && _git checkpoint                 \
      "${_notebook_path}"                 \
      "[${_ME}] Add: ${_target_unique_relative_path}"

    local _info=
    _info="$(
      _show "${_notebook_path:?}/${_target_unique_relative_path:?}" --info-line
    )"

    if ! ((_QUIET))
    then
      printf "Added: %s\\n" "${_info}"
    fi
  fi
}
_alias_subcommand "add" "+"
_alias_subcommand "add" "a"
_alias_subcommand "add" "create"
_alias_subcommand "add" "new"

# bookmark ########################################################### bookmark

_describe_bookmark() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} bookmark [<ls-options>...]
  ${_ME} bookmark [<notebook>:][<folder-path>/] <url>...
              [-c <comment> | --comment <comment>] [--edit] [-e | --encrypt]
              [-f <filename> | --filename <filename>] [--no-request]
              [-q <quote> | --quote <quote>] [--save-source]
              [-r (<url> | <selector>) | --related (<url> | <selector>)]...
              [-t <tag1>,<tag2>... | --tags <tag1>,<tag2>...] [--title <title>]
  ${_ME} bookmark list [<list-options>...]
  ${_ME} bookmark (edit | delete | open | peek | url)
              ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
  ${_ME} bookmark search <query>

$(_color_primary "Options"):
  -c, --comment <comment>      A comment or description for this bookmark.
  --edit                       Open the bookmark in your editor before saving.
  -e, --encrypt                Encrypt the bookmark with a password.
  -f, --filename <filename>    The filename for the bookmark. It is
                               recommended to omit the extension so the
                               default bookmark extension is used.
  --no-request                 Don't request or download the target page.
  -q, --quote <quote>          A quote or excerpt from the saved page.
                               Alias: \`--excerpt\`
  -r, --related <selector>     A selector for an item related to the
                               bookmarked page.
  -r, --related <url>          A URL for a page related to the bookmarked page.
                               Multiple \`--related\` flags can be used in a
                               command to save multiple related URLs and
                               selectors.
  --save-source                Save the page source as HTML.
  -t, --tags <tag1>,<tag2>...  A comma-separated list of tags.
  --title <title>              The bookmark title. When not specified,
                               \`${_ME}\` will use the html <title> tag.

$(_color_primary "Subcommands"):
  (default)  Add a new bookmark for <url>, or list bookmarks.
             Bookmarks can also be added with \`${_ME} <url>\`
  delete     Delete a bookmark.
  edit       Edit a bookmark.
  list       List bookmarks in the current notebook.
             Shortcut Alias: \`ls\`
  open       Open the bookmarked page in your system's primary web browser.
             Shortcut Alias: \`o\`
  peek       Open the bookmarked page in your terminal web browser.
             Alias: \`preview\`
             Shortcut Alias: \`p\`
  search     Search bookmarks for <query>.
             Shortcut Alias: \`q\`
  url        Print the URL for the specified bookmark.

$(_color_primary "Description"):
  Create, view, search, edit, and delete bookmarks.

  By default, the html page content is saved within the bookmark, making the
  bookmarked page available for full-text search. When Pandoc [1] is
  installed, the HTML content is converted to Markdown before saving.
  When readability-cli [2] is install, markup is cleaned up to focus on
  content.

  \`peek\` opens the page in \`w3m\` [3] or \`links\` [4] when available.
  To specify a preferred browser, set the \`\$BROWSER\` environment variable
  in your .bashrc, .zshrc, or equivalent, e.g.: export BROWSER="links"

  Bookmarks are identified by the \`.bookmark.md\` file extension. The
  bookmark URL is the first URL in the file within "<" and ">" characters:

    <https://www.example.com>

    1. https://pandoc.org/
    2. https://gitlab.com/gardenappl/readability-cli
    3. https://en.wikipedia.org/wiki/W3m
    4. https://en.wikipedia.org/wiki/Links_(web_browser)

$(_color_primary "Read More"):
  ${_README_URL}#-bookmark

$(_color_primary "See Also"):
  ${_ME} help browse
  ${_ME} help open
  ${_ME} help peek
  ${_ME} help show

$(_color_primary "Examples"):
  ${_ME} https://example.com
  ${_ME} example: https://example.com
  ${_ME} https://example.com --encrypt
  ${_ME} https://example.com --tags example,sample,demo
  ${_ME} https://example.com/about -c "Example comment."
  ${_ME} https://example.com/faqs -f example-filename
  ${_ME} https://example.com --quote "Example quote or excerpt."
  ${_ME} bookmark list
  ${_ME} bookmark search "example query"
  ${_ME} bookmark open 5
  ${_ME} bk

$(_color_primary "Shortcut Aliases"):
  ${_ME} bk
  ${_ME} bm
HEREDOC
}
_bookmark() {
  # Usage: _bookmark_cleanup_tag_content <string>
  _bookmark_cleanup_tag_content() {
    local _character_removal_pattern=
    _character_removal_pattern="$(
      printf "\xE2\x80\xAA|\xE2\x80\xAB|\xE2\x80\xAC"
    )"

    # `awk` condenses and trims whitespace
    # `sed` removes select unicode characters
    # `w3m` converts HTML entities
    printf "%s\\n" "${1:-}"                                     \
      | awk '$1=$1'                                             \
      | LC_ALL=C sed -E -e "s/${_character_removal_pattern}//g" \
      | if _command_exists "w3m"
        then
           w3m -dump -T text/html -cols 9999
         else
           cat
        fi
  }

  # Usage: _bookmark_view_in_terminal_browser (<url>)
  _bookmark_view_in_terminal_browser() {
    local _target_url="${1:-}"

    if _web_browser --check
    then
      _web_browser "${_target_url}"

      return 0
    elif _command_exists "curl" || _command_exists "wget"
    then
      _download_from "${_target_url}"               \
        | if _command_exists "pandoc"
          then
            _pandoc                                 \
              --standard-input                      \
              --from  html-native_divs-native_spans \
              --to    markdown                      \
              | _highlight_syntax_if_available "md"
          else
            cat
          fi | _pager

      return 0
    else
      _exit_1 printf "Terminal web browser not detected.\\n"
    fi
  }

  local _arguments=()
  local _bookmark_content=
  local _comment=
  local _content_cleanup_tool="readability"
  local _content_conversion_tool="pandoc"
  local _edit_before_commit=0
  local _encrypt=0
  local _non_url_arguments=()
  local _password=
  local _quote=
  local _related_identifiers=()
  local _request_page=1
  local _save_source=0
  local _secondary_urls=()
  local _selector=
  local _skip_content=0
  local _skip_folder_prompt=0
  local _subcommand=
  local _tag_list=
  local _target_filename=
  local _title=
  local _url=

  if [[ -n "${NB_BOOKMARK_CONTENT_CLEANUP_TOOL+x}"    ]]
  then
    _content_cleanup_tool="${NB_BOOKMARK_CONTENT_CLEANUP_TOOL}"
  fi

  if [[ -n "${NB_BOOKMARK_CONTENT_CONVERSION_TOOL+x}" ]]
  then
    _content_conversion_tool="${NB_BOOKMARK_CONTENT_CONVERSION_TOOL}"
  fi

  local _previous_arg=

  local __arg=
  for   __arg in "${@:-}"
  do
    if [[ "${_previous_arg:-}" =~ ^-- ]] ||
       ! _string_is_url "${__arg:-}"
    then
      _non_url_arguments+=("${__arg:-}")
    fi

    _previous_arg="${__arg:-}"
  done

  while ((${#}))
  do
    case "${1:-}" in
      -c|--comment*)
        _comment="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      --content*cleanup*tool)
        _content_cleanup_tool="${2:-}"

        shift
        ;;
      --content*conversion*tool)
        _content_conversion_tool="${2:-}"

        shift
        ;;
      --download|--fetch|--online|--request)
        _request_page=1
        ;;
      --edit)
        _edit_before_commit=1
        ;;
      -e|--encrypt*)
        _encrypt=1
        ;;
      -f|--filename)
        _target_filename="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      --no*download|--no*fetch|--no*request|--offline)
        _request_page=0
        ;;
      --password)
        _password="$(_option_get_value "${1}" "${2:-}")"
        _arguments+=("${1:-}" "${2:-}")

        shift
        ;;
      --quiet)
        _QUIET=1
        ;;
      -q|--quote|--excerpt)
        _quote="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      -r|--via|--also|--related)
        _related_identifiers+=("$(_option_get_value "${1}" "${2:-}")")

        shift
        ;;
      --save*source|--source|--save*html|--html|--raw*content|--raw*html)
        _save_source=1
        ;;
      --skip*content|--no*content)
        _skip_content=1
        ;;
      --skip*folder*prompt)
        _skip_folder_prompt=1
        ;;
      -t|--tag*)
        _tag_list="$(_option_get_tags "${1}" "${2:-}")"

        shift
        ;;
      --title)
        _title="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      d|delete|remove|rm|trash|-)
        _delete "${2:-}" "${3:-}"

        return 0
        ;;
      edit)
        _edit "${2:-}"

        return 0
        ;;
      help)
        _help "bookmark"

        return 0
        ;;
      ls|list)
        _subcommand="list"
        ;;
      search|q)
        _subcommand="search"
        ;;
      open|o|peek|p|preview|url)
        if _option_value_is_present "${2:-}"
        then
          if [[ "${1}" =~ (^open$|^o$)  ]]
          then
            _subcommand="open"
          elif [[ "${1}" =~ (^peek$|^p$|^preview$) ]]
          then
            _subcommand="peek"
          elif [[ "${1}" == "url"       ]]
          then
            _subcommand="url"
          fi

          _selector="${2:-}"

          shift
        else
          _exit_1                                     \
            printf "%s requires a valid argument.\\n" \
            "$(_color_primary "bookmark ${1}")"
        fi
        ;;
      *)
        if [[ ! "${_subcommand:-}"  =~ (^list$|^search$)  ]] &&
           _string_is_url "${1}"
        then
          if [[ -z "${_url:-}" ]]
          then
            _url="${1}"
          else
            _secondary_urls+=("${1}")
          fi
        elif [[ -z "${_subcommand:-}"                     ]] ||
             [[ "${_subcommand}"    =~ (^list$|^search$)  ]]
        then
          if [[ "${1:-}" =~ (:|^/) ]] && [[ -z "${_selector:-}" ]]
          then
            _selector="${1:-}"
          fi

          _arguments+=("${1}")
        fi
        ;;
    esac

    shift
  done

  _debug echo "\${_content_cleanup_tool}: '${_content_cleanup_tool:-}'"
  _debug echo "\${_content_conversion_tool}: '${_content_conversion_tool:-}'"

  # `bookmark list`

  if [[ "${_subcommand}" == "list"  ]]
  then
    if [[ -n "${_arguments[*]:-}"   ]]
    then
      _list --bookmarks "${_arguments[@]}"

      return 0
    else
      _list --bookmarks

      return 0
    fi
  fi

  # `bookmark search`

  if [[ "${_subcommand}" == "search" ]]
  then
    _search --bookmarks "${_arguments[@]}"

    return 0
  fi

  # `bookmark open`, `bookmark peek`, `bookmark url`

  {
    if [[ "${_subcommand}" =~ (^open$|^peek$|^url$) ]]
    then
      local _relative_path=
      _relative_path="$(_show "${_selector}" --relative-path)"

      local _notebook_path=
      _notebook_path="$(_notebooks current --path)"

      if [[ -z "${_relative_path}"                  ]]
      then
        if [[ "${_subcommand}" =~ (^open$|^peek$)   ]]
        then
          local _maybe_notebook="${_selector:-}"
          _maybe_notebook="$(
            printf "%s\\n" "${_maybe_notebook}" | LC_ALL=C sed 's/\:$//'
          )"

          if [[ -d "${NB_DIR}/${_maybe_notebook}/.git" ]]
          then
            _notebooks "${_subcommand}" "${_maybe_notebook}" && return 0
          fi
        fi
        _exit_1 printf "Not found: %s\\n" "$(_color_primary "${_selector}")"
      fi

      local _target_path="${_notebook_path}/${_relative_path}"

      # handle non-bookmarks
      if [[ "${_subcommand}" =~ (^open$|^peek$) ]]
      then
        if [[ "${_relative_path}" =~ \.html$  ]]
        then
          if [[ "${_subcommand}" == "open"  ]]
          then
            _open_in_gui_app "${_target_path:-}" && return 0
          elif [[ "${_subcommand}" == "peek"  ]]
          then
            _bookmark_view_in_terminal_browser "file://${_target_path}"

            return 0
          fi
        elif [[ ! "${_relative_path}" =~ .bookmark\.md$       ]] &&
             [[ ! "${_relative_path}" =~ .bookmark\.md\.enc$  ]]
        then
          if [[ "${_subcommand}" == "open"    ]]
          then
            if [[ -d "${_target_path:-}"      ]] &&
               _open_in_gui_app "${_target_path:-}"
            then
              return 0
            elif [[ -n "${_password}"         ]]
            then
              _edit "${_selector}" --password "${_password}"
            else
              _edit "${_selector}"
            fi
          elif [[ "${_subcommand}" == "peek"  ]]
          then
            if [[ -n "${_password}"           ]]
            then
              _show "${_selector}" --password "${_password}"
            else
              _show "${_selector}"
            fi
          fi

          return 0
        fi
      fi

      local _target_url=
      _target_url="$(_show "${_target_path}" --url "${_arguments[@]:-}")"

      if [[ "${_subcommand}" == "url"           ]]
      then
        printf "%s\\n" "${_target_url}"

        return 0
      fi

      if [[ "${_subcommand}" =~ (^open$|^peek$) ]]
      then
        local _check_wayback=0
        local _http_error_codes=(
          404 408 410 451 500 502 503 504 509 520 521 523 524 525 526
        )
        local _http_status=
        _http_status="$(_get_http_status "${_target_url}")"

        if _contains "${_http_status}" "${_http_error_codes[@]}"
        then
          printf "Page no longer available: %s\\n" \
            "$(_color_primary "${_target_url}")"

          while true
          do
            local __yn=
            IFS='' read -r -e -d $'\n' -p \
"Check the Wayback Machine for an archived version instead? $(_color_brackets "y/N") " __yn

            case "${__yn}" in
              [Yy]*)
                _check_wayback=1

                break
                ;;
              *)
                break
                ;;
            esac
          done
        fi

        if ((_check_wayback))
        then
          local _wayback_response=
          _wayback_response="$(
            _download_from --no-chrome                                    \
              "https://archive.org/wayback/available?url=${_target_url}"  \
              | grep 'closest'                                            \
              | LC_ALL=C sed -E "s/.*\"closest\": {([^}]+)}.*/\1/g"       \
              | LC_ALL=C sed -E "s/.*\"url\": \"([^\"]+)\".*/\1/g" || printf ""
          )"

          if [[ -n "${_wayback_response:-}" ]]
          then
            _target_url="${_wayback_response}"
          else
            _exit_1 printf                  \
              "No archived version available from the Wayback Machine.\\n"
          fi
        fi
      fi

      # `bookmark peek`
      if [[   "${_subcommand}" == "peek"    ]]
      then
        _bookmark_view_in_terminal_browser "${_target_url}"

        return 0
      # `bookmark open`
      elif [[ "${_subcommand}" == "open"    ]]
      then
        if _open_in_gui_app "${_target_url:-}"
        then
          return 0
        else
          _exit_1 printf                                          \
            "%s doesn't know how to open URLs on this system.\\n" \
            "$(_color_primary "${_ME}")"
        fi
      fi
    fi
  }

  # `bookmark`

  if [[   -z "${_url:-}"          ]]
  then
    if [[ -z "${_arguments[*]:-}" ]]
    then
      local _line_length=36
      local _maybe_header_selector=

      if _notebooks current --selected
      then
        _maybe_header_selector="$(
          _notebooks show "$(_notebooks current)" --no-color --escaped
        ): "

        local _padded_header_selector_length=
        _padded_header_selector_length="$(
          _get_visible_length "${_maybe_header_selector}"
        )"

        _line_length="$((_line_length + _padded_header_selector_length))"
      fi

      local _header=
      _header="Add: $(_color_primary "${_ME} ${_maybe_header_selector}<url>")"
      _header="${_header} Help: $(_color_primary "${_ME} help bookmark")"

      printf "%s\\n" "${_header}"
      _print_line "$(printf "%-${_line_length}s" '.')"
    fi

    _bookmark list "${_arguments[@]:-}"

    return 0
  fi

  # `bookmark <url>`

  if ((${#_secondary_urls[@]}))
  then
    local __url=
    for   __url in "${_url}" "${_secondary_urls[@]}"
    do
      # shellcheck disable=SC2046
      _bookmark "${__url}" $(printf "%s\\n" "${_non_url_arguments[@]}")
    done

    return 0
  fi

  local _temp_file=
  _temp_file="$(_temp file)"

  local _download_url="${_url}"
  _download_url="$(
    printf "%s\\n" "${_download_url}"       \
      | LC_ALL=C sed 's/https:\/\/twitter.com/https:\/\/mobile.twitter.com/g'
  )"

  if [[ "${_selector}" =~ (:|^/)  ]]
  then
    _notebooks select "${_selector}"
  fi

  local _relative_folder_path=
  local _relative_path=

  _relative_folder_path="$(
    _selector_resolve_folders "${_arguments[0]:-}" --build || :
  )"

  if [[ -n "${_relative_folder_path:-}"     ]]
  then
    _relative_folder_path="${_relative_folder_path}/"
  fi

  if [[ -z "${_target_filename:-}"          ]]
  then
    _relative_path="$(
      _notebooks current --filename         \
        "${_relative_folder_path}$(date '+%Y%m%d%H%M%S').bookmark.md"
    )"
  else
    if [[ "${_target_filename}" =~ \.       ]]
    then
      _relative_path="$(
        _notebooks current --filename       \
          "${_relative_folder_path}${_target_filename}")"
    else
      _relative_path="$(
        _notebooks current --filename       \
          "${_relative_folder_path}${_target_filename}.bookmark.md"
      )"
    fi
  fi

  local _notebook_path=
  _notebook_path="$(_notebooks current --path)"

  local _duplicate_search_path="${_notebook_path}"

  if [[ -n "${_relative_folder_path:-}"     ]]
  then
    _duplicate_search_path="${_notebook_path}/${_relative_folder_path}"
  fi

  if [[ -d "${_duplicate_search_path:-}"    ]]
  then
    local _grep_command=(
      grep -s                         \
        -e "^<${_download_url}>"      \
        -e "^##"
    )

    if ((_GIT_ENABLED))
    then
      _grep_command=(
        git -C "${_notebook_path:-}"  \
          grep                        \
          -e "^<${_download_url}>"    \
          -e "^##"                    \
          --no-heading                \
          --color=never
      )
    elif _command_exists "rg"
    then
      _grep_command=(
        rg                            \
          --color never               \
          --no-heading                \
          --with-filename             \
          -e "^##"                    \
          -e "^<${_download_url}>"
      )
    fi

    local _candidate_matches=()
    _candidate_matches=($(
      set +o noglob

      "${_grep_command[@]:-}"                     \
        "${_duplicate_search_path}/"*.bookmark.md \
        2>/dev/null || :

      set -o noglob
    ))

    local _duplicate_matches=()

    if ((${#_candidate_matches[@]}))
    then
      local _current_filename=
      local _include_match=1

      local __candidate_match=
      for   __candidate_match in "${_candidate_matches[@]:-}"
      do
        if [[ "${_current_filename:-}" != "${__candidate_match%%:*}"  ]]
        then
          _current_filename="${__candidate_match%%:*}"
          _include_match=1
        fi

        if [[ "${__candidate_match#*:}" =~ ^##                        ]]
        then
          _include_match=0
        fi

        if ((_include_match))
        then
          _duplicate_matches+=("${_current_filename:-}")

          _include_match=0
        fi
      done
    fi

    if ((${#_duplicate_matches[@]}))
    then
      if [[ "${#_duplicate_matches[@]}" == "1" ]]
      then
        printf      \
"1 bookmark for this URL exists in this folder:\\n"
      _print_line   \
"----------------------------------------------"
      else
        printf      \
"%s bookmarks for this URL exist in this folder:\\n" "${#_duplicate_matches[@]}"
        _print_line \
"${#_duplicate_matches[@]}----------------------------------------------"
      fi

      local __duplicate_match=
      for   __duplicate_match in "${_duplicate_matches[@]:-}"
      do
        _show --info-line "${__duplicate_match%%:*}"
      done

      _print_line "------------------------------"

      while true
      do
        local __yn=
        IFS='' read -r -e -d $'\n' -p \
"$(_color_primary "Create another bookmark?") $(_color_brackets "y/N") " __yn

        case "${__yn}" in
          [Yy]*)
            break
            ;;
          *)
            printf "Exiting%s\\n" "$(_color_muted "...")"

            exit 0
            ;;
        esac
      done
    fi
  fi 1>&2

  if ((_request_page))
  then
    if ! _download_from "${_download_url}" "${_temp_file}" ||
       [[ ! -e "${_temp_file}"                          ]] ||
       [[ "$(wc -c <"${_temp_file}")" == 0              ]]
    then
      _warn printf                            \
        "Unable to download page at %s\\n"    \
        "$(_color_primary "${_url}")"
    fi
  fi

  if _file_is_text "${_temp_file}"
  then
    if [[ -z "${_title:-}"  ]] &&
       [[ "${_url:-}" =~ ^https://www.reddit.com ]]
    then
      _title="$(
        cat "${_temp_file}"                   \
          | grep '<shreddit-title title="'    \
          | sed -n 's/.*<shreddit-title title="\([^"]*\)".*/\1/p'
      )"
    fi

    if [[ -z "${_title:-}"  ]]
    then
      _title="$(
        cat "${_temp_file}"                   \
          | if _command_exists 'iconv'
            then
              iconv -c -t utf-8
            else
              cat
            fi                                \
          | awk '/<title[^>]*>/,/<\/title>/'  \
          | LC_ALL=C sed -e '/<\/title>/ q'   \
          | LC_ALL=C sed -e 's/<\/title>.*//' \
          | LC_ALL=C sed                      \
            -e 's/.*<title[^>]*>//'           \
            -e 's/.*<TITLE[^>]*>//'           \
            -e 's/<\/title>.*//'              \
            -e 's/<\/TITLE>.*//'              \
          | awk '$1=$1'     ||  :
      )"
    fi

    if [[ -z "${_title:-}"  ]]
    then
      _title="$(
        cat "${_temp_file}"     \
          | LC_ALL=C sed -E -n  \
            "s/.*<meta .*property=.og:title[^>]*content=\"([^\"]+)\".*/\1/p" \
            2>/dev/null     ||  :
      )"
    fi
  fi

  local _domain=
  _domain="$(printf "%s\\n" "${_url}" | awk -F[/:] '{print $4}')"

  if [[ -n "${_domain:-}"   ]]
  then
    [[ -n "${_title:-}"     ]]  && _title+=" "
    _title+="(${_domain})"
  fi

  if [[ -n "${_title:-}"    ]]
  then
    _title="$(_bookmark_cleanup_tag_content "${_title}")"

    _bookmark_content="# ${_title}${_NEWLINE}${_NEWLINE}"
  fi

  _bookmark_content+="<${_url}>${_NEWLINE}"

  if _file_is_text "${_temp_file}"
  then
    local _description=
    _description="$(
      cat "${_temp_file}"       \
        | LC_ALL=C sed -E -n    \
            "s/.*<meta .*name=.description.[^>]*content=\"([^\"]+)\".*/\1/p" \
            2>/dev/null     ||  :
    )"

    if [[ -z "${_description:-}"    ]]
    then
      _description="$(
        cat "${_temp_file}"     \
          | LC_ALL=C sed -E -n  \
              "s/.*<meta .*property=.og:description[^>]*content=\"([^\"]+)\".*/\1/p" \
              2>/dev/null   ||  :
      )"
    fi

    if [[ -n "${_description:-}"    ]]
    then
      _description="$(_bookmark_cleanup_tag_content "${_description}")"

      _bookmark_content+="${_NEWLINE}## Description${_NEWLINE}"
      _bookmark_content+="${_NEWLINE}${_description}${_NEWLINE}"
    fi
  fi

  if [[ -n "${_quote:-}"            ]]
  then
    _bookmark_content+="${_NEWLINE}## Quote${_NEWLINE}"

    local _counter=0

    local               __line=
    while IFS= read -r  __line
    do
      if ! ((_counter))
      then
        _bookmark_content+="${_NEWLINE}> ${__line}${_NEWLINE}"
      elif [[ -z "${__line:-}"      ]]
      then
        _bookmark_content+=">${_NEWLINE}"
      else
        _bookmark_content+="> ${__line}${_NEWLINE}"
      fi

      _counter="$((_counter+1))"
    done <<< "${_quote}"
  fi

  if [[ -n "${_comment:-}"          ]]
  then
    _bookmark_content+="${_NEWLINE}## Comment${_NEWLINE}"
    _bookmark_content+="${_NEWLINE}${_comment}${_NEWLINE}"
  fi

  if [[ -n "${_related_identifiers[*]:-}" ]]
  then
    _bookmark_content+="${_NEWLINE}## Related${_NEWLINE}${_NEWLINE}"
    _bookmark_content+="$(_build_related_list "${_related_identifiers[@]:-}")"
    _bookmark_content+="${_NEWLINE}"
  fi

  if [[ -n "${_tag_list:-}"         ]]
  then
    _bookmark_content+="${_NEWLINE}## Tags${_NEWLINE}"
    _bookmark_content+="${_NEWLINE}${_tag_list}${_NEWLINE}"
  fi

  if _file_is_text "${_temp_file}"
  then
    if ! ((_skip_content))
    then
      local _processed_content=

      if  {
            [[ "${_content_conversion_tool:-}"  == "pandoc"   ]] &&
            _command_exists "pandoc"
          } || {
            [[ "${_content_cleanup_tool:-}"     =~ readab     ]] &&
            _command_exists "readable"
          } || {
            [[ "${_content_cleanup_tool}"       == "rdrview"  ]] ||
            _contains "${_content_conversion_tool}" \
                      "html2markdown"               \
                      "html-to-markdown"            \
                      "markitdown"
          }
      then
        _processed_content="$(
          {
            cat "${_temp_file}"
          } | {
            if [[ "${_content_cleanup_tool:-}"  =~ readab     ]] &&
               _command_exists "readable"
            then # https://www.npmjs.com/package/readability-cli
              readable            \
                --base "${_url}"  \
                --quiet           \
                2>/dev/null || cat
            else
              cat
            fi
          } | {
            if [[ "${_content_cleanup_tool}"    == "rdrview"  ]] &&
               _command_exists "rdrview"
            then # https://github.com/eafer/rdrview
              rdrview -H -u "${_url}"
            else
              cat
            fi
          } | {
            if [[ "${_content_conversion_tool:-}"  == "markitdown"  ]] &&
               _command_exists "markitdown"
            then # https://github.com/microsoft/markitdown
              markitdown
            else
              cat
            fi
          } | {
            if [[ "${_content_conversion_tool:-}"  == "pandoc"      ]]
               _command_exists "pandoc"
            then # https://pandoc.org
              {
                _pandoc                                 \
                  --standard-input                      \
                  --from  html-native_divs-native_spans \
                  --to    markdown-grid_tables          \
                  --wrap=none                           \
                  2>/dev/null || cat
              } | {
                # strip empty list items
                LC_ALL=C sed -E -e 's/^-[[:space:]]*$//g'
              }
            else
              cat
            fi
          } | {
            if _contains  "${_content_conversion_tool}" \
                          "html2markdown"               \
                          "html-to-markdown"            &&
               _command_exists "html2markdown"
            then # https://github.com/JohannesKaufmann/html-to-markdown
              html2markdown
            else
              cat
            fi
          }
        )"

        if [[ -n "${_processed_content}"  ]]
        then
          _bookmark_content+="${_NEWLINE}## Content${_NEWLINE}"
          _bookmark_content+="${_NEWLINE}${_processed_content}${_NEWLINE}"
        fi
      else
        _save_source=1
      fi
    fi

    if ((_save_source))
    then
      _bookmark_content+="${_NEWLINE}## Source${_NEWLINE}"
      _bookmark_content+="${_NEWLINE}${_BT}${_BT}${_BT}html${_NEWLINE}"
      _bookmark_content+="$(cat "${_temp_file}")"
      _bookmark_content+="${_NEWLINE}${_BT}${_BT}${_BT}${_NEWLINE}"
    fi
  fi

  if [[ -n "${_bookmark_content}"         ]]
  then

    local _add_options=(
      "${_relative_path}"
      --content "${_bookmark_content}"
      --skip-standard-input
      --no-template
    )

    ((_encrypt))                &&  _add_options+=("--encrypt")
    ((_edit_before_commit))     &&  _add_options+=("--edit")
    [[ -n "${_password:-}"  ]]  &&  _add_options+=("--password" "${_password}")

    if ! ((_skip_folder_prompt))
    then
      _add_options+=("--folder-prompt")
    fi

    _add "${_add_options[@]}"

    [[ -f "${_temp_file:-}" ]]  &&  rm -f "${_temp_file:?}"

    return 0
  fi
}
_alias_subcommand "bookmark" "bk"
_alias_subcommand "bookmark" "bm"
_alias_subcommand "bookmark" "bookmarks"

# completions ##################################################### completions

_describe_completions() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} completions (check | install [-d | --download] | uninstall)

$(_color_primary "Options"):
  -d, --download  Download the completion scripts and install.

$(_color_primary "Description"):
  Manage completion scripts.

$(_color_primary "Read More"):
  https://github.com/${_REPO}/blob/${_REPO_MAIN_BRANCH}/etc/README.md

$(_color_primary "See Also"):
  ${_ME} help env
HEREDOC
}
_completions() {
  local _BASH_COMP_NAME="${_ME}"
  local _FISH_COMP_NAME="${_ME}.fish"
  local _ZSH_COMP_NAME="_${_ME}"

  # Usage: _completions_check
  _completions_check() {
    local _exists=0

    local __shell=
    for   __shell in bash fish zsh
    do
      local _completion_path=
      local _completion_target=

      case "${__shell}" in
        bash)
          _completion_path="$(_get_bash_completion_path)"
          _completion_target="${_completion_path}/${_BASH_COMP_NAME}"
          ;;
        fish)
          _completion_path="$(_get_fish_completion_path)"
          _completion_target="${_completion_path}/${_FISH_COMP_NAME}"
          ;;
        zsh)
          _completion_path="/usr/local/share/zsh/site-functions"
          _completion_target="${_completion_path}/${_ZSH_COMP_NAME}"
          ;;
      esac

      if [[ -d "${_completion_path}"        ]]
      then
        if [[ -w "${_completion_path}"      ]]
        then
          if [[ -e "${_completion_target}"  ]]
          then
            _exists=1

            printf "Exists: %s\\n" "${_completion_target}"
          fi
        else
          _warn printf "Permission denied: %s\\n" "${_completion_path}"
        fi
      fi
    done

    if ! ((_exists))
    then
      _exit_1 printf "Completion scripts not found.\\n"
    fi
  }

  # Usage: _get_bash_completion_path
  _get_bash_completion_path() {
    local _bash_completion_path=

    if [[ -n "${BASH_COMPLETION_COMPAT_DIR:-}"  ]]
    then
      _bash_completion_path="${BASH_COMPLETION_COMPAT_DIR}"
    fi

    if [[ -z "${_bash_completion_path:-}"       ]]
    then
      local _maybe_path=
      _maybe_path="$(
        pkg-config --variable=completionsdir bash-completion 2>/dev/null || :
      )"

      if [[ -n "${_maybe_path:-}"               ]]
      then
        _bash_completion_path="${_maybe_path}"
      fi
    fi

    if [[ -z "${_bash_completion_path:-}"       ]] &&
       [[ -d "/usr/local/etc/bash_completion.d" ]]
    then
      _bash_completion_path="/usr/local/etc/bash_completion.d"
    fi

    if [[ -z "${_bash_completion_path:-}"       ]] &&
       [[ -d "/etc/bash_completion.d"           ]]
    then
      _bash_completion_path="/etc/bash_completion.d"
    fi

    printf "%s\\n" "${_bash_completion_path:-}"
  }

  # Usage: _get_fish_completion_path
  _get_fish_completion_path() {
    local _fish_completion_path=

    if [[ -z "${_fish_completion_path:-}"                 ]] &&
       [[ -d "/usr/local/share/fish/vendor_completions.d" ]]
    then
      _fish_completion_path="/usr/local/share/fish/vendor_completions.d"
    fi

    if [[ -z "${_fish_completion_path:-}"       ]]
    then
      local _maybe_path=
      _maybe_path="$(
        pkg-config --variable=completionsdir fish 2>/dev/null || :
      )"

      if [[ -n "${_maybe_path:-}"               ]]
      then
        _fish_completion_path="${_maybe_path}"
      fi
    fi

    if [[ -z "${_fish_completion_path:-}"                 ]] &&
       [[ -d "/usr/share/fish/vendor_completions.d"       ]]
    then
      _fish_completion_path="/usr/share/fish/vendor_completions.d"
    fi

    printf "%s\\n" "${_fish_completion_path:-}"
  }

  _get_zsh_completion_path() {
      local _zsh_completion_path=

      if [[ -z "${_zsh_completion_path:-}"                 ]] &&
         [[ -d "/usr/local/share/zsh/site-functions" ]]
      then
        _zsh_completion_path="/usr/local/share/zsh/site-functions"
      fi

      if [[ -z "${_zsh_completion_path:-}"                 ]] &&
         [[ -d "/usr/share/zsh/site-functions"       ]]
      then
        _zsh_completion_path="/usr/share/zsh/site-functions"
      fi

      printf "%s\\n" "${_zsh_completion_path:-}"
  }

  # Usage: _completions_install [--download]
  _completions_install() {
    local _download=0
    if [[ "${1:-}" == "--download"  ]]
    then
      _download=1
    fi

    local _my_path="${0}"

    if [[ -L "${_my_path}"          ]]
    then
      _my_path="$(_resolve_symlink "${_my_path}")"
    fi

    local _my_dir=
    _my_dir="$(cd "$(dirname "${_my_path}")"; pwd)"
    if [[ -z "${_my_dir}"   ]]  ||  [[ ! -d "${_my_dir}"        ]]
    then
      exit 1
    fi

    if [[ -z "${_REPO:-}"   ]]  ||  [[ -z "${_REPO_RAW_URL:-}"  ]]
    then
      _exit_1 printf "Source Git repository not configured.\\n"
    fi

    local __shell=
    for   __shell in bash fish zsh
    do
      local _completion_source="${_my_dir}/etc/${_ME}-completion.${__shell}"

      if ((_download))
      then
        if [[ ! -f "${_completion_source}"  ]]
        then
          _completion_source="$(_temp file)"
          local _completion_url="${_REPO_RAW_URL}/etc/${_ME}-completion.${__shell}"

          if ! _download_from "${_completion_url}" "${_completion_source}" --no-chrome
          then
            _exit_1 printf "Unable to download completion script from %s\\n" \
              "${_completion_source}"
          fi
        fi
      fi

      if [[ ! -f "${_completion_source}"    ]]
      then
        cat <<HEREDOC
Unable to find source ${__shell} completion script. You can try downloading
and installing the latest version with the following command (\`sudo\` might
be necessary):
  ${_ME} completions install --download

More Information: ${__shell}
  https://github.com/${_REPO}/blob/${_REPO_MAIN_BRANCH}/etc/README.md
HEREDOC
      else
        local _completion_path=
        local _completion_target=

        case "${__shell}" in
          bash)
            _completion_path="$(_get_bash_completion_path)"
            _completion_target="${_completion_path}/${_BASH_COMP_NAME}"
            ;;
          fish)
            _completion_path="$(_get_fish_completion_path)"
            _completion_target="${_completion_path}/${_FISH_COMP_NAME}"
            ;;
          zsh)
            _completion_path="$(_get_zsh_completion_path)"
            _completion_target="${_completion_path}/${_ZSH_COMP_NAME}"
            ;;
        esac

        if [[ -n "${_completion_path:-}"        ]] &&
           [[ -d "${_completion_path}"          ]]
        then
          if [[ -w "${_completion_path}"        ]]
          then
            if [[ ! -e "${_completion_target}"  ]]
            then
              cp                                \
                "${_completion_source}"         \
                "${_completion_target}"

              chmod +r "${_completion_target}"

              printf "Completion script installed: %s\\n" \
                "${_completion_target}"
            else
              _warn printf "Exists: %s\\n" "${_completion_target}"
            fi
          else
            _warn printf "Permission denied: %s\\n" "${_completion_path}"
          fi
        fi
      fi
    done
  }

  # Usage: _completions_uninstall
  _completions_uninstall() {
    local _completion_path=
    local _completion_target=

    local __shell=
    for   __shell in bash fish zsh
    do
      case "${__shell}" in
        bash)
          _completion_path="$(_get_bash_completion_path)"
          _completion_target="${_completion_path}/${_BASH_COMP_NAME}"
          ;;
        fish)
          _completion_path="$(_get_fish_completion_path)"
          _completion_target="${_completion_path}/${_FISH_COMP_NAME}"
          ;;
        zsh)
          _completion_path="/usr/local/share/zsh/site-functions"
          _completion_target="${_completion_path}/${_ZSH_COMP_NAME}"
          ;;
      esac

      if [[ -n "${_completion_path:-}"  ]] &&
         [[ -d "${_completion_path}"    ]]
      then
        if [[ -w "${_completion_path}"    ]] &&
           [[ -w "${_completion_target}"  ]]
        then
          if [[ -f "${_completion_target}"  ]]
          then
            rm "${_completion_target:?}"

            printf "Completion script removed: %s\\n" \
              "${_completion_target}"
          fi
        else
          _warn printf "Permission denied: %s\\n" "${_completion_path}"
        fi
      fi
    done
  }

  local _subcommand="${1:-}"

  case "${_subcommand}" in
    check)
      _completions_check
      ;;
    install)
      if [[ "${2:-}" =~ (^-d|--download$)   ]]
      then
        _completions_install --download
      else
        _completions_install
      fi
      ;;
    uninstall)
      _completions_uninstall
      ;;
    *)
      _help "completions"

      return 0
      ;;
  esac
}

# delete ############################################################### delete

_describe_delete() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} delete ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])...
            [-f | --force]

$(_color_primary "Options"):
  -f, --force   Skip the confirmation prompt.

$(_color_primary "Description"):
  Delete one or more items.

$(_color_primary "Read More"):
  ${_README_URL}#deleting

$(_color_primary "See Also"):
  ${_ME} help add
  ${_ME} help browse
  ${_ME} help edit
  ${_ME} help move
  ${_ME} help show

$(_color_primary "Examples"):
  ${_ME} delete 3
  ${_ME} delete example.md
  ${_ME} delete "A Document Title"
  ${_ME} 3 delete --force
  ${_ME} example:delete 12
  ${_ME} delete example:12
  ${_ME} example:12 delete
  ${_ME} d 3
  ${_ME} 3 d
  ${_ME} d example:12
  ${_ME} example:12 d

$(_color_primary "Aliases"):
  ${_ME} rm
  ${_ME} trash

$(_color_primary "Shortcut Aliases"):
  ${_ME} d
  ${_ME} -
HEREDOC
}
_delete() {
  local _force=0
  local _print_prompt_list=0
  local _selectors=()
  local _title=

  local __arg=
  for   __arg in "${@:-}"
  do
    case "${__arg}" in
      -f|--force|--skip*|-y|--yes)
        _force=1
        ;;
      --prompt-list)
        _print_prompt_list=1
        ;;
      --quiet)
        _QUIET=1
        ;;
      *)
        [[ -n "${__arg:-}"  ]]  && _selectors+=("${__arg:-}")
        ;;
    esac
  done

  if ! ((${#_selectors[@]}))
  then
    _exit_1 _help "delete"
  fi

  local _notebook_paths=()
  local _notebook_selectors=()
  local _target_paths=()
  local _target_selectors=()

  local __selector=
  for   __selector in "${_selectors[@]:-}"
  do
    [[ -z "${__selector:-}"       ]]  && continue

    local _selector_path=
    _selector_path="$(_show "${__selector:-}" --path 2>/dev/null || :)"

    local _selector_notebook_path=
    _selector_notebook_path="$(_notebooks show "${__selector:-}" --path 2>/dev/null || :)"

    if [[ -n "${_selector_path}" ]]
    then
      if [[ "${_selector_path:-}" == "${_selector_notebook_path:-}" ]]
      then
        _notebook_paths+=("${_selector_notebook_path}")
        _notebook_selectors+=("${__selector}")
      else
        _target_paths+=("${_selector_path}")
        _target_selectors+=("${__selector}")
      fi
    elif [[ -n "${_selector_notebook_path:-}" ]] &&
         {
           [[ -z  "${__selector##*:}"         ]] ||
           [[ !   "${__selector:-}" =~ :      ]]
         }
    then
      _notebook_paths+=("${_selector_notebook_path}")
      _notebook_selectors+=("${__selector}")
    else
      _exit_1 printf "Not found: %s\\n" "$(_color_primary "${__selector}")"
    fi
  done

  local __notebook_selector=
  for   __notebook_selector in "${_notebook_selectors[@]:-}"
  do
    [[ -z "${__notebook_selector:-}" ]]  && continue

    if ((_force))
    then
      _notebooks delete "${__notebook_selector}" --force
    else
      _notebooks delete "${__notebook_selector}"
    fi
  done

  if ! ((${#_target_paths[@]}))
  then
    return
  fi

  if ((_print_prompt_list))     || ! ((_force))
  then
    if [[ "${#_target_paths[@]}"   == 1  ]]
    then
      printf "Deleting: %s\\n" "$(_show "${_target_selectors[0]:-}" --info-line)"
    else
      printf "Deleting:\\n"

      local __prompt_selector=
      for   __prompt_selector in "${_target_paths[@]:-}"
      do
        [[ -z "${__prompt_selector:-}" ]] && continue

        printf "%s\\n" "$(_show "${__prompt_selector:-}" --info-line)"
      done

    fi
  fi

  if ! ((_force))
  then
    while true
    do
      local __yn=
      IFS='' read -r -e -d $'\n' -p \
"$(_color_primary "Proceed?")  $(_color_brackets "y/N") " __yn

      case "${__yn}" in
        [Yy]*)
          break
          ;;
        *)
          printf "Exiting...\\n"

          exit 0
          ;;
      esac
    done
  fi

  local __delete_selector=
  for   __delete_selector in "${_target_paths[@]:-}"
  do
    local _info_line=
    _info_line="$(_show "${__delete_selector:-}" --info-line)"

    local _relative_path=
    _relative_path="$(_show "${__delete_selector}" --relative-path)"

    local _notebook_path=
    _notebook_path="$(
      _notebooks show "${__delete_selector:-}" --path ||
        _notebooks current --path
    )"

    local _basename="${_relative_path##*\/}"
    local _folder_path="${_notebook_path}"

    if [[ "${_relative_path:-}" =~ / ]]
    then
      _folder_path="${_notebook_path}/${_relative_path%\/*}"
    fi

    if [[ -n "${_basename}" ]] && [[ -e "${_notebook_path}/${_relative_path}" ]]
    then
      _pin unpin "${_notebook_path}/${_relative_path}" &> /dev/null || :

      if [[ -d "${_notebook_path}/${_relative_path}"            ]]  &&
         [[ -z "$(ls -A "${_notebook_path}/${_relative_path}")" ]]
      then
        rm -r "${_notebook_path:?}/${_relative_path:?}"
      else
        if git -C "${_notebook_path:?}" check-ignore    \
             "${_notebook_path:?}/${_relative_path:?}" 1>/dev/null
        then
          rm -r "${_notebook_path:?}/${_relative_path:?}"
        else
          git -C "${_notebook_path:?}" rm -r            \
            "${_notebook_path:?}/${_relative_path:?}" 1>/dev/null
        fi
      fi

      if [[ ! -e "${_notebook_path}/${_relative_path}"  ]]
      then
        _index delete "${_basename}" "${_folder_path}"

        _git checkpoint "${_notebook_path}" "[${_ME}] Delete: ${_relative_path}"

        if ! ((_QUIET))
        then
          printf "Deleted:  %s\\n" "${_info_line}"
        fi
      fi
    else
      _exit_1 printf "Selection not found.\\n"
    fi
  done
}
_alias_subcommand "delete" "-"
_alias_subcommand "delete" "d"
_alias_subcommand "delete" "rm"
_alias_subcommand "delete" "trash"

# edit ################################################################### edit

_describe_edit() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} edit ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
          [-c <content> | --content <content>] [--edit]
          [-e <editor> | --editor <editor>] [-l | --last] [--overwrite]
          [--prepend]

$(_color_primary "Options"):
  -c, --content <content>  Content to add to the item.
  --edit                   Open the note in the editor before saving when
                           content is piped or passed as an argument.
  -e, --editor <editor>    Edit the note with <editor>, overriding the editor
                           specified in the \`\$EDITOR\` environment variable.
  -l, --last               Edit the last modified item.
  --overwrite              Overwrite existing content with <content> and
                           standard input.
  --prepend                Prepend <content> and standard input before
                           existing content.

$(_color_primary "Description"):
  Open the specified note in \`\$EDITOR\`, currently set to: ${NB_EDITOR}

  Content piped to \`${_ME} edit\` or passed using the \`--content\` option
  is appended to the file without opening it in the editor, unless the
  \`--edit\` flag is specified.

  Non-text files are opened in your system's preferred app or program for
  that file type.

$(_color_primary "Read More"):
  ${_README_URL}#editing

$(_color_primary "See Also"):
  ${_ME} help add
  ${_ME} help browse
  ${_ME} help delete
  ${_ME} help move
  ${_ME} help show

$(_color_primary "Examples"):
  ${_ME} edit 3
  ${_ME} edit example.md
  ${_ME} edit "A Document Title"
  echo "Content to append." | ${_ME} edit 1
  ${_ME} 3 edit
  ${_ME} example:edit 12
  ${_ME} edit example:12
  ${_ME} example:12 edit
  ${_ME} e 12
  ${_ME} 12 e
  ${_ME} e example:12
  ${_ME} example:12 e

$(_color_primary "Shortcut Alias"):
  ${_ME} e
HEREDOC
}
_edit() {
  local _content=
  local _content_option_present=0
  local _edit_before_commit=0
  local _edit_type="append"
  local _edit_last_item=0
  local _local_editor=
  local _password=
  local _selector=

  while ((${#}))
  do
    case "${1:-}" in
      -c|--content)
        _content_option_present=1

        if [[ -z "${2:-}"                   ]]
        then
          _exit_1 printf                          \
            "%s requires a valid argument.\\n"    \
            "$(_color_primary "${1:-}")"
        else
          if [[ -n "${_content:-}"          ]]
          then
            _content+="${_NEWLINE}${_NEWLINE}"
          fi

          _content+="$(printf "%s\\n" "${2:-}")"

          shift
        fi
        ;;
      --edit)
        _edit_before_commit=1
        ;;
      -e|--editor)
        _local_editor="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      --append|--overwrite|--prepend)
        _edit_type="${1#--}"

        if [[ -n  "${2:-}"                    ]] &&
           [[ !   "${2:-}" =~ ^--[A-Za-z0-9]+ ]] &&
           ! _contains "${2:-}" "-c" "-e"
        then
          if [[ -n "${_content:-}"            ]]
          then
            _content+="${_NEWLINE}"
          fi

          _content+="$(printf "%s\\n" "${2:-}")"

          shift
        fi
        ;;
      -l|--last*)
        if [[ "${2:-}" =~ ^[0-9]+$  ]]
        then
          _edit_last_item="${2:-}"

          shift
        else
          _edit_last_item=1
        fi
        ;;
      --password)
        _password="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      --quiet)
        _QUIET=1
        ;;
      *)
        if [[ -z "${_selector:-}"   ]]
        then
          _selector="${1:-}"
        fi
        ;;
    esac

    shift
  done

  local _notebook_path=
  _notebook_path="$(_notebooks current --path)"

  if ((_edit_last_item)) && [[ -z "${_selector:-}" ]]
  then
    _selector="$(
      if [[ -n "$(ls "${_notebook_path}")" ]]
      then
        if stat -f '%m %N' . >/dev/null 2>&1
        then # macOS (BSD stat)
          find "${_notebook_path}"                        \
            -type d -name '.*' -prune -o -type f -print0  \
            | xargs -0 stat -f '%m %N' 2>/dev/null        \
            | sort -rn                                    \
            | head -n 1                                   \
            | cut -d' ' -f2-
        else # Linux (GNU stat)
          find "${_notebook_path}"                        \
            -type d -name '.*' -prune -o -type f -print0  \
            | xargs -0 stat -c '%Y %n' 2>/dev/null        \
            | sort -rn                                    \
            | head -n 1                                   \
            | cut -d' ' -f2-
        fi
      fi
    )"
  fi

  if [[ -z "${_selector:-}" ]]
  then
    _exit_1 _help "edit"
  fi

  local _relative_path=
  _relative_path="$(_show "${_selector:-}" --relative-path)"

  local _basename="${_relative_path##*\/}"
  local _folder_path="${_relative_path%\/*}"

  if [[ -z "${_relative_path:-}"  ]]
  then
    _exit_1 printf "Not found: %s\\n" "$(_color_primary "${_relative_path}")"
  fi

  if [[ -n "${_relative_path}"                    ]] &&
     [[ -e "${_notebook_path}/${_relative_path}"  ]]
  then
    local _before=
    _before="$(_get_hash "${_notebook_path}/${_relative_path}")"

    local _decrypted_path=
    local _encrypted_path=
    local _encryption_tool=
    local _target_file="${_notebook_path}/${_relative_path}"

    if _file_is_encrypted "${_target_file}"
    then
      _encrypted_path="${_target_file}"
      _encryption_tool="$(_get_decryption_tool "${_encrypted_path:-}")"

      if [[    "${_encryption_tool:-}" != "age"   ]] &&
         [[ -z "${_password}"                     ]]
      then
        # request password without displaying it
        printf "%s: " "$(_color_primary "Password")"

        IFS='' read -r -e -d $'\n' -s _password </dev/tty

        if [[ -z "${_password}"                   ]]
        then
          _exit_1 printf "Password required.\\n"
        fi
      fi

      _decrypted_path="$(_decrypt_file "${_target_file}" "${_password:-}")"

      _target_file="${_decrypted_path}"

      _before="$(_get_hash "${_decrypted_path}")"
    fi

    if [[ -n "${_content:-}"      ]] || _piped_input
    then
      {
        if [[ -n "${_content}"    ]]
        then
          printf "%s\\n" "${_content}"
        fi

        if _piped_input
        then
          cat
        fi
      } | {
        if [[   "${_edit_type:-}" == "overwrite"  ]]
        then
          cat > "${_target_file}"
        elif [[ "${_edit_type:-}" == "prepend"    ]]
        then
          local _prepend_temp=
          _prepend_temp="$(_temp file)"

          cat                       >   "${_prepend_temp:?}"

          if ((_content_option_present))
          then
            printf "\\n"            >>  "${_prepend_temp:?}"
          fi

          cat "${_target_file}"     >>  "${_prepend_temp:?}"

          cat "${_prepend_temp:?}"  >   "${_target_file}"

          if [[ -f "${_prepend_temp:?}" ]]
          then
            rm  "${_prepend_temp:?}"
          fi
        else
          if ((_content_option_present))
          then
            printf "\\n"  >>  "${_target_file}"
          fi

          cat             >>  "${_target_file}"
        fi
      }
    fi

    if ((_edit_before_commit)) || {
       ! _piped_input && [[ -z "${_content:-}"    ]]
    }
    then
      if [[ -n "${_local_editor}"   ]]
      then
        NB_EDITOR="${_local_editor}" _edit_file "${_target_file}"
      else
        _edit_file "${_target_file}"
      fi
    fi

    local _after=
    _after="$(_get_hash "${_notebook_path}/${_relative_path}")"

    if [[ -n "${_encrypted_path:-}" ]]  &&  [[ -e "${_decrypted_path:-}" ]]
    then
      _after="$(_get_hash "${_decrypted_path}")"

      if [[ "${_before}" != "${_after}" ]]
      then
        local _temp_encrypted_path=
        _temp_encrypted_path="$(_temp file "${_relative_path}").tmp"

        mv "${_encrypted_path}" "${_temp_encrypted_path}"

        _encrypt_file                   \
          "${_decrypted_path}"          \
          "${_encrypted_path}"          \
          --password "${_password:-}"   \
          --tool "${_encryption_tool:-}"

        if [[ -e "${_temp_encrypted_path:-}"  ]]
        then
          if [[ -e "${_encrypted_path:?}"     ]]
          then
            rm "${_temp_encrypted_path:?}"
          else
            mv "${_temp_encrypted_path}" "${_encrypted_path}"
          fi
        fi
      fi

      rm "${_decrypted_path:?}"
    fi

    _git checkpoint "${_notebook_path}" "[${_ME}] Edit: ${_relative_path}"

    if [[ "${_before}" != "${_after}"   ]]
    then
      local _info=
      _info="$(_show "${_relative_path}" --info-line)"

      if ! ((_QUIET))
      then
        printf "Updated: %s\\n" "${_info}"
      fi
    fi
  else
    _exit_1 printf "Selection not found.\\n"
  fi
}
_alias_subcommand "edit" "e"

# env ##################################################################### env

_describe_env() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} env [-l | --long]
  ${_ME} env [install | update] [--ace | --mathjax]

$(_color_primary "Subcommands"):
  (default) Print environment and configuration information.
  install   Install dependencies on supported systems.
  update    Update dependencies.

$(_color_primary "Options"):
  --ace       Install or update Ace editor [1][2].
  -l, --long  Print additional environmental information.
  --mathjax   Install or update MathJax [3].

    1. https://github.com/ajaxorg/ace
    2. https://github.com/ajaxorg/ace-builds
    3. https://github.com/mathjax/MathJax

$(_color_primary "Description"):
  Print program environment and configuration information, or install
  dependencies.

$(_color_primary "Read More"):
  ${_README_URL}#installation

$(_color_primary "See Also"):
  ${_ME} help completions
  ${_ME} help init
  ${_ME} help update
  ${_ME} help version
HEREDOC
}
_env() {
  # Usage: _env_install_deb <name> <version> <repo>
  _env_install_deb() {
    local _deb_filename=
    local _name="${1:?}"
    local _repo="${3:?}"
    local _version="${2:?}"
    local _x86_64_bit=1

    local _arch=
    _arch="$(uname -m)"

    case "${_arch:-}" in
      x86_64)
        _deb_filename="${_name}_${_version}_amd64.deb"
        ;;
      aarch64)
        _x86_64_bit=0
        _deb_filename="${_name}_${_version}_arm64.deb"
        ;;
      arm*)
        _x86_64_bit=0
        _deb_filename="${_name}_${_version}_armhf.deb"
        ;;
    esac

    if [[ -z "${_deb_filename:-}"   ]]  || {
         [[ "${_name}" == "ripgrep" ]]  && ! ((_x86_64_bit))
       }
    then
      _warn printf                                                      \
        "Please install %s manually. No .deb package available for %s." \
        "$(_color_primary "${_name}")"                                  \
        "$(_color_primary "${_arch}")"
      return 0
    fi

    local _deb_path="${HOME}/${_deb_filename}"

    # handle bat version prefix in URL
    [[ "${_name}" == "bat"  ]] && _version="v${_version}"

    wget                    \
      -O "${_deb_path}"     \
      "https://github.com/${_repo}/releases/download/${_version}/${_deb_filename}"

    if [[ -e "${_deb_path}" ]]
    then
      dpkg -i "${_deb_path}"
      rm "${_deb_path:?}"
    fi
  }

  # Usage: _env_max_version <version> <version>
  _env_max_version() {
    printf "%s\\n" "${@:?}"                           \
      | sort -r -t '.' -k 1,1 -k 2,2 -k 3,3 -k 4,4 -g \
      | head -n 1
  }

  local _subcommand="${1:-}"

  case "${_subcommand}" in
    install|update)
      if ! _contains "${2:-}" "--ace" "--mathjax"
      then # skip to next section if `_env install --ace`
        # packages: curl pandoc pygments w3m ripgrep tig
        if [[ -x "$(command -v apk)"  ]]
        then
          _completions install --download

          apk add --no-cache  \
            bash-completion   \
            curl              \
            pandoc            \
            py3-pygments      \
            ripgrep           \
            tig               \
            w3m
        elif [[ -x "$(command -v apt-get)" ]]
        then
          _completions install --download

          local _apt_packages=()
          local _deb_packages=()
          local _dependencies=(
            bash-completion
            bat
            curl
            ncat
            pandoc
            python3-pygments
            ripgrep
            socat
            tig
            w3m
          )

          [[ "$(cat /etc/os-release)" =~ (ubuntu|debian) ]] || return 1

          apt-get update

          local __package=
          for   __package in "${_dependencies[@]}"
          do
            if ! _command_exists "${__package}" &&
               apt-cache show "${__package}" | grep -q "Package: ${__package}"
            then
              _apt_packages+=("${__package}")
            fi
          done

          apt-get install -y "${_apt_packages[@]:-}"

          # force install of bat
          apt-get install -y bat -o Dpkg::Options::="--force-overwrite"

          if ! _command_exists "rg"
          then
            _deb_packages+=("ripgrep 12.1.1 BurntSushi/ripgrep")
          fi

          if ! _command_exists "bat" || ! _command_exists "batcat"
          then
            _deb_packages+=("bat 0.22.1 sharkdp/bat")
          fi

          local __package=
          for   __package in "${_deb_packages[@]}"
          do
            local _arguments=()
            IFS=' ' read -ra _arguments <<< "${__package:-}"

            _env_install_deb "${_arguments[@]:-}"
          done
        elif [[ -x "$(command -v dnf)"    ]]
        then
          : # TODO: dnf install
          _completions install --download
        elif [[ -x "$(command -v zypper)" ]]
        then
          : # TODO: zypper install
          _completions install --download
        else
          _completions install --download
        fi
      fi

      # install assets

      case "${2:-}" in
        --ace)
          if [[ ! -e "${NB_DIR}/.assets/ace-builds" ]]
          then
            if [[ ! -e "${NB_DIR}/.assets"          ]]
            then
              mkdir "${NB_DIR}/.assets"
            fi

            cd "${NB_DIR}/.assets" ||
              _exit_1 printf "Unable to \`cd\` to %s\\n" "${NB_DIR}/.assets"

            git clone https://github.com/ajaxorg/ace-builds.git || return 0
          else
            cd "${NB_DIR}/.assets/ace-builds" ||
              _exit_1 printf "Unable to \`cd\` to %s\\n" "${NB_DIR}/.assets/ace-builds"

            git -C "${NB_DIR}/.assets/ace-builds" pull origin   || return 0

            local _git_status_output=
            _git_status_output="$(git -C "${NB_DIR}/.assets/ace-builds" status --porcelain)"

            if [[ -n "${_git_status_output:-}"      ]] &&
               ! grep -qv '^ D demo/' <<< "$_git_status_output"
            then # reset repository if there are stray deleted demo files.
              git -C "${NB_DIR}/.assets/ace-builds" reset --hard HEAD
            fi
          fi
          ;;
        --mathjax)
          if [[ ! -e "${NB_DIR}/.assets/MathJax"    ]]
          then
            if [[ ! -e "${NB_DIR}/.assets"          ]]
            then
              mkdir "${NB_DIR}/.assets"
            fi

            cd "${NB_DIR}/.assets" ||
              _exit_1 printf "Unable to \`cd\` to %s\\n" "${NB_DIR}/.assets"

            git clone https://github.com/mathjax/MathJax.git  || return 0
          else
            cd "${NB_DIR}/.assets/MathJax" ||
              _exit_1 printf "Unable to \`cd\` to %s\\n" "${NB_DIR}/.assets/MathJax"

            git -C "${NB_DIR}/.assets/MathJax" pull origin    || return 0
          fi
          ;;
      esac
      ;;
    uninstall)
      _completions uninstall
      ;;
    *)
      printf "_ME=%s\\n"                                  "${_ME:-}"
      printf "_MY_PATH=%s\\n"                             "${_MY_PATH:-}"
      printf "EDITOR=%s\\n"                               "${EDITOR:-}"
      printf "NB_ACE_ENABLED=%s\\n"                       "${NB_ACE_ENABLED:-}"
      printf "NB_ACE_MD_GUTTER=%s\\n"                     "${NB_ACE_MD_GUTTER:-}"
      printf "NB_ACE_RELATIVE_LINE_NUMBERS=%s\\n"         "${NB_ACE_RELATIVE_LINE_NUMBERS:-}"
      printf "NB_ACE_SOFT_TABS=%s\\n"                     "${NB_ACE_SOFT_TABS:-}"
      printf "NB_ACE_KEYBOARD=%s\\n"                      "${NB_ACE_KEYBOARD:-}"
      printf "NB_AUDIO_TOOL=%s\\n"                        "${NB_AUDIO_TOOL:-}"
      printf "NB_AUTO_SYNC=%s\\n"                         "${NB_AUTO_SYNC:-}"
      printf "NB_AUTO_SYNC_SECONDS=%s\\n"                 "${NB_AUTO_SYNC_SECONDS:-}"
      printf "NB_BOOKMARK_CONTENT_CLEANUP_TOOL=%s\\n"     "${NB_BOOKMARK_CONTENT_CLEANUP_TOOL:-}"
      printf "NB_BOOKMARK_CONTENT_CONVERSION_TOOL=%s\\n"  "${NB_BOOKMARK_CONTENT_CONVERSION_TOOL:-}"
      printf "NB_BROWSE_MARKDOWN_READER=%s\\n"            "${NB_BROWSE_MARKDOWN_READER:-}"
      printf "NB_BROWSE_SERVER_TOOL=%s\\n"                "${NB_BROWSE_SERVER_TOOL:-}"
      printf "NB_BROWSE_SUPPORT_LINKS=%s\\n"              "${NB_BROWSE_SUPPORT_LINKS:-}"
      printf "NB_BROWSER=%s\\n"                           "${NB_BROWSER:-}"
      printf "NB_COLOR_PRIMARY=%s\\n"                     "${NB_COLOR_PRIMARY:-}"
      printf "NB_COLOR_SECONDARY=%s\\n"                   "${NB_COLOR_SECONDARY:-}"
      printf "NB_COLOR_THEME=%s\\n"                       "${NB_COLOR_THEME:-}"
      printf "NB_CUSTOM_CSS=%s\\n"                        "${NB_CUSTOM_CSS:-}"
      printf "NB_CUSTOM_CSS_URL=%s\\n"                    "${NB_CUSTOM_CSS_URL:-}"
      printf "NB_CUSTOM_JAVASCRIPT=%s\\n"                 "${NB_CUSTOM_JAVASCRIPT:-}"
      printf "NB_CUSTOM_JAVASCRIPT_URL=%s\\n"             "${NB_CUSTOM_JAVASCRIPT_URL:-}"
      printf "NB_DATA_TOOL=%s\\n"                         "${NB_DATA_TOOL:-}"
      printf "NB_DEFAULT_EXTENSION=%s\\n"                 "${NB_DEFAULT_EXTENSION:-}"
      printf "NB_DEFAULT_TEMPLATE=%s\\n"                  "${NB_DEFAULT_TEMPLATE:-}"
      printf "NB_DIR=%s\\n"                               "${NB_DIR:-}"
      printf "NB_DIRECTORY_TOOL=%s\\n"                    "${NB_DIRECTORY_TOOL:-}"
      printf "NB_DOWNLOAD_TOOL=%s\\n"                     "${NB_DOWNLOAD_TOOL:-}"
      printf "NB_EDITOR=%s\\n"                            "${NB_EDITOR:-}"
      printf "NB_ENCRYPTION_TOOL=%s\\n"                   "${NB_ENCRYPTION_TOOL:-}"
      printf "NB_FOLDERS_FIRST=%s\\n"                     "${NB_FOLDERS_FIRST:-}"
      printf "NB_FOOTER=%s\\n"                            "${NB_FOOTER:-}"
      printf "NB_GUI_BROWSER=%s\\n"                       "${NB_GUI_BROWSER:-}"
      printf "NB_HEADER=%s\\n"                            "${NB_HEADER:-}"
      printf "NB_IMAGE_TOOL=%s\\n"                        "${NB_IMAGE_TOOL:-}"
      printf "NB_INDICATOR_AUDIO=%s\\n"                   "${NB_INDICATOR_AUDIO:-}"
      printf "NB_INDICATOR_BOOKMARK=%s\\n"                "${NB_INDICATOR_BOOKMARK:-}"
      printf "NB_INDICATOR_DOCUMENT=%s\\n"                "${NB_INDICATOR_DOCUMENT:-}"
      printf "NB_INDICATOR_EBOOK=%s\\n"                   "${NB_INDICATOR_EBOOK:-}"
      printf "NB_INDICATOR_ENCRYPTED=%s\\n"               "${NB_INDICATOR_ENCRYPTED:-}"
      printf "NB_INDICATOR_FOLDER=%s\\n"                  "${NB_INDICATOR_FOLDER:-}"
      printf "NB_INDICATOR_IMAGE=%s\\n"                   "${NB_INDICATOR_IMAGE:-}"
      printf "NB_INDICATOR_PINNED=%s\\n"                  "${NB_INDICATOR_PINNED:-}"
      printf "NB_INDICATOR_TODO=%s\\n"                    "${NB_INDICATOR_TODO:-}"
      printf "NB_INDICATOR_TODO_DONE=%s\\n"               "${NB_INDICATOR_TODO_DONE:-}"
      printf "NB_INDICATOR_VIDEO=%s\\n"                   "${NB_INDICATOR_VIDEO:-}"
      printf "NB_LIMIT=%s\\n"                             "${NB_LIMIT:-}"
      printf "NB_MATHJAX_ENABLED=%s\\n"                   "${NB_MATHJAX_ENABLED:-}"
      printf "NB_MARKDOWN_TOOL=%s\\n"                     "${NB_MARKDOWN_TOOL:-}"
      printf "NB_NOTEBOOK_PATH=%s\\n"                     "${NB_NOTEBOOK_PATH:-}"
      printf "NB_PINNED_PATTERN=%s\\n"                    "${NB_PINNED_PATTERN:-}"
      printf "NB_SERVER_HOST=%s\\n"                       "${NB_SERVER_HOST:-}"
      printf "NB_SERVER_PORT=%s\\n"                       "${NB_SERVER_PORT:-}"
      printf "NB_USER_AGENT=%s\\n"                        "${NB_USER_AGENT:-}"
      printf "NB_SYNTAX_THEME=%s\\n"                      "${NB_SYNTAX_THEME:-}"
      printf "NBRC_PATH=%s\\n"                            "${NBRC_PATH:-}"
      printf "PAGER=%s\\n"                                "${PAGER:-}"
      printf "_LOCAL_NOTEBOOK_PATH=%s\\n"                 "${_LOCAL_NOTEBOOK_PATH:-}"
      printf "_GLOBAL_NOTEBOOK_PATH=%s\\n"                "${_GLOBAL_NOTEBOOK_PATH:-}"
      printf "_CURRENT_WORKING_DIR=%s\\n"                 "${_CURRENT_WORKING_DIR:-}"

      if _contains "${1:-}" "--long" "-l"
      then
        printf "\\n"
        printf "ack:        %s\\n" "$(command -v ack)"
        printf "ag:         %s\\n" "$(command -v ag)"
        printf "bat:        %s\\n" "$(command -v bat)"
        printf "code:       %s\\n" "$(command -v code)"
        printf "curl:       %s\\n" "$(command -v curl)"
        printf "emacs:      %s\\n" "$(command -v emacs)"
        printf "git:        %s\\n" "$(command -v git)"
        printf "gvim:       %s\\n" "$(command -v gvim)"
        printf "gpg:        %s\\n" "$(command -v gpg)"
        printf "highlight:  %s\\n" "$(command -v highlight)"
        printf "less:       %s\\n" "$(command -v less)"
        printf "lynx:       %s\\n" "$(command -v lynx)"
        printf "macdown:    %s\\n" "$(command -v macdown)"
        printf "mate:       %s\\n" "$(command -v mate)"
        printf "mvim:       %s\\n" "$(command -v mvim)"
        printf "nano:       %s\\n" "$(command -v nano)"
        printf "nc:         %s\\n" "$(command -v ncat)"
        printf "ncat:       %s\\n" "$(command -v nc)"
        printf "nvim:       %s\\n" "$(command -v nvim)"
        printf "openssl:    %s\\n" "$(command -v openssl)"
        printf "pandoc:     %s\\n" "$(command -v pandoc)"
        printf "pygments:   %s\\n" "$(command -v pygmentize)"
        printf "readable:   %s\\n" "$(command -v readable)"
        printf "rg:         %s\\n" "$(command -v rg)"
        printf "subl:       %s\\n" "$(command -v subl)"
        printf "tig:        %s\\n" "$(command -v tig)"
        printf "w3m:        %s\\n" "$(command -v w3m)"
        printf "wget:       %s\\n" "$(command -v wget)"
        printf "vim:        %s\\n" "$(command -v vim)"

        printf "\\n"
        printf "bash --version\\n"
        printf -- "--------------\\n"
        printf "%s\\n" "$(bash --version | head -1)"

        printf "\\n"
        printf "git --version\\n"
        printf -- "-------------\\n"
        printf "%s\\n" "$(git --version | head -1)"

        printf "\\n"
        printf "uname -a\\n"
        printf -- "--------\\n"
        printf "%s\\n" "$(uname -a)"

        printf "\\n"
        printf "locale\\n"
        printf -- "------\\n"
        printf "%s\\n" "$(locale)"

        if _command_exists "google-chrome"
        then
          printf "\\n"
          printf "google-chrome --version\\n"
          printf -- "-----------------------\\n"
          printf "%s\\n"  "$(google-chrome --version 2>&1)"
        fi

        if _command_exists "chromium"
        then
          printf "\\n"
          printf "chromium --version\\n"
          printf -- "------------------\\n"
          printf "%s\\n"  "$(chromium --version 2>&1)"
        fi

        if _command_exists "chromium-browser"
        then
          printf "\\n"
          printf "chromium-browser --version\\n"
          printf -- "--------------------------\\n"
          printf "%s\\n"  "$(chromium-browser --version 2>&1)"
        fi

        if [[ -x "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" ]]
        then
          printf "\\n"
          printf "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome --version\\n"
          printf -- "----------------------------------------------------------------------\\n"
          printf "%s\\n"  "$('/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' --version 2>&1)"
        fi

        if [[ -x "/Applications/Chromium.app/Contents/MacOS/Chromium"           ]]
        then
          printf "\\n"
          printf "/Applications/Chromium.app/Contents/MacOS/Chromium --version\\n"
          printf -- "------------------------------------------------------------\\n"
          printf "%s\\n"  "$('/Applications/Chromium.app/Contents/MacOS/Chromium' --version 2>&1)"
        fi

        if _command_exists "awk"
        then
          printf "\\n"
          printf "awk --version\\n"
          printf -- "-------------\\n"
          printf "%s\\n" "$(awk --version 2>&1)"
        fi

        if _command_exists "grep"
        then
          printf "\\n"
          printf "grep --version\\n"
          printf -- "--------------\\n"
          printf "%s\\n" "$(grep --version 2>&1)"
        fi

        if _command_exists "sed"
        then
          printf "\\n"
          printf "sed --version\\n"
          printf -- "-------------\\n"
          printf "%s\\n" "$(sed --version 2>&1)"
        fi

        if _command_exists "nc"
        then
          printf "\\n"
          printf "nc --version\\n"
          printf -- "------------\\n"
          printf "%s\\n"  "$(nc --version 2>&1)"
        fi

        if _command_exists "ncat"
        then
          printf "\\n"
          printf "ncat --version\\n"
          printf -- "--------------\\n"
          printf "%s\\n"  "$(ncat --version 2>&1)"
        fi

        if _command_exists "pandoc"
        then
          printf "\\n"
          printf "pandoc --version\\n"
          printf -- "----------------\\n"
          printf "%s\\n" "$(pandoc --version 2>&1)"
        fi

        if _command_exists "socat"
        then
          printf "\\n"
          printf "socat -V\\n"
          printf -- "--------\\n"
          printf "%s\\n" "$(socat -V 2>&1)"
        fi

        if _command_exists "w3m"
        then
          printf "\\n"
          printf "w3m -version\\n"
          printf -- "------------\\n"
          printf "%s\\n" "$(w3m -version 2>&1)"
        fi
      fi
      ;;
  esac
}

# export ############################################################### export

_describe_export() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} export ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
            <path> [-f | --force] [<pandoc options>...]
  ${_ME} export notebook <name> [<path>]
  ${_ME} export pandoc ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
            [<pandoc options>...]

$(_color_primary "Options"):
  -f, --force   Skip the confirmation prompt when overwriting an existing file.

$(_color_primary "Subcommands"):
  (default)     Export a file to <path>. If <path> has a different extension
                than the source note, convert the note using \`pandoc\`.
  notebook      Export the notebook <name> to the current directory or <path>.
                Alias for \`${_ME} notebooks export\`.
  pandoc        Export the file to standard output or a file using \`pandoc\`.
                \`export pandoc\` prints to standard output by default.

$(_color_primary "Description"):
  Export a file or notebook.

  If Pandoc [1] is available, convert the note from its current format
  to the format of the output file as indicated by the file extension
  in <path>. Any additional arguments are passed directly to Pandoc.
  See the Pandoc help information for available options.

    1. https://pandoc.org/

$(_color_primary "Read More"):
  ${_README_URL}#%EF%B8%8F-import--export

$(_color_primary "See Also"):
  ${_ME} help browse
  ${_ME} help import

$(_color_primary "Examples"):
  # Export an Emacs Org mode note
  ${_ME} export example.org /path/to/example.org

  # Export a Markdown note to HTML and print to standard output
  ${_ME} export pandoc example.md --from=markdown_strict --to=html

  # Export a Markdown note to a .docx Microsoft Office Word document
  ${_ME} export example.md /path/to/example.docx

  # Export note 12 in the "sample" notebook to HTML
  ${_ME} export sample:12 /path/to/example.html
HEREDOC
}
_export() {
  local _args=()
  local _force=0
  local _notebook_export=0
  local _pandoc_only=0
  local _selector=
  local _target_path=

  local __arg=
  for   __arg in "${@:-}"
  do
    case "${__arg}" in
      -f|--force|--skip*|-y|--yes)
        _force=1
        ;;
      notebook*)
        _notebook_export=1
        ;;
      pandoc)
        _pandoc_only=1
        ;;
      *)
        if [[ -z "${_selector:-}"   ]]
        then
          _selector="${__arg}"
        elif ! ((_pandoc_only)) &&  [[ -z "${_target_path:-}" ]]
        then
          _target_path="${__arg}"
        else
          _args+=("${__arg}")
        fi
        ;;
    esac
  done

  if [[ -z "${_selector:-}" ]]
  then
    _exit_1 _help "export"
  fi

  if ((_notebook_export))
  then
    _notebooks export "${_selector:-}" "${_target_path:-}"

    return 0
  fi

  local _notebook_path=
  _notebook_path="$(_notebooks current --path)"

  local _relative_path=
  _relative_path="$(_show "${_selector}" --relative-path)"

  local _basename="${_relative_path##*\/}"

  if [[ -z "${_relative_path:-}"                      ]] ||
     [[ ! -e "${_notebook_path}/${_relative_path:-}"  ]]
  then
    _exit_1 printf "Not found: %s\\n" "$(_color_primary "${_selector}")"
  fi

  if ((_pandoc_only))
  then
    if _command_exists "pandoc"
    then
      if [[ -n "${_args[*]:-}"    ]]
      then
        _pandoc "${_notebook_path}/${_relative_path}" "${_args[@]:-}"
      else
        _pandoc "${_notebook_path}/${_relative_path}"
      fi
    else
      _exit_1 printf "Pandoc required. https://pandoc.org/\\n"
    fi
  else
    if [[ -z "${_target_path:-}"  ]]
    then
      _exit_1 _help "export"
    fi

    if [[ -d "${_target_path:-}"  ]]
    then
      _target_path="${_target_path%/}/${_basename}"
    fi

    if [[ -e "${_target_path:-}"  ]]
    then
      if ! ((_force))
      then
        printf "File exists at %s\\n" "$(_color_primary "${_target_path}")"

        while true
        do
          local __yn=
          IFS='' read -r -e -d $'\n' -p \
"$(_color_primary "Overwrite existing file?") $(_color_brackets "y/N") " __yn

          case "${__yn}" in
            [Yy]*)
              break
              ;;
            *)
              printf "Exiting%s\\n" "$(_color_muted "...")"

              exit 0
              ;;
          esac
        done
      fi
    fi

    local _source_file_type="${_basename##*.}"
    local _target_file_type="${_target_path##*.}"

    if _command_exists "pandoc"   &&
       [[ "${_source_file_type}"  != "${_target_file_type}" ]]
    then
      if [[ -n "${_args[*]:-}"    ]]
      then
        _pandoc                                   \
          "${_notebook_path}/${_relative_path}"   \
          -o "${_target_path}"                    \
          --standalone                            \
          "${_args[@]:-}"
      else
        _pandoc                                   \
          "${_notebook_path}/${_relative_path}"   \
          -o "${_target_path}"                    \
          --standalone
      fi
    else
      cp "${_notebook_path}/${_relative_path}" "${_target_path}"
    fi &&
      printf "Exported: %s\\n"  "$(_show "${_relative_path}" --info-line)"
      printf "To:        %s\\n" "$(_color_primary "${_target_path}")"
  fi
}

# history ############################################################# history

_describe_history() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} history [<notebook>:][<folder-path>/][<id> | <filename> | <title>]

$(_color_primary "Description"):
  Display notebook history using \`tig\` [1] (if available) or \`git log\`.
  When a note is specified, the history for that note is displayed.

    1. https://github.com/jonas/tig

$(_color_primary "Read More"):
  ${_README_URL}#-revision-history
  ${_README_URL}#-git-sync

$(_color_primary "See Also"):
  ${_ME} help git
  ${_ME} help remote
  ${_ME} help status
  ${_ME} help sync

$(_color_primary "Examples"):
  ${_ME} history
  ${_ME} history example.md
  ${_ME} 3 history
  ${_ME} example:history
  ${_ME} history example:
  ${_ME} example:history 12
  ${_ME} history example:12
  ${_ME} example:12 history
HEREDOC
}
_history() {
  local _basename=
  local _force_git_log=0
  local _notebook_path=
  local _selector=

  local __arg=
  for   __arg in "${@:-}"
  do
    case "${__arg}" in
      --*log*|--*git*)
        _force_git_log=1
        ;;
      *)
        if [[ -z "${_selector:-}" ]]
        then
          _selector="${__arg}"
        fi
        ;;
    esac
  done

  if [[ -n "${_selector:-}"       ]]
  then
    if [[  "${_selector}" =~ :$   ]] ||
       ! _relative_path="$(_show "${_selector}" --relative-path 2>/dev/null)"
    then
      if ! _notebook_path="$(_notebooks show "${_selector}" --path 2>/dev/null)"
      then
        _exit_1 printf "Not found: %s\\n" "$(_color_primary "${_selector:-}")"
      fi
    fi
  fi

  if [[ -z "${_notebook_path:-}"  ]]
  then
    _notebook_path="$(_notebooks current --path)"
  fi

  cd "${_notebook_path}" || _exit_1 printf "_history() \`cd\` failed.\\n"

  local _log_command="git log"

  if _command_exists "tig" && ! ((_force_git_log))
  then
    _log_command="tig --all"
  fi

  if [[ -n "${_relative_path:-}"  ]] && [[ -e "${_notebook_path}/${_relative_path}" ]]
  then
    eval "${_log_command} -- \"${_relative_path}\""
  else
    eval "${_log_command}"
  fi
}

# import ############################################################### import

_describe_import() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} import [bookmarks | copy | download | move] (<path>... | <url>)
            [--convert] [<notebook>:][<folder-path>/][<filename>]
  ${_ME} import notebook <path> [<name>]

$(_color_primary "Options"):
  --convert  Convert HTML content to Markdown.

$(_color_primary "Subcommands"):
  (default)  Copy or download the file(s) at <path> or <url>.
  bookmarks  Import bookmarks from a Chrome, Firefox, or Edge export file.
  copy       Copy the file(s) at <path> into the current notebook.
  download   Download the file at <url> into the current notebook.
  move       Move the file(s) at <path> into the current notebook.
  notebook   Import the local notebook at <path> to make it global.

$(_color_primary "Description"):
  Copy, move, or download files into \`nb\`, import bookmarks, or import
  a local notebook to make it global.

$(_color_primary "Read More"):
  ${_README_URL}#%EF%B8%8F-import--export

$(_color_primary "See Also"):
  ${_ME} help add
  ${_ME} help export

$(_color_primary "Examples"):
  ${_ME} import ~/Pictures/example.png
  ${_ME} import ~/Documents/example.docx
  ${_ME} import https://example.com/example.pdf
  ${_ME} example:import https://example.com/example.jpg
  ${_ME} import ./*
  ${_ME} import ./*.md
  ${_ME} import ~/Pictures/example.png example-notebook:
  ${_ME} import ~/Documents/example.docx example-folder/

$(_color_primary "Shortcut Alias"):
  ${_ME} i
HEREDOC
}
_import() {
  # _import_create_bookmark()
  #
  # Usage:
  #   _import_create_bookmark <target-selector> <line>
  _import_create_bookmark() {
    local _line="${2:?}"
    local _target_selector="${1:-}"

    local _bookmark_options=(--skip-folder-prompt)

    local _add_timestamp=
    _add_timestamp="$(
      LC_ALL=C sed -E -e 's/.*ADD_DATE=\"([[:digit:]]+)\".*/\1/g' <<< "${_line}"
    )"

    local _target_filename=
    _target_filename="$(
      if hash "gdate" 2>/dev/null
      then # GNU prefixed
        gdate -u -d "@${_add_timestamp}"  "+%Y%m%d%H%M%S"
      elif date --version >/dev/null 2>&1
      then # GNU
        date  -u -d "@${_add_timestamp}"  "+%Y%m%d%H%M%S"
      else # BSD
        date  -u -r "${_add_timestamp}"   "+%Y%m%d%H%M%S"
      fi
    )"

    if [[ -n "${_target_filename:-}"  ]]
    then
      _bookmark_options+=(--filename "${_target_filename}")
    fi

    local _tag_list=
    _tag_list="$(
      grep -q 'TAGS=\"'                                       <<< "${_line}" &&
        LC_ALL=C sed -E -e 's/.*TAGS=\"([^\"]+)\".*/\1/g'     <<< "${_line}" || :
    )"

    if [[ -n "${_tag_list:-}"         ]]
    then
      _bookmark_options+=(--tags "${_tag_list}")
    fi

    local _title=
    _title="$(
      LC_ALL=C sed -E -e 's/.*>(.*)<\/A>/\1/g'                <<< "${_line}"
    )"

    if [[ -n "${_title:-}"            ]]
    then
      _bookmark_options+=(--title "${_title}")
    fi

    local _url=
    _url="$(
      LC_ALL=C sed -E -e 's/.*HREF=\"(.*)\" ADD_DATE.*/\1/g'  <<< "${_line}"
    )"

    _notebooks select "${_target_selector%%:*}"

    _bookmark                         \
      "${_target_selector}"           \
      "${_url}"                       \
      "${_bookmark_options[@]}"
  }

  # _import_init_target_relative_path()
  #
  # Usage:
  #   _import_init_target_relative_path <notebook-path> <source-basename> <selector-path>
  _import_init_target_relative_path() {
    local _notebook_path="${1:?}"
    local _source_basename="${2:?}"
    local _selector_path="${3:-}"
    local _target_folder_relative_path=
    local _target_relative_path=

    if [[ -n "${_selector_path:-}"          ]]
    then
      if [[ "${_selector_path}" =~ /$                 ]] ||
         [[ -d "${_notebook_path}/${_selector_path}"  ]]
      then
        if [[ ! "${_selector_path}" =~ /$   ]]
        then
          _selector_path="${_selector_path}/"
        fi

        _target_folder_relative_path="$(
          _selector_resolve_folders "${_selector_path}" --build || :
        )"

        _target_relative_path="${_target_folder_relative_path}/${_source_basename}"
      elif [[ "${_selector_path}" =~ /      ]]
      then
        _target_folder_relative_path="$(
          _selector_resolve_folders "${_selector_path}" --build || :
        )"

        _target_relative_path="${_target_folder_relative_path}/${_selector_path##*\/}"
      else
        _target_relative_path="${_selector_path}"
      fi
    else
      _target_relative_path="${_source_basename}"
    fi

    if [[ "${_target_relative_path:-}" =~ / ]]
    then
      _target_folder_relative_path="${_target_relative_path%\/*}"

      if [[ ! -e "${_notebook_path}/${_target_folder_relative_path}" ]]
      then
        mkdir -p "${_notebook_path}/${_target_folder_relative_path}"
      fi
    fi

    printf "%s\\n" "$(
      _notebooks show "${_notebook_path}" --filename "${_target_relative_path}"
    )"
  }

  # _import_validate_path()
  #
  # Usage:
  #   _import_validate_path <path>
  _import_validate_path() {
    if [[     -z "${1:-}" ]]
    then
      _exit_1 _help "import"
    elif [[ ! -e "${1:-}" ]]
    then
      _exit_1 printf "File not found: %s\\n" "$(_color_primary "${1:-}")"
    fi
  }

  local _convert=0
  local _paths=()
  local _selector=
  local _source_and_target_identifiers=()
  local _subcommand=
  local _target_notebook_name=
  local _url=

  local _local_notebook_path=
  _local_notebook_path="$(_notebooks --local --path || :)"

  if _piped_input
  then
    IFS=$' \n' _paths+=($(cat))
  fi

  local __arg=
  for   __arg in "${@:-}"
  do
    case "${__arg}" in
      bookmark|bookmarks)
        _subcommand="bookmarks"
        ;;
      copy|download|move)
        _subcommand="${__arg}"
        ;;
      notebook*)
        _subcommand="notebook"
        ;;
      --convert)
        _convert=1
        ;;
      *)
        if _string_is_url "${__arg:-}"
        then
          _url="${__arg:-}"
          _subcommand="download"
        else
          _source_and_target_identifiers+=("${__arg:-}")
        fi
        ;;
    esac
  done

  [[ -n "${_subcommand:-}" ]] || _subcommand="copy"

  local __source_and_target_identifier=
  for   __source_and_target_identifier in "${_source_and_target_identifiers[@]:-}"
  do
    if [[    "${_subcommand:-}" == "download" ]] &&
       [[ -n "${_url:-}"                      ]]
    then
      _selector="${__source_and_target_identifier:-}"
    elif [[ "${_subcommand}" == bookmarks                     ]] &&
         [[ ! "${__source_and_target_identifier}" =~ (^/|^~/) ]] &&
         [[ "${__source_and_target_identifier}"   =~ (:$|/$)  ]]
    then
      _selector="${__source_and_target_identifier}"
    elif [[ "${_subcommand}" =~ (^copy$|^move$)               ]] &&
         [[ ! "${__source_and_target_identifier}" =~ (^/|^~/) ]] &&
         {
           [[ -n "${_local_notebook_path}"                    ]] ||
           [[ ! -e "${PWD}/${__source_and_target_identifier}" ]]
         }
    then
      _selector="${__source_and_target_identifier}"
    elif [[ "${_subcommand}" == "notebook"    ]] &&
         [[ -n "${_paths[*]:-}"               ]]
    then
      _target_notebook_name="${__source_and_target_identifier:-}"
    else
      if [[ "${__source_and_target_identifier:-}" =~ ^~/ ]]
      then
        _paths+="$(
          printf "%s\\n" "${__source_and_target_identifier:-}" | sed "s,^~,${HOME},g"
        )"
      else
        _paths+=("${__source_and_target_identifier:-}")
      fi
    fi
  done

  local _notebook_name=
  local _notebook_path=
  local _selector_path=

  if [[ "${_selector:-}" =~ :     ]]
  then
    _notebook_name="$(
      _notebooks show "${_selector%%:*}" --name 2>/dev/null \
        || _notebooks current --name
    )"
    _notebook_path="$(
      _notebooks show "${_selector%%:*}" --path 2>/dev/null \
        || _notebooks current --path
      )"
    _selector_path="${_selector#*:}"
  else
    _notebook_name="$(_notebooks current --name)"
    _notebook_path="$(_notebooks current --path)"
    _selector_path="${_selector:-}"
  fi

  local _source_basename=
  local _target_basename=
  local _target_folder_relative_path=
  local _target_relative_path=

  case "${_subcommand}" in
    bookmarks)
      local _target_folder_relative_path=
      _target_folder_relative_path="$(
        _selector_resolve_folders "${_selector_path}" --build || :
      )"

      if [[ -n  "${_target_folder_relative_path:-}"     ]] &&
         [[ !   "${_target_folder_relative_path}" =~ /$ ]]
      then
        _target_folder_relative_path="${_target_folder_relative_path}/"
      fi

      local __path=
      for   __path in "${_paths[@]:-}"
      do
        _import_validate_path "${__path:-}"

        local               __line=
        while IFS= read -r  __line || [[ -n "${__line:-}"           ]]
        do
          if [[ "${__line}" =~ ^[[:space:]]*\<DT\>                  ]]
          then
            if [[ "${__line}" =~ PERSONAL_TOOLBAR_FOLDER=\"true\"   ]]
            then
              _target_folder_relative_path="${_target_folder_relative_path}toolbar/"
            elif [[ "${__line}" =~ \<DT\>\<A.*\>.*\</A\>            ]]
            then
              _import_create_bookmark                               \
                "${_notebook_name}:${_target_folder_relative_path}" \
                "${__line}" || :
            elif [[ "${__line}" =~ \<DT\>\<H3.*\>.*\</H3\>          ]]
            then
              local _parent_folder_name=
              _parent_folder_name="$(
                LC_ALL=C sed -E -e 's/.*>(.*)<\/H3>.*/\1/g' <<< "${__line}"
              )"

              _target_folder_relative_path="${_target_folder_relative_path}${_parent_folder_name}/"
            fi
          elif [[ "${__line}" =~ \</DL\>\<p\>                       ]]
          then
            _target_folder_relative_path="${_target_folder_relative_path%/}"

            if [[ "${_target_folder_relative_path:-}" =~ \/         ]]
            then
              _target_folder_relative_path="${_target_folder_relative_path%/*}/"
            else
              _target_folder_relative_path=
            fi
          fi
        done < "${__path}"
      done
      ;;
    copy)
      local __path=
      for   __path in "${_paths[@]:-}"
      do
        _import_validate_path "${__path:-}"

        _source_basename="$(basename -- "${__path}")"

        _target_relative_path="$(
          _import_init_target_relative_path \
            "${_notebook_path}"             \
            "${_source_basename}"           \
            "${_selector_path}"
        )"

        if [[ "${_target_relative_path}" =~ / ]]
        then
          _target_folder_relative_path="${_target_relative_path%\/*}"
        fi

        _target_basename="${_target_relative_path##*\/}"

        if [[ -d "${__path}"      ]]
        then
          cp -R "${__path}" "${_notebook_path}/${_target_relative_path}"
        else
          cp "${__path}" "${_notebook_path}/${_target_relative_path}"
        fi &&
          _index add              \
            "${_target_basename}" \
            "${_notebook_path}/${_target_folder_relative_path}" &&
              _git checkpoint "${_notebook_path}" "[${_ME}] Import: ${_target_relative_path}"

        printf "Imported %s from %s\\n"                                       \
          "$(_show "${_notebook_path}/${_target_relative_path}" --info-line)" \
          "$(_color_primary "${__path}")"
      done
      ;;
    download)
      _source_basename="$(basename -- "${_url}" | tr -d '[:space:]')"

      if [[ "${_url}" =~ \/$ ]]
      then
        _source_basename="${_source_basename}.html"
      fi

      _target_relative_path="$(
        _import_init_target_relative_path \
          "${_notebook_path}"             \
          "${_source_basename}"           \
          "${_selector_path}"
      )"

      if [[ "${_target_relative_path}" =~ / ]]
      then
        _target_folder_relative_path="${_target_relative_path%\/*}"
      fi

      _target_basename="${_target_relative_path##*\/}"

      if ((_convert))
      then
        if ! _download_from "${_url}" \
            | _pandoc                 \
              --standard-input        \
              --from html             \
              --to markdown           \
              -o "${_notebook_path}/${_target_relative_path}"
        then
          _exit_1 printf "Unable to download and convert: %s\\n" "${_url}"
        fi
      else
        if ! _download_from "${_url}" "${_notebook_path}/${_target_relative_path}"
        then
          _exit_1 printf "Unable to download: %s\\n" "${_url}"
        fi
      fi &&
        _index add              \
          "${_target_basename}" \
          "${_notebook_path}/${_target_folder_relative_path:-}" &&
            _git checkpoint "${_notebook_path}" "\
[${_ME}] Import: ${_target_relative_path}

Source:
${_url}
"
      printf "Imported %s from %s\\n"                     \
        "$(_show "${_target_relative_path}" --info-line)" \
        "$(_color_primary "${_url}")"
      ;;
    move)
      local __path=
      for   __path in "${_paths[@]:-}"
      do
        _import_validate_path "${__path:-}"

        _source_basename="$(basename -- "${__path}")"

        _target_relative_path="$(
          _import_init_target_relative_path   \
            "${_notebook_path}"               \
            "${_source_basename}"             \
            "${_selector_path}"
        )"

        if [[ "${_target_relative_path}" =~ / ]]
        then
          _target_folder_relative_path="${_target_relative_path%\/*}"
        fi

        _target_basename="${_target_relative_path##*\/}"

        mv "${__path}" "${_notebook_path}/${_target_relative_path}" &&
          _index add              \
            "${_target_basename}" \
            "${_notebook_path}/${_target_folder_relative_path:-}"   &&
              _git checkpoint "${_notebook_path}" "[${_ME}] Import: ${_target_relative_path}"

        printf "Imported %s from %s\\n"                     \
          "$(_show "${_target_relative_path}" --info-line)" \
          "$(_color_primary "${__path}")"
      done
      ;;
    notebook)
      _notebooks import "${_paths[0]:-}" "${_target_notebook_name:-}"

      return 0
      ;;
    *)
      _exit_1 _help "import"
      ;;
  esac
}
_alias_subcommand "import" "i"

# move ################################################################### move

_describe_move() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} move ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
          ([<notebook>:][<path>] | --reset | --to-bookmark | --to-note |
          --to-title | --to-todo) [-f | --force]

$(_color_primary "Options"):
  -f, --force     Skip the confirmation prompt.
  --reset         Reset the filename to the last modified timestamp.
  --to-bookmark   Preserve the existing filename and replace the extension
                  with ".bookmark.md" to convert the note to a bookmark.
  --to-note       Preserve the existing filename and replace the bookmark's
                  ".bookmark.md" extension with ".md" to convert the bookmark
                  to a Markdown note.
  --to-title      Set the filename to the note title, lowercased with spaces
                  and disallowed filename characters replaced with underscores.
  --to-todo       Preserve the existing filename and replace the extension
                  with ".todo.md" to convert the note to a todo.

$(_color_primary "Description"):
  Move or rename a note. Move the note to <path> or change the file type.
  When the file extension is omitted, the existing extension is used.
  When only a file extension is specified, only the extension will be updated.

  \`move\` and \`rename\` are aliases and can be used interchangeably.

$(_color_primary "Read More"):
  ${_README_URL}#-moving--renaming

$(_color_primary "See Also"):
  ${_ME} help copy
  ${_ME} help delete
  ${_ME} help edit

$(_color_primary "Examples"):
  # move "example.md" to "sample.org"
  ${_ME} move example.md sample.org

  # rename note 3 ("example.md") to "New Name.md"
  ${_ME} rename 3 "New Name"

  # rename "example.bookmark.md" to "New Name.bookmark.md"
  ${_ME} move example.bookmark.md "New Name"

  # rename note 3 ("example.md") to a bookmark named "example.bookmark.md"
  ${_ME} rename 3 --to-bookmark

  # move note 12 into "Sample Folder" in the "demo" notebook
  ${_ME} move example:12 demo:Sample\ Folder/

  # rename note 12 in the "example" notebook to "sample.md"
  ${_ME} rename example:12 "sample.md"

  # change the file extension of note 5 to .org
  ${_ME} rename 5 .org

$(_color_primary "Alias"):
  ${_ME} rename

$(_color_primary "Shortcut Alias"):
  ${_ME} mv
HEREDOC
}
_move() {
  local _force=0
  local _reset=0
  local _selectors=()
  local _to_target_type=

  while ((${#}))
  do
    case "${1:-}" in
      -f|--force|--skip*|-y|--yes)
        _force=1
        ;;
      --reset)
        _reset=1
        ;;
      --to*bookmark)
        _to_target_type="bookmark"
        ;;
      --to*note)
        _to_target_type="note"
        ;;
      --to*title)
        _to_target_type="title"
        ;;
      --to*todo)
        _to_target_type="todo"
        ;;
      --to)
        _to_target_type="$(_option_get_value "${1:-}" "${2:-}")"

        shift
        ;;
      -*)
        :
        ;;
      *)
        if [[ -n "${1:-}" ]]
        then
          _selectors+=("${1:-}")
        fi
        ;;
    esac

    shift
  done

  local _source_selectors=()
  local _target_selector=

  if ((${#_selectors[@]}))
  then
    if ((${#_selectors[@]} - 1))
    then
      local i=
      for ((i=0; i < ${#_selectors[@]} - 1; i++))
      do
        _source_selectors+=("${_selectors[i]}")
      done

      _target_selector="${_selectors[${#_selectors[@]}-1]}"
    else
      _source_selectors+=("${_selectors[@]}")
    fi
  elif [[ -z "${_to_target_type:-}" ]] &&
       [[ -z "${_reset:-}"          ]]
  then
    _exit_1 _help "move"
  fi

  if ! ((${#_source_selectors[@]}))
  then
    _exit_1 _help "move"
  fi

  local _source_selector=
  for   _source_selector in "${_source_selectors[@]:-}"
  do
    local _source_relative_path=
    _source_relative_path="$(_show "${_source_selector}" --relative-path)"

    if [[ -z "${_source_relative_path:-}"     ]]
    then
      _exit_1 _help "move"
    fi

    local _source_notebook_path=
    if [[ "${_source_selector:-}" =~ :    ]]
    then
      _source_notebook_path="$(
        _notebooks show "${_source_selector}" --path 2>/dev/null || :
      )"
    fi

    if [[ -z "${_source_notebook_path:-}"     ]]
    then
      _source_notebook_path="$(_notebooks current --path)"
    fi

    local _source_basename="${_source_relative_path##*\/}"
    local _source_folder_path="${_source_notebook_path}"
    local _source_path="${_source_notebook_path}/${_source_relative_path}"

    if [[ "${_source_relative_path:-}" =~ /   ]]
    then
      _source_folder_path="${_source_notebook_path}/${_source_relative_path%\/*}"
    fi

    local _source_file_name="${_source_basename%%.*}"
    local _source_file_type="${_source_basename#*.}"

    if [[ -z "${_source_file_type:-}"                     ]] ||
       [[ "${_source_file_type}" == "${_source_basename}" ]]
    then
      _source_file_type=
    fi

    local _target_selector_relative_path=

    if ((_reset))
    then
      local _target_file_name=
      _target_file_name="$(
        date -r "${_source_notebook_path}/${_source_relative_path}" "+%Y%m%d%H%M%S"
      )"

      local _target_file_type="${_source_file_type:-"${NB_DEFAULT_EXTENSION}"}"

      _target_basename="${_target_file_name}.${_target_file_type}"
    elif [[ "${_to_target_type:-}" == "title" ]]
    then
      if ! _file_is_text "${_source_path:-}"
      then
        _exit_1 printf "Must be a text file.\\n"
      fi

      local _source_title=
      _source_title="$(_get_content "${_source_path:-}" --title)"

      if [[ -z "${_source_title:-}"           ]]
      then
        _exit_1 printf "Title not found.\\n"
      fi

      local _sanitized_filename=
      _sanitized_filename="$(_get_sanitized_filename "${_source_title:-}")"

      local _target_file_type="${_source_file_type:-"${NB_DEFAULT_EXTENSION}"}"

      _target_basename="${_sanitized_filename}.${_target_file_type}"
    elif [[ -n "${_target_selector:-}"        ]] ||
         [[ -n "${_to_target_type:-}"         ]]
    then
      _target_selector_relative_path="${_target_selector#*:}"

      local _target_basename="${_target_selector_relative_path##*\/}"
      local _target_file_name="${_target_basename%%.*}"
      local _target_file_type="${_target_basename#*.}"

      if [[   -n "${_target_file_type:-}"                         ]] &&
         [[   -z "${_target_file_name:-}"                         ]]
      then # only file extension in target
        _target_selector_relative_path=""
      elif [[ -z "${_target_file_type:-}"                         ]] ||
           [[    "${_target_file_type}" == "${_target_basename}"  ]]
      then # no file extension in target
        if [[ -n "${_source_file_type}"                           ]]
        then
          _target_file_type="${_source_file_type}"
        else
          _target_file_type=
        fi
      fi

      case "${_to_target_type:-}" in
        '')       :                                               ;;
        bookmark) _target_file_type="bookmark.md"                 ;;
        note)     _target_file_type="${NB_DEFAULT_EXTENSION:-md}" ;;
        todo)     _target_file_type="todo.md"                     ;;
        *)        _target_file_type="${_to_target_type#.}"        ;;
      esac

      if [[ -z "${_target_file_name:-}" ]]
      then
        _target_file_name="${_source_file_name}"
      fi

      if [[ -n "${_target_file_type:-}" ]]
      then
        _target_basename="${_target_file_name}.${_target_file_type}"
      else
        _target_basename="${_target_file_name}"
      fi
    else
      _exit_1 _help "move"
    fi

    _target_basename="$(_normalize_encoding "${_target_basename}")"

    if [[ -z  "${_target_selector_relative_path:-}" ]]
    then
      if [[   "${_source_relative_path}" =~ /       ]]
      then
        _target_selector_relative_path="${_source_relative_path%/*}/${_target_basename}"
      else
        _target_selector_relative_path="${_target_basename}"
      fi
    fi

    local _target_info=
    local _target_notebook_path=

    if [[       "${_target_selector:-}" =~ :  ]]
    then
      _target_notebook_path="$(
        _notebooks show "${_target_selector:-}" --path 2>/dev/null || :
      )"

      if [[ -z  "${_target_notebook_path:-}"  ]]
      then
        _exit_1 printf "Target notebook not found: %s\\n" "${_target_selector%%:*}"
      fi
    else
      _target_notebook_path="$(_notebooks current --path)"
    fi

    if _notebooks current --selected ||
       [[ "${_target_notebook_path}" != "$(_notebooks current --path)" ]]
    then
      _target_info="$(_notebooks show "${_target_notebook_path}" --name --no-color):"
    fi

    local _target_folder_relative_path=

    if [[ -n "${_target_selector_relative_path:-}"  ]]
    then
      _target_folder_relative_path="$(
        _selector_resolve_folders "${_target_selector_relative_path}" --build || :
      )"

      if [[ -z "${_target_folder_relative_path:-}"  ]]
      then
        _target_folder_relative_path="${_target_selector_relative_path%\/*}"
      fi
    fi

    local _target_folder_path=
    local _target_relative_path=

    if [[   "${_target_selector_relative_path:-}" =~ /            ]]
    then
      _target_folder_path="${_target_notebook_path}/${_target_folder_relative_path}"
      _target_relative_path="${_target_folder_relative_path}/${_target_basename}"
    else
      _target_folder_path="${_target_notebook_path}"
      _target_relative_path="${_target_basename}"
    fi

    _target_info+="${_target_relative_path}"

    if [[ -e  "${_target_notebook_path}/${_target_relative_path}" ]]
    then
      _exit_1 printf "File already exists: %s\\n"         \
        "$(_color_primary "${_target_info}")"
    fi

    if ! ((_force))
    then
      printf "Moving:   %s\\n" "$(_show "${_source_path}" --info-line)"
      printf "To:       %s\\n" "$(_color_primary "${_target_info}")"

      while true
      do
        local __yn=
        IFS='' read -r -e -d $'\n' -p                     \
"$(_color_primary "Proceed?")  $(_color_brackets "y/N") " __yn

        case "${__yn}" in
          [Yy]*)
            break
            ;;
          *)
            printf "Exiting%s\\n" "$(_color_muted "...")"

            exit 0
            ;;
        esac
      done
    fi

    if [[ ! -e "${_target_folder_path}" ]]
    then
      mkdir -p "${_target_folder_path}" ||
        _exit_1 printf "Unable to create folder: %s\\n"   \
          "$(_color_primary "${_target_folder_path}")"
    fi

    mv "${_source_path}" "${_target_notebook_path}/${_target_relative_path}" ||
      _exit_1 printf "Move failed.\\n"

    if [[ -e "${_source_folder_path:-}/.pindex"           ]]  &&
       grep -q  "^${_source_basename}$"     "${_source_folder_path:-}/.pindex"
    then
      if [[ "${_source_folder_path}" == "${_target_folder_path}"    ]]
      then
        _sed_i -e                                         \
          "s/^${_source_basename}$/${_target_basename}/"  \
          "${_source_folder_path:-}/.pindex"
      else
        _sed_i -e                                         \
          "/^${_source_basename}$/d"                      \
          "${_source_folder_path:-}/.pindex"

        if [[ ! -e "${_target_folder_path:-}/.pindex"     ]]
        then
          touch "${_target_folder_path:-}/.pindex"
        fi

        printf "%s\\n" "${_target_basename}" >> "${_target_folder_path:-}/.pindex"
      fi
    fi

    if [[ "${_source_notebook_path}" == "${_target_notebook_path}"  ]]
    then
      if [[ "${_source_folder_path}" == "${_target_folder_path}"    ]]
      then
        _index update               \
          "${_source_basename}"     \
          "${_target_basename}"     \
          "${_source_folder_path}"
      else
        _index delete "${_source_basename}" "${_source_folder_path}"  &&
          _index add  "${_target_basename}" "${_target_folder_path}"
      fi || _exit_1 printf "Move index update failed.\\n"

      _git checkpoint "${_target_notebook_path}"  \
        "[${_ME}] Move: ${_source_relative_path} to ${_target_relative_path}"
    else
      _index delete "${_source_basename}" "${_source_folder_path}"

      _git checkpoint "${_source_notebook_path}"  \
        "[${_ME}] Delete: ${_source_relative_path}"

      _index add "${_target_basename}" "${_target_folder_path}"

      _git checkpoint "${_target_notebook_path}"  \
        "[${_ME}] Add: ${_target_relative_path}"
    fi

    printf "Moved to: %s\\n" "$(
      _show "${_target_notebook_path}/${_target_relative_path}" --info-line
    )"
  done
}
_alias_subcommand "move" "mv"
_alias_subcommand "move" "rename"

# open ################################################################### open

_describe_open() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} open ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])

$(_color_primary "Description"):
  Open an item or notebook. When the item is a bookmark, open the bookmarked
  page in your system's primary web browser. When the item is in a text format
  or any other file type, \`open\` is the equivalent of \`edit\`. \`open\`
  with a notebook opens the notebook folder in the system's file browser.

$(_color_primary "Read More"):
  ${_README_URL}#viewing-bookmarks

$(_color_primary "See also"):
  ${_ME} help bookmark
  ${_ME} help browse
  ${_ME} help peek
  ${_ME} help show

$(_color_primary "Examples"):
  ${_ME} open 3
  ${_ME} open example.bookmark.md
  ${_ME} 3 open
  ${_ME} example:open 12
  ${_ME} open example:12
  ${_ME} example:12 open
  ${_ME} o 3
  ${_ME} 3 o
  ${_ME} o example:12
  ${_ME} example:12 o

$(_color_primary "Shortcut Alias"):
  ${_ME} o
HEREDOC
}
_open() {
  if [[ -z "${1:-}" ]]
  then
    _exit_1 _help "open"
  fi

  _bookmark open "${@:-}"
}
_alias_subcommand "open" "o"

# peek ################################################################### peek

_describe_peek() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} peek ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])

$(_color_primary "Description"):
  View an item or notebook in the terminal. When the item is a bookmark, view
  the bookmarked page in your terminal web browser. When the note is in a text
  format or any other file type, \`peek\` is the equivalent of \`show\`. When
  used with a notebook, \`peek\` opens the notebook folder first tool found in
  the following list: \`ranger\` [1], \`mc\` [2], \`vifm\` [3], \`joshuto\` [4],
  \`lsd\` [5] \`eza\` [6], or \`ls\`.

    1. https://ranger.github.io/
    2. https://en.wikipedia.org/wiki/Midnight_Commander
    3. https://vifm.info/
    4. https://github.com/kamiyaa/joshuto
    5. https://github.com/lsd-rs/lsd
    6. https://github.com/eza-community/eza

$(_color_primary "Read More"):
  ${_README_URL}#viewing-bookmarks

$(_color_primary "See also"):
  ${_ME} help bookmark
  ${_ME} help browse
  ${_ME} help open
  ${_ME} help show

$(_color_primary "Examples"):
  ${_ME} peek 3
  ${_ME} peek example.bookmark.md
  ${_ME} 3 peek
  ${_ME} example:peek 12
  ${_ME} peek example:12
  ${_ME} example:12 peek
  ${_ME} p 3
  ${_ME} 3 p
  ${_ME} p example:12
  ${_ME} example:12 p

$(_color_primary "Alias"):
  ${_ME} preview

$(_color_primary "Shortcut Alias"):
  ${_ME} p
HEREDOC
}
_peek() {
  if [[ -z "${1:-}" ]]
  then
    _exit_1 _help "peek"
  fi

  _bookmark peek "${@}"
}
_alias_subcommand "peek" "p"
_alias_subcommand "peek" "preview"

# pin ##################################################################### pin

_describe_pin() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} pin ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])

$(_color_primary "Description"):
  Pin an item so it appears first in lists.

$(_color_primary "Read More"):
  ${_README_URL}#-pinning

$(_color_primary "See Also"):
  ${_ME} help browse
  ${_ME} help list
  ${_ME} help ls
  ${_ME} help unpin

$(_color_primary "Examples"):
  ${_ME} pin 123
  ${_ME} pin example:sample/321
HEREDOC
}
_pin() {
  local _selector=
  local _subcommand="pin"

  local __arg=
  for   __arg in "${@:-}"
  do
    case "${__arg:-}" in
      unpin)  _subcommand="unpin"     ;;
      *)      _selector="${__arg:-}"  ;;
    esac
  done

  if [[ -z "${_selector:-}" ]]
  then
    _warn _help "${_subcommand}"

    return 1
  fi

  local _item_path=
  _item_path="$(_show "${_selector}" --path)" || return 1

  local _basename="${_item_path##*\/}"
  local _folder_path="${_item_path%\/*}"
  local _pindex_path="${_folder_path}/.pindex"

  local _notebook_path=
  _notebook_path="$(
    _notebooks show "${_selector}" --path 2>/dev/null ||
      _notebooks current --path
  )"

  local _relative_path=
  _relative_path="$(_show "${_selector}" --relative-path)"

  if [[ ! -e "${_item_path:-}"        ]] ||
     [[ ! -d "${_folder_path:-}"      ]] ||
     [[   -z "${_basename:-}"         ]] ||
     [[   -z "${_notebook_path:-}"    ]] ||
     [[   -z "${_relative_path:-}"    ]]
  then
    _warn printf "Not found: %s\\n" "${_selector}"

    return 1
  fi

  case "${_subcommand:-}" in
    unpin)
      if [[ ! -e "${_pindex_path}"    ]] ||
         ! grep -q "^${_basename}$" "${_pindex_path}"
      then
        _warn printf                  \
          "Not pinned: %s\\n"         \
          "$(_color_primary "${_selector}")"

        return 1
      fi

      _sed_i -e "s/^${_basename}$//g"   "${_pindex_path}"
      _sed_i -e '/^[[:space:]]*$/d'     "${_pindex_path}" # remove blank line

      if [[ ! -s "${_pindex_path:?}"  ]]
      then
        rm -f "${_pindex_path:?}"
      fi

      _git checkpoint "${_notebook_path}" "[${_ME}] Unpinned: ${_relative_path}"

      printf "Unpinned: %s\\n" "$(_show "${_selector}" --info-line)"
      ;;
    *)
      if [[ ! -e "${_pindex_path}"    ]]
      then
        touch "${_pindex_path}"
      fi

      if grep -q "^${_basename}$" "${_pindex_path}"
      then
        _warn printf                  \
          "Already pinned: %s\\n"     \
          "$(_color_primary "${_selector}")"

        return 1
      else
        printf "%s\\n" "${_basename}" >> "${_pindex_path}"
        _sed_i -e '/^[[:space:]]*$/d'    "${_pindex_path}" # remove blank lines

        _git checkpoint "${_notebook_path}" "[${_ME}] Pinned: ${_relative_path}"

        printf "Pinned: %s\\n" "$(_show "${_selector}" --info-line)"
      fi
      ;;
  esac
}

# run ##################################################################### run

_describe_run() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} run <command> [<arguments>...]

$(_color_primary "Description"):
  Run shell commands within the current notebook directory.

$(_color_primary "See Also"):
  ${_ME} help git
  ${_ME} help shell

$(_color_primary "Examples"):
  ${_ME} run ls -la
  ${_ME} run find . -name 'example*'
  ${_ME} run rg example
HEREDOC
}
_run() {
  local _notebook_path=
  _notebook_path="$(_notebooks current --path)"

  cd "${_notebook_path}"  || _exit_1 printf "_run() \`cd\` failed.\\n"
  [[ -n "${*}" ]]         || _exit_1 printf "Command required.\\n"

  if ! _command_exists "${1:-}"
  then
    _warn printf "Command not found: %s\\n" "$(_color_primary "${1:-}")"

    exit 127
  fi

  ("${@}")
}
_alias_subcommand "run" "r"

# search ############################################################### search

_describe_search() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} search ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
            <query>... [-a | --all] [--and <query>] [--not <query>] [--or <query>]
            [-l | --list] [--path] [-t <tag1>,<tag2>... | --tag <tag1>,<tag2>...]
            [-t | --tags] [--type <type> | --<type>] [--utility <name>]

$(_color_primary "Options"):
  -a, --all                     Search all unarchived notebooks.
  --and <query>                 Add a AND query.
  -l, --list                    Print the id, filename, and title listing for
                                each matching file, without the excerpt.
  --not <query>                 Add a NOT query.
  --or  <query>                 Add an OR query.
  --path                        Print the full path for each matching file.
  -t, --tag <tag1>,<tag2>...    A comma-separated list of tags.
  -t, --tags                    List all tags found in the notebook.
  --type <type>, --<type>       Search items of <type>. <type> can be a file
                                extension or one of the following types:
                                archive, audio, book, bookmark, document,
                                folder, image, note, text, video
  --utility <name>              The name of the search utility to search with.

$(_color_primary "Description"):
  Perform a full text search.

  Multiple query arguments are treated as AND queries, returning items that
  match all queries. AND queries can also be specified with the --and <query>
  option. The --or <query> option can be used to specify an OR query,
  returning items that match at least one of the queries. --not <query>
  excludes items matching <query>.

  \`${_ME} search\` is powered by Git's built-in \`git grep\` tool. \`${_ME}\` also
  supports performing searches with alternative search tools using the
  --utility <name> option.

  Supported alternative search tools:
    1. \`rga\`   https://github.com/phiresky/ripgrep-all
    2. \`rg\`    https://github.com/BurntSushi/ripgrep
    3. \`ag\`    https://github.com/ggreer/the_silver_searcher
    4. \`ack\`   https://beyondgrep.com/
    5. \`grep\`  https://en.wikipedia.org/wiki/Grep

$(_color_primary "Read More"):
  ${_README_URL}#-search

$(_color_primary "See Also"):
  ${_ME} help browse
  ${_ME} help list
  ${_ME} help ls

$(_color_primary "Examples"):
  # search current notebook for "example query"
  ${_ME} search "example query"

  # search the notebook "example" for "example query"
  ${_ME} search example: "example query"

  # search all notebooks for "example query" and list matching items
  ${_ME} search "example query" --all --list

  # search for items matching "Example" AND "Demo"
  ${_ME} search "Example" "Demo"
  ${_ME} search "Example" --and "Demo"

  # search for items matching "Example" OR "Sample"
  ${_ME} search "Example|Sample"
  ${_ME} search "Example" --or "Sample"

  # search for items matching both "Example" AND "Sample", and NOT "Demo"
  ${_ME} search "Example" --and "Sample" --not "Demo"

  # search with a regular expression
  ${_ME} search "\d\d\d-\d\d\d\d"

  # search for tags
  ${_ME} search --tag tag1 -t tag2

  # search the current notebook for "example query"
  ${_ME} q "example query"

  # search all notebooks for "example query" and list matching items
  ${_ME} q -la "example query"

$(_color_primary "Shortcut Alias"):
  ${_ME} q
HEREDOC
}
_search() {
  # Usage: _search_with <command-name> <search-utility>
  _search_with() {
    _command_exists "${1:?}" && [[ "${2:-}" == "${1:?}" ]]
  }

  local _all=0
  local _and_queries=()
  local _not_queries=()
  local _arguments=()
  local _last_path=
  local _limit=0
  local _max_columns="2000"
  local _max_depth=0
  local _only_list=0
  local _option_tags=()
  local _or_queries=()
  local _page=1
  local _print_notebook_selectors=0
  local _print_paths=0
  local _query=
  local _replacement=
  local _search_args=()
  local _search_for_tags=0
  local _search_utility=
  local _selectors=()
  local _sort=0
  local _type=

  while ((${#}))
  do
    case "${1:-}" in
      -a|--all)
        _all=1
        ;;
      --and|--not|--or)
        local _operator="${1#--}"

        if [[ "${2:-}" == "-e" ]]
        then
          shift
        fi

        if [[ "${2:-}" =~ (^-t$|^--tag*|^--hashtag*) ]] &&
           _option_value_is_present "${3:-}"
        then
          shift

          IFS=' ' read -ra _option_tags <<< "$(
            _option_get_tags "${1:-}" "${2:-}"
          )"

          if [[   "${_operator:-}" == "and" ]]
          then
            _and_queries+=(${_option_tags[@]:-})
          elif [[ "${_operator:-}" == "not" ]]
          then
            _not_queries+=(${_option_tags[@]:-})
          else
            _or_queries+=(${_option_tags[@]:-})
          fi

          shift
        else
          if [[   "${_operator:-}" == "and" ]]
          then
            _and_queries+=("$(_option_get_value "--and" "${2:-}")")
          elif [[ "${_operator:-}" == "not" ]]
          then
            _not_queries+=("$(_option_get_value "--not" "${2:-}")")
          else
            _or_queries+=("$(_option_get_value "--or" "${2:-}")")
          fi

          shift
        fi
        ;;
      --limit|-n|--num|--number|--per*)
        _limit="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      -l|--list)
        _only_list=1
        ;;
      --no*color)
        _COLOR_ENABLED=0
        ;;
      --no*recur*)
        _max_depth=1
        ;;
      --notebook-selectors)
        _print_notebook_selectors=1
        ;;
      --page)
        _page="$(_option_get_value "${1}" "${2:-}")"
        ((_page)) || _page=1

        shift
        ;;
      --path*)
        _print_paths=1
        _COLOR_ENABLED=0
        ;;
      -q|--query|-e)
        _and_queries+=("$(_option_get_value "${1}" "${2:-}")")

        shift
        ;;
      --replace*)
        # TODO
        _replacement="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      -s|--sort)
        _sort=1
        ;;
      -t|--tag*|--hashtag*)
        if _option_value_is_present "${2:-}"
        then
          IFS=' ' read -ra _option_tags <<< "$(
            _option_get_tags "${1:-}" "${2:-}"
          )"

          _and_queries+=(${_option_tags[@]:-})

          shift
        else
          _search_for_tags=1
        fi
        ;;
      --*tool|--*utility)
        _search_utility="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      --type)
        _type="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      --use*grep)
        # TODO: Remove. Replaced with the --tool / --utility option.
        _search_utility="grep"
        ;;
      *)
        if [[ "${1:-}" =~ ^-- ]]
        then
          _type="${1:2}"
        else
          _arguments+=("${1}")
        fi
        ;;
    esac

    shift
  done

  if [[ -z "${_search_utility:-}"                       ]] &&
     [[ -n "${NB_SEARCH_TOOL:-${NB_SEARCH_UTILITY:-}}"  ]]
  then
    _search_utility=${NB_SEARCH_TOOL:-${NB_SEARCH_UTILITY:-}}
  fi

  local _current_notebook_path=
  _current_notebook_path="$(_notebooks current --path)"

  local _local_notebook_path=
  _local_notebook_path="$(_notebooks --local --path || :)"

  local _target_paths=()

  if ((_all))
  then
    _target_paths=($(_notebooks --paths --unarchived))
  fi

  local i=
  for ((i=0; i < ${#_arguments[@]}; i++))
  do
    local _maybe_path=

    if [[ -z "${_arguments[i]:-}"     ]]
    then
      continue
    elif [[ "${_arguments[i]}" =~ :$  ]]
    then
      _maybe_path="$(
        _notebooks show "${_arguments[i]}" --path 2>/dev/null || :
      )"

      if [[ -n "${_maybe_path:-}"     ]]
      then
        _notebooks select "${_arguments[i]}"
      fi
    else
      if [[ "${_arguments[i]}" =~ ^/  ]]
      then
        _maybe_path="${_arguments[i]%/}"
      else
        _maybe_path="$(
          _selector_resolve_path "${_arguments[i]:-}" \
            --full                                    \
            --skip-titles                             \
            2>/dev/null || :
        )"
      fi
    fi

    if [[ -z "${_maybe_path:-}"                     ]] ||
       {
         [[ "${i}" -eq "$((${#_arguments[@]} - 1))" ]] &&
         [[ -z "${_and_queries[*]:-}"               ]]
       }
    then
      local _query_argument="${_arguments[i]:-}"

      if [[ "${_query_argument:-}"    =~ ^[^/]*/$   ]]
      then
        if [[ -d "${_maybe_path:-}"   ]]
        then
          _query_argument=
        else
          _query_argument="${_query_argument%\/}"
        fi
      fi

      if _notebooks current --selected
      then
        _and_queries+=("${_query_argument#*:}")
      else
        _and_queries+=("${_query_argument}")
      fi
    fi

    if [[ -n "${_maybe_path:-}"       ]] &&
       [[ -z "${_target_paths[*]:-}"  ]] &&
       {
         _notebooks current --selected   ||
         [[ "${#_arguments[@]}" -gt 1 ]] ||
         ((_search_for_tags))
       }
    then
      _target_paths+=("${_maybe_path}")
      _selectors+=("${_arguments[i]}")
    fi
  done

  if [[ -z "${_target_paths[*]:-}"    ]]
  then
    _target_paths=("${_current_notebook_path}")
  fi

  local _xargs=("-0")

  if xargs --help &> /dev/null
  then # GNU (BSD does this by default)
    _xargs+=("--no-run-if-empty")
  fi

  if ((_search_for_tags))
  then
    local _git_major_version=
    _git_major_version="$(git --version | cut -d " "  -f 3 | cut -d "." -f 1)"

    local _git_minor_version=
    _git_minor_version="$(git --version | cut -d " "  -f 3 | cut -d "." -f 2)"

    local _use_git_grep=0

    if ((_GIT_ENABLED))                           &&
       [[ "${_git_major_version:-}"   -gt 2   ]]  ||  {
         [[ "${_git_major_version:-}" ==  2   ]]  &&
         [[ "${_git_minor_version:-}" -ge 19  ]]
    }
    then # git 2.19+ has --only-matching option
      _use_git_grep=1
    fi

    if ((_use_git_grep))
    then
      local _grep_arguments=(
        "--extended-regexp"
        "-I"
        "--ignore-case"
        "--only-matching"
        -e '(^|[[:space:]])#[[:alnum:]/_-]+'
      )
    else
      local _grep_arguments=(
        "--extended-regexp"
        "-I"
        "--ignore-case"
        "--only-matching"
        -e '[[:space:]]#[[:alnum:]/_-]+'
        -e '^#[A-Za-z0-9/_-]+'
      )
    fi

    {
      local __target_path=
      for   __target_path in "${_target_paths[@]:-}"
      do
        [[ -n "${__target_path:-}"    ]] || continue

        if [[ -d "${__target_path:-}" ]]
        then
          local _target_folder_path="${__target_path:-}"
        else
          local _target_folder_path="${__target_path%/*}"
        fi

        {
          if ((_use_git_grep))
          then
            GIT_PAGER=''                      \
              git -C "${_target_folder_path}" \
              grep                            \
              "${_grep_arguments[@]:-}"       \
              --files-with-matches            \
              --null                          \
              "${__target_path}"              \
              2>/dev/null || true
          else
            {
              find "${__target_path}"         \
                ! -path '*/.git*'             \
                -path '*/[^.]*'               \
                -type f                       \
                -print0
            } | {
              xargs "${_xargs[@]}"            \
                grep                          \
                "${_grep_arguments[@]:-}"     \
                --files-with-matches          \
                --null
            }
          fi
        } | {
          if ((_use_git_grep))
          then
            GIT_PAGER=''                      \
              xargs "${_xargs[@]}"            \
              git -C "${_target_folder_path}" \
              grep                            \
              "${_grep_arguments[@]:-}"       \
              -e "## Comment"                 \
              -e "## Tags"                    \
              -e "## Content"                 \
              -e "## Page Content"            \
              -e "## Source"                  \
              2>/dev/null || true
          else
            xargs "${_xargs[@]}"              \
              grep                            \
              "${_grep_arguments[@]:-}"       \
              -e "## Comment"                 \
              -e "## Tags"                    \
              -e "## Content"                 \
              -e "## Page Content"            \
              -e "## Source"                  \
              2>/dev/null || true
          fi
        }
      done
    } | {
      local _last_match_path=
      local _match_path=
      local _seen_matches=()
      local _skip=1

      local         __match=
      while read -r __match
      do
        if [[ "${__match:-}" =~ : ]]
        then
          _match_path="${__match%:*}"
        fi

        local _normalized_match="${__match##*:}"
        _normalized_match="${_normalized_match#"${_normalized_match%%[![:space:]]*}"}"
        _normalized_match="${_normalized_match%"${_normalized_match##*[![:space:]]}"}"

        if [[ "${_match_path:-}"              =~ \.bookmark\.md$    ]]
        then
          if [[ "${_last_match_path:-}"       != "${_match_path:-}" ]]
          then
            _skip=1
            _last_match_path="${_match_path}"
          fi

          if [[ "${_normalized_match:-}"      =~ ^##                ]]
          then
            if [[ "${_normalized_match:-}"    =~ (Comment|Tags)     ]]
            then
              _skip=0
            elif [[ "${_normalized_match:-}"  =~ (Content|Source)   ]]
            then
              _skip=1
            fi

            continue
          fi

          if ((_skip))
          then
            continue
          fi
        elif [[ "${_normalized_match:-}"      =~ ^##                ]]
        then
          continue
        fi

        if ! _contains "${_normalized_match}" "${_seen_matches[@]:-}"
        then
          printf "%s\\n" "${_normalized_match:-}"
          _seen_matches+=("${_normalized_match:-}")
        fi
      done

      if ! ((${#_seen_matches[@]}))
      then
        printf "No #hashtags found.\\n"
      fi
    }

    return 0
  fi

  if [[ -z "${_and_queries[*]:-}" ]] &&
     [[ -z "${_not_queries[*]:-}" ]]
  then
    _exit_1 _help "search"
  fi

  local _queries=()

  local __and_query=
  for   __and_query in "${_and_queries[@]:-}"
  do
    [[ -n "${__and_query:-}"            ]] || continue

    if [[ "${_and_query:-}" =~ ^\#      ]]
    then
      _and_query="${_and_query}$"
    fi

    if ((${#_or_queries[@]}))
    then
      local _or_query_string=

      local __or_query=
      for   __or_query in "${_or_queries[@]:-}"
      do
        [[ -n "${__or_query:-}"         ]] || continue

        if [[ "${__or_query:-}" =~ ^\#  ]]
        then
          __or_query="${__or_query}$"
        fi

        _or_query_string="${_or_query_string}|${__or_query}"
      done

      _queries+=("${__and_query}${_or_query_string}")
    else
      _queries+=("${__and_query}")
    fi
  done

  local _query=
  _query="$(_join "|" "${_queries[@]:-}")"

  if [[ -z "${_query:-}"          ]] &&
     [[ -n "${_not_queries[*]:-}" ]]
  then
    _only_list=1
  fi

  {
    local __target_path=
    for   __target_path in "${_target_paths[@]:-}"
    do
      if [[ -d "${__target_path}" ]]
      then
        local _target_folder_path="${__target_path}"
      else
        local _target_folder_path="${__target_path%\/*}"
      fi

      local _max_id=
      _max_id="$(_index get_max_id "${_target_folder_path}")"

      {
        if _search_with "rg" "${_search_utility:-}"
        then
          local _rg_command="rg"

          if _command_exists "rga"
          then
            _rg_command="rga"
          fi

          if ((_max_depth))
          then
            _search_args+=("--max-depth" "${_max_depth}")
          fi

          if ((_COLOR_ENABLED))
          then
            _search_args+=("--color" "always")
          else
            _search_args+=("--color" "never")
          fi

          if ((_sort))
          then
            _search_args+=("--sort-files")
          fi

          local _search_paths=("${__target_path}")

          if [[ -f "${__target_path}"     ]] &&
             [[ "${#_arguments[@]}" -le 1 ]]
          then
            _search_paths+=("${__target_path%\/*}/.index")
          fi

          "${_rg_command}"                  \
            --hidden                        \
            --iglob '!.git'                 \
            --ignore-case                   \
            --line-number                   \
            --max-columns "${_max_columns}" \
            --max-columns-preview           \
            --no-heading                    \
            --with-filename                 \
            "${_search_args[@]}"            \
            "${_query}"                     \
            "${_search_paths[@]:-}"         \
              || return 0 # Don't fail out within a single scope.
        elif _search_with "ag" "${_search_utility:-}"
        then
          if ((_max_depth))
          then
            _search_args+=("--norecurse")
          fi

          if ((_COLOR_ENABLED))
          then
            _search_args+=("--color")
            _search_args+=("--color-line-number"  "32")
            _search_args+=("--color-match"        "1;35")
          else
            _search_args+=("--nocolor")
          fi

          # TODO: ag doesn't support sorting directly.
          # if ((_sort))
          # then
          #   _search_args+=("--workers" "1")
          # fi

          local _search_paths=("${__target_path}")

          if [[ -f "${__target_path}"     ]] &&
             [[ "${#_arguments[@]}" -le 1 ]]
          then
            _search_paths+=("${__target_path%\/*}/.index")
          fi

          ag                      \
            --filename            \
            --hidden              \
            --ignore ".git"       \
            --ignore-case         \
            --noheading           \
            "${_search_args[@]}"  \
            "${_query}"           \
            "${_search_paths[@]}" \
              || return 0 # Don't fail out within a single scope.
        elif _search_with "ack" "${_search_utility:-}"
        then # ack is available.
          if ((_max_depth))
          then
            _search_args+=("--no-recurse")
          fi

          if ((_COLOR_ENABLED))
          then
            _search_args+=("--color")
            _search_args+=("--color-lineno=bold green")
            _search_args+=("--color-match=blue on_black")
          else
            _search_args+=("--nocolor")
          fi

          if ((_sort))
          then
            _search_args+=("--sort-files")
          fi

          local _search_paths=("${__target_path}")

          if [[ -f "${__target_path}"     ]] &&
             [[ "${#_arguments[@]}" -le 1 ]]
          then
            _search_paths+=("${__target_path%\/*}/.index")
          fi

          ack                     \
            --ignore-case         \
            --noheading           \
            --with-filename       \
            "${_search_args[@]}"  \
            "${_query}"           \
            "${_search_paths[@]}" \
              || return 0 # Don't fail out within a single scope.
        elif _search_with "grep" "${_search_utility:-}"
        then
          if _grep_supports_color
          then
            if ((_COLOR_ENABLED))
            then
              _search_args+=("--color=always")
            else
              _search_args+=("--color=never")
            fi
          fi

          set +f
          {
            if [[ -f "${__target_path:-}"     ]]
            then
              if [[ "${#_arguments[@]}" -le 1 ]]
              then
                # Print .index with null byte delimiter so it's included in
                # the list of files to search.
                printf "%s/.index\0%s" "${__target_path%\/*}" "${__target_path}"
              else
                printf "%s" "${__target_path}"
              fi
            elif [[ "${_max_depth}" == 1      ]]
            then
              # Print .index with null byte delimiter so it's included in
              # the list of files to search.
              printf "%s/.index\0" "${__target_path}"
              find "${__target_path}"/*   \
                \( -name . -o -prune \)   \
                -type f                   \
                -print0
            else
              find "${__target_path}"                     \
                ! -path '*/.git*'                         \
                \( -path '*/.index' -o -path '*/[^.]*' \) \
                -type f                                   \
                -print0
            fi
          } | {
            # Add /dev/null so file path is printed even if there is only one
            # matching file. Reference: https://stackoverflow.com/a/15432718
            xargs -0 grep           \
              -E                    \
              --ignore-case         \
              "${_search_args[@]}"  \
              --text                \
              -n                    \
              "${_query}"           \
              /dev/null             \
                || return 0 # Don't fail out within a single scope.
          }
          set -f
        else
          local _notebook_path=
          _notebook_path="$(_notebooks show "${__target_path:-}" --path)"

          local _escaped_notebook_path=
          _escaped_notebook_path="$(
            printf "%s\\n" "${_notebook_path:-}" | LC_ALL=C sed 's/\//\\\//g'
          )"

          if ((_max_depth))
          then
            _search_args+=("--no-recursive")
          fi

          local _search_args_no_color=("--color=never")

          if [[ -n "${_search_args[*]:-}" ]]
          then
            _search_args_no_color+=("${_search_args[@]:-}")
          fi

          if ((_COLOR_ENABLED))
          then
            _search_args+=("--color=always")
          else
            _search_args+=("--color=never")
          fi

          local _search_paths=("${__target_path}")

          if [[ -f "${__target_path}"     ]] &&
             [[ "${#_arguments[@]}" -le 1 ]]
          then
            _search_paths+=("${__target_path%\/*}/.index")
          fi

          if [[ "${#_queries[@]}" == 1 ]]
          then
            GIT_PAGER='' git -C "${_notebook_path}"               \
              grep                                                \
              --extended-regexp                                   \
              --ignore-case                                       \
              --line-number                                       \
              --text                                              \
              "${_search_args[@]:-}"                              \
              -e "${_query:-}"                                    \
              "${_search_paths[@]:-}"                             \
            | LC_ALL=C sed -e "s/^/${_escaped_notebook_path}\//"  \
              || return 0  # Don't fail out within a single scope.
          else
            local __search_group=
            for   __search_group in "index" "files"
            do
              {
                if [[ "${__search_group}" == "index" ]]
                then
                  # list all .index files
                  GIT_PAGER='' git -C "${_notebook_path}" \
                    ls-files -z '*.index'
                else
                  # list all non-.index files
                  GIT_PAGER='' git -C "${_notebook_path}" \
                    ls-files -z -- . ':!:*.index'
                fi
              } | {
                local _last_pipe=
                local _this_pipe=

                local __and_query=
                for   __and_query in "${_queries[@]:-}"
                do
                  [[ -n "${__and_query:-}"    ]] || continue

                  _this_pipe=$(_temp file --touch) && {
                    rm -f   "${_this_pipe}"
                    mkfifo  "${_this_pipe}"
                  }

                  if [[ -p "${_last_pipe:-}"  ]]
                  then
                    <"${_last_pipe:-}" cat
                  else
                    cat
                  fi | {
                    GIT_PAGER='' xargs "${_xargs[@]}" \
                      git -C "${_notebook_path}"      \
                      grep                            \
                      --extended-regexp               \
                      --files-with-matches            \
                      --ignore-case                   \
                      --null                          \
                      --text                          \
                      "${_search_args_no_color[@]:-}" \
                      -e "${__and_query:-}"           \
                        || return 0  # Don't fail out within a single scope.
                  } > "${_this_pipe:-}" &

                  _last_pipe="${_this_pipe:-}"
                done

                if [[ -p "${_last_pipe:-}"    ]]
                then
                  <"${_last_pipe:-}" cat
                else
                  cat
                fi
              } | {
                local _last_pipe=
                local _this_pipe=

                local __not_query=
                for   __not_query in "${_not_queries[@]:-}"
                do
                  [[ -n "${__not_query:-}"    ]] || continue

                  _this_pipe=$(_temp file --touch) && {
                    rm -f   "${_this_pipe}"
                    mkfifo  "${_this_pipe}"
                  }

                  if [[ -p "${_last_pipe:-}"  ]]
                  then
                    <"${_last_pipe:-}" cat
                  else
                    cat
                  fi | {
                    GIT_PAGER='' xargs "${_xargs[@]}" \
                      git -C "${_notebook_path}"      \
                      grep                            \
                      --extended-regexp               \
                      --files-without-match           \
                      --ignore-case                   \
                      --null                          \
                      --text                          \
                      "${_search_args_no_color[@]:-}" \
                      -e "${__not_query:-}"           \
                        || return 0  # Don't fail out within a single scope.
                  } > "${_this_pipe:-}" &

                  _last_pipe="${_this_pipe:-}"
                done

                if [[ -p "${_last_pipe:-}"    ]]
                then
                  <"${_last_pipe:-}" cat
                else
                  cat
                fi
              } | {
                if [[ "${__search_group}" == "index" ]]
                then
                  local i=
                  for ((i=0; i < ${#_queries[@]}; i++))
                  do
                    [[ -n "${_queries[i]:-}"  ]] || continue

                    if ! ((i))
                    then
                      _search_args+=("-e" "${_queries[i]:-}")
                    else
                      _search_args+=("--and" "-e" "${_queries[i]:-}")
                    fi
                  done

                  GIT_PAGER='' xargs "${_xargs[@]}"                     \
                    git -C "${_notebook_path}"                          \
                    grep                                                \
                    --extended-regexp                                   \
                    --ignore-case                                       \
                    --line-number                                       \
                    --text                                              \
                    "${_search_args[@]:-}"                              \
                  | LC_ALL=C sed -e "s/^/${_escaped_notebook_path}\//"  \
                    || return 0  # Don't fail out within a single scope.
                else
                  GIT_PAGER='' xargs "${_xargs[@]}"                     \
                    git -C "${_notebook_path}"                          \
                    grep                                                \
                    --extended-regexp                                   \
                    --ignore-case                                       \
                    --line-number                                       \
                    --text                                              \
                    "${_search_args[@]:-}"                              \
                    -e "${_query:-}"                                    \
                  | LC_ALL=C sed -e "s/^/${_escaped_notebook_path}\//"  \
                    || return 0  # Don't fail out within a single scope.
                fi
              }
            done
          fi
        fi
      } | {
        local _binary_match_message_printed=0
        local _paginated_count=0
        local _pagination_max="$((_page * _limit))"
        local _pagination_min="$(((_page * _limit) - _limit))"

        local         __line=
        while read -r __line
        do
          local _content=
          local _content_line_with_hit=
          local _file_info=
          local _file_info_color=
          local _filename=
          local _filename_color=
          local _filename_hit=0
          local _id=
          local _line_path_segment="${__line%%:*}"
          local _path=
          local _skip=0

          if ((_print_paths))
          then
            _path="${_line_path_segment:-}"
          else
            # Use `sed` to remove color and 'matches' suffix from output.
            # https://unix.stackexchange.com/a/140255
            _path="$(
              printf "%s\\n" "${_line_path_segment}"              \
                | LC_ALL=C sed                                    \
                    -e "s,$(printf '\033')\\[[0-9;]*[a-zA-Z],,g"  \
                    -e 's/ matches//g'
            )"
          fi

          if ((_only_list))                       &&
             [[ "${_last_path}" == "${_path}" ]]  &&
             [[ ! "${_path}"    =~ .index$    ]]
          then
            [[ -n "${_path}" ]] && _last_path="${_path}"

            continue
          fi

          if [[ "${_path}"      =~ \.pindex$  ]]
          then
            [[ -n "${_path}" ]] && _last_path="${_path}"

            continue
          fi

          if [[ "${_last_path}" != "${_path}" ]]
          then
            if   [[ ! "${_path}" =~ .index    ]] &&
                 [[ -z "$(LC_ALL=C sed -E "${_IGNORE_PATTERNS[@]:-}" <<< "${_path##*/}")" ]]
            then
              _skip=1
            elif [[ -n "${_type:-}"           ]]
            then
              if [[  "${_path}" =~ ${_type}$  ]]
              then
                _skip=0
              elif {
                [[ "${_type}" =~ (^bookmark$|^bookmarks$)                   ]] &&
                  _file_is_bookmark "${_path}"
                } || {
                  [[ "${_type}" =~ (^todo$|^todos$|^task$|^tasks$)          ]] &&
                  _file_is_todo "${_path}"
                } || {
                  [[ "${_type}" =~ (^note$|^notes$)                         ]] &&
                  _file_is_text "${_path}"                                     &&
                  [[ ! "${_path:-}" =~ (.bookmark.md$|-bookmark.md$)        ]]
                } || {
                  [[ "${_type}" =~ (^folder$|^folders$)                     ]] &&
                  [[ "$(dirname "${_path}")" != "${__target_path}"          ]]
                } || {
                  [[ "${_type}" =~ ^archive$                                ]] &&
                  _file_is_archive "${_path}"
                } || {
                  [[ "${_type}" =~ (^audio$|^music$)                        ]] &&
                  _file_is_audio "${_path}"
                } || {
                  [[ "${_type}" =~ (^document$|^documents$|^doc$|^docs$)    ]] &&
                  _file_is_document "${_path}"
                } || {
                  [[ "${_type}" =~ ^encrypted$                              ]] &&
                  _file_is_encrypted "${_path}"
                } || {
                  [[ "${_type}" =~ (^image$|^images$|^picture$|^pictures$)  ]] &&
                  _file_is_image "${_path}"
                } || {
                  [[ "${_type}" =~ ^text$                                   ]] &&
                  _file_is_text "${_path}"
                } || {
                  [[ "${_type}" =~ (^video$|^videos$)                       ]] &&
                  _file_is_video "${_path}"
                }
              then
                _skip=0
              else
                _skip=1
              fi
            fi
          fi

          if [[ -z "${__line}" ]]
          then
            # Print nothing, skipping the blank line in `ag` output with
            # multiple matches.
            :
          elif ((_print_paths))
          then
            if [[ "${_last_path}" != "${_path}"   ]]
            then # match is in a different file than the last match
              printf "%s\\n" "${_path}"
            fi
          else
            if ((_skip))
            then
              continue
            fi

            local _folder_path="${_path%\/*}"

            if [[ ! -e "${_folder_path}/.index"   ]]
            then # skip unindexed folders
              continue
            fi

            if ((_limit)) &&
               {
                 [[ "${_last_path}" != "${_path}" ]] ||
                 [[ "${_path}"      =~ \.index$   ]]
               }
            then
              _paginated_count=$((_paginated_count+1))

              if [[ "${_paginated_count}"   -le "${_pagination_min}"  ]]
              then
                [[ -n "${_path}" ]] && _last_path="${_path}"

                continue
              elif [[ "${_paginated_count}" -gt "${_pagination_max}"  ]]
              then
                break
              fi
            fi

            if [[ -n "${_local_notebook_path:-}"                ]] &&
               [[ "${_folder_path}" =~ ${_local_notebook_path}  ]]
            then
              local _notebook_path="${_local_notebook_path}"
            else
              local _notebook_and_folder_path="${_folder_path#"${NB_DIR}"/}"
              local _notebook_path="${NB_DIR}/${_notebook_and_folder_path%%/*}"
            fi

            local _relative_folder_path="${_folder_path#"${_notebook_path}"/}"
            _relative_folder_path="${_relative_folder_path#"${_notebook_path}"}"

            _filename="$(basename "${_path}")"

            # normalize filenames with octal escape sequences from git grep
            _filename="$(printf "%b\\n" "${_filename}")"
            _filename="${_filename%\"}"
            _filename="${_filename#\"}"

            _filename_color="${_filename}"

            # Use ".index" to match filenames.
            if [[ -n "${_filename:-}" ]] && [[ "${_filename:-}" == ".index" ]]
            then
              _filename_hit=1
              _filename_color="$(printf "%s\\n" "${__line}" | cut -d: -f 3-)"
              _filename="$(
                printf "%s\\n" "${_filename_color}" \
                  | LC_ALL=C sed "s,$(printf '\033')\\[[0-9;]*[a-zA-Z],,g"
              )"
            fi

            local _maybe_id_path=
            local _relative_path="${_filename}"

            if [[ -n "${_relative_folder_path:-}" ]]
            then
              _max_id="$(_index get_max_id "${_folder_path}")"
              _maybe_id_path="${_relative_folder_path}/"
              _relative_path="${_relative_folder_path}/${_filename}"
            fi

            local _normalized_filename="${_filename:-}"

            if _command_exists "iconv"
            then
              _normalized_filename="$(
                printf "%s\\n" "${_filename:-}" | iconv -c -t utf-8
              )"
            fi

            _id="$(_index get_id "${_normalized_filename}" "${_folder_path}" || :)"

            if ((_filename_hit))
            then
              _content="$(_get_content "${_folder_path}/${_filename}")"

              if [[ -n "${_content}"                  ]] &&
                 [[ ! "${_content}" =~ ^__first_line: ]]
              then
                _file_info="${_filename} ${_MD} ${_content}"
                _file_info_color="${_filename_color} ${_MD} ${_content}"
              else
                _file_info="${_filename}"
                _file_info_color="${_filename_color}"
              fi
            else
              _content="$(_get_content "${_path}")"

              if [[ "${_content:-}" =~ ^__first_line: ]]
              then
                _file_info="${_filename} ${_MD} \"${_content#__first_line:}\""
                _file_info_color="${_filename_color} ${_MD} \"${_content#__first_line:}\""
              elif [[ -n "${_content:-}" ]]
              then
                _file_info="${_content}"
                _file_info_color="${_content}"
              else
                _file_info="${_filename}"
                _file_info_color="${_filename_color}"
              fi
            fi

            local _indicators=
            _indicators="$(
              NB_NOTEBOOK_PATH="${_notebook_path}" \
                _show "${_relative_path}" --indicators
            )"

            local _info_line=
            local _info_line_color=
            local _max_identifier=

            if ((_all))                       ||
               ((_print_notebook_selectors))  ||
               _notebooks current --selected
            then
              local _notebook_name=
              _notebook_name="$(
                _notebooks show "${_notebook_path}" --name --no-color
              )"

              _info_line="[${_notebook_name}:${_maybe_id_path}${_id}] "
              _info_line_color+="$(_color_brackets "${_notebook_name}:${_maybe_id_path}${_id}") "
              _max_identifier="[${_notebook_name}:${_maybe_id_path}${_max_id}] "
            else
              _info_line="[${_maybe_id_path}${_id}] "
              _info_line_color+="$(_color_brackets "${_maybe_id_path}${_id}") "
              _max_identifier="[${_maybe_id_path}${_max_id}] "
            fi

            # Use calculated number of spaces for nicer formatting.
            local _spaces=''
            local _spaces_length=0

            if ((_only_list))
            then
              _spaces_length=$(( ${#_max_identifier} - ${#_info_line} ))
            fi

            if ((_spaces_length))
            then
              printf -v _spaces '%*s' "${_spaces_length}" ""

              _info_line+="${_spaces}"
              _info_line_color+="${_spaces}"
            fi

            if [[ -n "${_indicators:-}" ]]
            then
              _info_line+="${_indicators}"
              _info_line_color+="${_indicators}"
            fi

            _info_line+="${_file_info}"
            _info_line_color+="${_file_info_color}"

            if [[ "${_last_path}" != "${_path}" ]] || ((_filename_hit))
            then # match is in a different file than the last match
              ((_COLOR_ENABLED)) && _wrap off

              printf "%s" "${_info_line_color}"

              ((_COLOR_ENABLED)) && _wrap on

              printf "\\n"

              _binary_match_message_printed=0
            fi

            if ((_only_list)) || ((_binary_match_message_printed))
            then
              [[ -n "${_path}" ]] && _last_path="${_path}"

              continue
            fi

            if [[ "${_last_path}" != "${_path}" ]] || ((_filename_hit))
            then # match is in a different file than the last match
              ((_COLOR_ENABLED)) && _wrap off

              local _visible_line_length=
              _visible_line_length="$(
                _get_visible_length "${_info_line:-}"
              )"

              _print_line "$(printf "%-${_visible_line_length}s" '.')"

              ((_COLOR_ENABLED)) && _wrap on
            fi

            if ((_filename_hit))
            then
              local _filename_type_label="Filename"

              if [[ -d "${_folder_path}/${_filename}" ]]
              then
                _filename_type_label="Folder Name"
              fi

              _content_line_with_hit="${_filename_type_label} Match: $(
                printf "%s\\n" "${__line}" | cut -d: -f 3-
              )"
            elif ! _file_is_text "${_folder_path}/${_filename}"
            then
              _content_line_with_hit="Binary file matches."
              _binary_match_message_printed=1
            else
              _content_line_with_hit="$(
                printf "%s\\n" "${__line}" | cut -d: -f 2-
              )"
            fi

            # Truncate long lines.
            local _line_length=
            _line_length="$(
              printf "%s\\n" "${_content_line_with_hit}" | awk '{print length}'
            )"

            local _line_length_diff=
            _line_length_diff=$((_line_length-_max_columns-100))

            if [[ "${_line_length_diff}" -gt 0      ]]
            then
              _content_line_with_hit="$(
                printf "%s\\n" "${_content_line_with_hit}" \
                  | awk '{ print substr($0, 1, 2000) }'
              )"

              _content_line_with_hit+="$(
                _color_primary "... [${_line_length_diff} characters omitted]"
              )"
            fi

            printf "%s\\n\\n" "${_content_line_with_hit}"
          fi

          [[ -n "${_path}" ]] && _last_path="${_path}"
        done
      }
    done
  } | {
    local       __search_output_line=
    if read -r  __search_output_line
    then # output is present
      # Print the test line then `cat` the rest.
      printf "%s\\n" "${__search_output_line:-}"

      cat

      return 0
    else
      if ((_all))
      then
        printf "Not found in any notebook: %s\\n"   \
          "$(_color_primary "${_query:-}")"
      else
        local _search_selector=

        if [[ -n "${_selectors[0]:-}"               ]]
        then
          _search_selector="${_selectors[0]}"

          if [[ -f "${_target_paths[0]:-}"          ]] &&
             [[ "${_search_selector:-}" =~ /$       ]]
          then # strip trailing slash from files
            _search_selector="${_search_selector%/}"
          elif [[ "${_search_selector:-}" =~ :$     ]]
          then
            _search_selector="${_search_selector%:}"
          elif [[ -d "${_target_paths[0]:-}"        ]] &&
               [[ !  "${_search_selector:-}" =~ /$  ]]
          then # add trailing slash to folders
            _search_selector="${_search_selector}/"
          fi
        else
          _search_selector="$(_notebooks current --name)"
        fi

        local _query_message=

        if [[ "${#_queries[@]}" -le 1 ]]
        then
          _query_message="${_query}"
        else
          local i=
          for ((i=0; i < ${#_queries[@]}; i++))
          do
            if ((i))
            then
              _query_message+=" + ${_queries[i]:-}"
            else
              _query_message="${_queries[i]:-}"
            fi
          done
        fi

        if [[ "${_page:-0}" -gt 1     ]]
        then
          return 0
        else
          _warn printf "Not found in %s: %s\\n"               \
                  "$(_color_primary "${_search_selector:-}")" \
                  "$(_color_primary "${_query_message:-}")"
        fi
      fi

      return 1
    fi
  }
}
_alias_subcommand "search" "q"
_alias_subcommand "search" "grep"

# show ################################################################### show

_describe_show() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} show ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
          [[-a | --added] | [--authors] | [-b | --browse] | --filename | --id |
          --info-line | --path | [-p | --print] | --relative-path | [-r |
          --render] | --title | --type [<type>] | [-u | --updated]] [--no-color]
  ${_ME} show <notebook>

$(_color_primary "Options"):
  -a, --added      Print the date and time when the item was added.
  --authors        List the git commit authors of an item.
  -b, --browse     Open the item with \`${_ME} browse\`.
  --filename       Print the filename of the item.
  --id             Print the id number of the item.
  --info-line      Print the id, filename, and title of the item.
  --no-color       Show without syntax highlighting.
  --path           Print the full path of the item.
  -p, --print      Print to standard output / terminal.
  --relative-path  Print the item's path relative within the notebook.
  -r, --render     Use \`pandoc\` [1] to render the file to HTML and display
                   in the terminal web browser. If either \`pandoc\` or a
                   browser are unavailable, \`-r\` / \`--render\` is ignored.
  --title          Print the title of the note.
  --type [<type>]  Print the file extension or, when <type> is specified,
                   return true if the item matches <type>. <type> can be a
                   file extension or one of the following types:
                   archive, audio, bookmark, document, folder, image,
                   text, video
  -u, --updated    Print the date and time of the last recorded change.

$(_color_primary "Description"):
  Show an item or notebook. Notes in text file formats can be rendered or
  printed to standard output. Non-text files are opened in your system's
  preferred app or program for that file type.

  By default, the item is opened using \`less\` or the program configured
  in the \`\$PAGER\` environment variable. Use the following keys to navigate
  in \`less\` (see \`man less\` for more information):

    Key               Function
    ---               --------
    mouse scroll      Scroll up or down
    arrow up or down  Scroll one line up or down
    f                 Jump forward one window
    b                 Jump back one window
    d                 Jump down one half window
    u                 Jump up one half window
    /<query>          Search for <query>
    n                 Jump to next <query> match
    q                 Quit

  To skip the pager and print to standard output, use the \`-p\` / \`--print\`
  option.

  \`-r\` / \`--render\` automatically uses either \`w3m\` [2] or \`links\` [3].
  To specify a preferred browser, set the \`\$BROWSER\` environment variable
  in your .bashrc, .zshrc, or equivalent, e.g.: export BROWSER="links"

  If \`bat\` [5], \`highlight\` [6], or Pygments [7] is installed, notes are
  printed with syntax highlighting.

    1. https://pandoc.org/
    2. https://en.wikipedia.org/wiki/W3m
    3. https://en.wikipedia.org/wiki/Links_(web_browser)
    5. https://github.com/sharkdp/bat
    6. http://www.andre-simon.de/doku/highlight/en/highlight.php
    7. https://pygments.org/

$(_color_primary "Read More"):
  ${_README_URL}#viewing

$(_color_primary "See Also"):
  ${_ME} help browse
  ${_ME} help open
  ${_ME} help peek

$(_color_primary "Examples"):
  ${_ME} show 1
  ${_ME} show example.md --render
  ${_ME} show "A Document Title" --print --no-color
  ${_ME} 1 show
  ${_ME} example:show 12
  ${_ME} show example:12
  ${_ME} example:12 show
  ${_ME} s 1
  ${_ME} 1 s
  ${_ME} s example:12
  ${_ME} example:12 s

$(_color_primary "Alias"):
  ${_ME} view

$(_color_primary "Shortcut Alias"):
  ${_ME} s
HEREDOC
}
_show() {
  # _show_indicators()
  #
  # Usage:
  #   _show_indicators <path> [--done]
  #
  # Description:
  #   Print a list of indicators based on the file type.
  #
  # NOTE: Indicator logic is also specified in `list` for performance.
  _show_indicators() {
    local _done=0
    local _indicators=
    local _path="${1:-}"

    case "${2:-}" in
      --done) _done=1 ;;
    esac

    local _pindex_path="${_path%/*}/.pindex"

    if [[ -e "${_pindex_path}"  ]]
    then
      # shellcheck disable=SC2046
      if _contains "${_path##*/}" $(cat "${_pindex_path}")
      then
        _indicators+="${_NB_INDICATOR_PINNED:-}"
      fi
    fi

    if [[ -d "${_path}"         ]]
    then
      _indicators+="${_NB_INDICATOR_FOLDER:-}"
    elif _file_is_bookmark "${_path}"
    then
      _indicators+="${_NB_INDICATOR_BOOKMARK:-}"
    elif _file_is_image "${_path}"
    then
      _indicators+="${_NB_INDICATOR_IMAGE:-}"
    elif _file_is_document "${_path}"
    then
      _indicators+="${_NB_INDICATOR_DOCUMENT:-}"
    elif _file_is_video "${_path}"
    then
      _indicators+="${_NB_INDICATOR_VIDEO:-}"
    elif _file_is_audio "${_path}"
    then
      _indicators+="${_NB_INDICATOR_AUDIO:-}"
    elif [[ "${_path}" =~ \.epub$ ]]
    then
      _indicators+="${_NB_INDICATOR_EBOOK:-}"
    fi

    if _file_is_encrypted "${_path}"
    then
      _indicators+="${_NB_INDICATOR_ENCRYPTED:-}"
    fi

    if _file_is_todo "${_path}"
    then
      if ((_done))
      then
        _indicators+="${_NB_INDICATOR_TODO_DONE% } "
      else
        _indicators+="${_NB_INDICATOR_TODO% } "
      fi
    fi

    printf "%s\\n" "${_indicators:-}"
  }

  local _browse=0
  local _browse_gui=0
  local _check_type=0
  local _limit="${NB_BROWSE_LIMIT:-20}"
  local _list_page=1
  local _password=
  local _print_added=0
  local _print_authors=0
  local _print_bookmark_url=0
  local _print_filename=0
  local _print_folder_path=0
  local _print_id=0
  local _print_indicators=0
  local _print_info=0
  local _print_output=0
  local _print_path=0
  local _print_relative_path=0
  local _print_selector_id=0
  local _print_title=0
  local _print_updated=0
  local _render=0
  local _selector=
  local _skip_notebook_fallback=0
  local _tool=
  local _type=
  local _unresolved_arguments=()

  while ((${#}))
  do
    case "${1:-}" in
      -a|--added*|--created*)
        _print_added=1
        _skip_notebook_fallback=1
        ;;
      --auth*)
        _print_authors=1
        ;;
      -b|--br|--browse)
        _browse=1
        ;;
      --filename|--basename)
        _print_filename=1
        _skip_notebook_fallback=1
        ;;
      --folder-path)
        _print_folder_path=1
        ;;
      -g|--gui)
        _browse_gui=1
        ;;
      --id|--index)
        _print_id=1
        _skip_notebook_fallback=1
        ;;
      --indicators)
        _print_indicators=1
        _skip_notebook_fallback=1
        ;;
      --info*line)
        _print_info=1
        _skip_notebook_fallback=1
        ;;
      --limit|-n|--num|--number|--per*)
        _limit="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      --no*color|--raw)
        _COLOR_ENABLED=0
        ;;
      --notebook*|--include*notebook*|--with*notebook*)
        _skip_notebook_fallback=0
        ;;
      --page)
        _list_page="$(_option_get_value "${1}" "${2:-}")"
        ((_list_page)) || _list_page=1

        shift
        ;;
      --password)
        _password="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      --path)
        _print_path=1
        _skip_notebook_fallback=1
        ;;
      -p|--print|--dump|--skip*pager|--no*pager)
        _print_output=1
        ;;
      --relative-path)
        _print_relative_path=1
        _skip_notebook_fallback=1
        ;;
      -r|--render)
        _render=1
        ;;
      --selector*id)
        _print_selector_id=1
        _skip_notebook_fallback=1
        ;;
      --title)
        _print_title=1
        _skip_notebook_fallback=1
        ;;
      --tool|--utility)
        _tool="$(_option_get_value "${1}" "${2:-}")"

        shift
        ;;
      --type)
        _check_type=1
        _skip_notebook_fallback=1

        if _option_value_is_present "${2:-}"
        then
          _type="${2}"

          shift
        fi
        ;;
      -u|--updated*)
        _print_updated=1
        _skip_notebook_fallback=1
        ;;
      --url)
        _print_bookmark_url=1
        ;;
      *)
        if [[ -z "${_selector:-}" ]]
        then
          _selector="${1}"
        else
          _unresolved_arguments+=("${1}")
        fi
        ;;
    esac

    shift
  done

  if [[ -z "${_selector:-}" ]]
  then
    _exit_1 _help "show"
  fi

  if ((_print_selector_id))
  then
    _selector_get_identifier "${_selector:-}"

    return 0
  fi

  local _notebook_path=

  if [[ "${_selector:-}" =~ : ]] && [[ ! "${_selector:-}" =~ /.*: ]]
  then
    _notebook_path="$(_notebooks show "${_selector%%:*}" --path)" || return 1

    if ((_print_path)) && [[ "${_selector:-}" =~ :$ ]]
    then
      printf "%s\\n" "${_notebook_path}"

      return 0
    fi
  elif [[ "${_selector:-}" =~ ^${NB_DIR}  ]]
  then
    local _selector_relative_path="${_selector#"${NB_DIR}"/}"

    _notebook_path="$(_notebooks show "${_selector_relative_path%%/*}" --path)"
  elif [[ "${_selector:-}" =~ ^/          ]]
  then
    _notebook_path="$(_notebooks show "${_selector}" --path)"
  fi

  if [[ -z "${_notebook_path:-}"          ]]
  then
    _notebook_path="$(_notebooks current --path)"
  fi

  local _relative_path=
  _relative_path="$(
    _selector_resolve_path "${_selector}" "${_notebook_path}" --relative
  )"

  local _folder_path="${_notebook_path:?}"
  local _relative_folder_path=

  if [[ "${_relative_path:-}" =~ /        ]]
  then
    _folder_path="${_notebook_path}/${_relative_path%\/*}"
    _relative_folder_path="${_relative_path%\/*}"
  fi

  local _basename=
  _basename="$(basename "${_relative_path}")"

  local _target_path="${_notebook_path}/${_relative_path}"

  if [[ -z "${_relative_path:-}"    ]] && ! ((_skip_notebook_fallback))
  then
    local _maybe_notebook="${_selector:-}"

    if [[ "${_maybe_notebook:-}" =~ ^${NB_DIR}    ]]
    then
      _maybe_notebook="${_maybe_notebook##*\/}"
    fi

    _maybe_notebook="${_maybe_notebook%:}"

    if [[ -d "${NB_DIR}/${_maybe_notebook}/.git"  ]]
    then
      if ((_print_path))
      then
        printf "%s\\n" "${NB_DIR}/${_maybe_notebook}"
      elif ((_print_relative_path)) || ((_print_folder_path))
      then
        printf ""
      else
        NB_NOTEBOOK_PATH="${NB_DIR}/${_maybe_notebook}" \
          _ls "${_unresolved_arguments[@]:-}"
      fi

      return 0
    else
      _warn printf "Not found: %s\\n" "$(_color_primary "${_selector}")"

      return 1
    fi
  fi

  if [[ ! "${_selector}" =~ :$      ]] && {
       [[ -z "${_relative_path:-}"  ]] ||
       [[ ! -e "${_target_path}"    ]]
     }
  then
    _warn printf "Not found: %s\\n" "$(_color_primary "${_selector:-}")"

    return 1
  fi

  if ((_print_folder_path))
  then
    if [[ "${_selector:-}" =~ /$                      ]] &&
       [[ -d "${_notebook_path}/${_relative_path:-}"  ]]
    then
      printf "%s\\n" "${_relative_path}"
    elif [[ "${_relative_path:-}" =~ / ]]
    then
      printf "%s\\n" "${_relative_path%\/*}"
    else
      printf ""
    fi

    return 0
  fi

  if ((_print_relative_path))
  then
    printf "%s\\n" "${_relative_path}"

    return 0
  fi

  if ((_print_path))
  then # `show --path`
    printf "%s/%s\\n" "${_notebook_path}" "${_relative_path}"

    return 0
  fi

  if ((_print_filename))
  then
    printf "%s\\n" "${_basename}"

    return 0
  fi

  if ((_print_id))
  then
    printf "%s\\n" "$(
      _index get_id "${_relative_path##*/}" "${_folder_path}"
    )"

    return 0
  fi

  if ((_print_title))
  then
    _get_content "${_notebook_path}/${_relative_path}" --title

    return 0
  fi

  if ((_print_authors))
  then
    GIT_PAGER='' git -C "${_notebook_path}" shortlog              \
      --summary --email -- "${_notebook_path}/${_relative_path}"  \
      | LC_ALL=C sed "s/^[[:space:]]\{1,\}[[:digit:]]\{1,\}[[:space:]]\{1,\}//g"

    return 0
  fi

  if ((_print_indicators))
  then
    local _indicator_arguments=("${_notebook_path}/${_relative_path}")

    if [[ "${_relative_path:-}" =~ todo\.md ]]
    then
      local _todo_title=
      _todo_title="$(
        _get_content "${_notebook_path}/${_relative_path}" --title
      )"

      if [[ "${_todo_title}" =~ ^\[x\]      ]]
      then
        _indicator_arguments+=(--done)
      fi
    fi

    _show_indicators "${_indicator_arguments[@]:-}"

    return 0
  fi

  if ((_check_type))
  then
    if [[ -z "${_type}"       ]]
    then
      if [[ -d "${_notebook_path}/${_relative_path}"  ]]
      then
        printf "%s\\n" "folder"
      else
        printf "%s\\n" "${_relative_path#*.}"
      fi

      return 0
    else
      if _contains "${_type}" "${_FILE_TYPES[@]:-}"
      then
        "_file_is_${_type}" "${_notebook_path}/${_relative_path}"

        return $?
      else
        [[ "${_type}" == "${_relative_path#*.}"       ]]

        return $?
      fi
    fi
  fi

  if ((_print_info))
  then
    local _id=

    if [[ -n "${_basename:-}" ]]
    then
      _id="$(_index get_id "${_basename}" "${_folder_path}")"
    fi

    local _maybe_scoped_relative_path="${_relative_path}"

    local _maybe_scoped_id=
    _maybe_scoped_id="${_relative_folder_path:+"${_relative_folder_path}/"}${_id}"

    if _notebooks current --selected ||
       [[ "${_notebook_path}" != "$(_notebooks current --path)" ]]
    then
      local _notebook_name=
      _notebook_name="$(
        _notebooks show "${_notebook_path}" --name --no-color
      )"

      _maybe_scoped_id="${_notebook_name}:${_maybe_scoped_id}"
      _maybe_scoped_relative_path="${_notebook_name}:${_maybe_scoped_relative_path}"
    fi

    local _info_line=
    _info_line+="$(_color_brackets "${_maybe_scoped_id}") "

    local _indicators=
    _indicators="$(_show "${_notebook_path}/${_relative_path}" --indicators)"

    if [[ -n "${_indicators:-}" ]]
    then
      _info_line+="${_indicators}"
    fi

    _info_line+="$(_color_primary "${_maybe_scoped_relative_path}") "

    local _title=
    _title="$(_get_content "${_notebook_path}/${_relative_path}" --title)"

    if [[ -n "${_title:-}"      ]]
    then
      if [[ "${_relative_path}"  =~ todo\.md$ ]] && ((_COLOR_ENABLED))
      then
        _title="\
${_title/\[x\]/${_TPUT_SETAF_8}[${_TPUT_COLOR_PRIMARY}x${_TPUT_SETAF_8}]${_TPUT_SGR0}}"
        _title="\
${_title/\[$' '\]/${_TPUT_SETAF_8}[ ]${_TPUT_SGR0}}"
      fi

      _info_line+="\"${_title}\""
    fi

    # trim leading and trailing whitepace
    IFS=' ' read -r _info_line <<<"${_info_line:-}"

    printf "%s\\n" "${_info_line:-}"

    return 0
  fi

  if ((_print_added))
  then
    git -C "${_notebook_path}" --no-pager \
      log                                 \
      --follow                            \
      --diff-filter=A                     \
      --date=iso-local                    \
      --pretty='%ad'                      \
      "${_relative_path}"

    return 0
  fi

  if ((_print_updated))
  then
    git -C "${_notebook_path}" --no-pager \
      log                                 \
      -1                                  \
      --follow                            \
      --date=iso-local                    \
      --pretty='%ad'                      \
      "${_relative_path}"

    return 0
  fi

  if _file_is_encrypted "${_target_path}"
  then
    local _encrypted_path=
    _encrypted_path="${_target_path}"

    local _decryption_tool=
    _decryption_tool="$(_get_decryption_tool "${_encrypted_path:-}")"

    if [[    "${_decryption_tool:-}" != "age" ]] &&
       [[ -z "${_password}"                   ]]
    then
      # request password without displaying it
      printf "%s: " "$(_color_primary "Password")"

      local _password=
      IFS='' read -r -e -d $'\n' -s _password </dev/tty

      if [[ -z "${_password}"                 ]]
      then
        _exit_1 printf "Password required.\\n"
      fi
    fi

    local _decrypted_path=
    _decrypted_path="$(_decrypt_file "${_target_path}" "${_password}")"

    _target_path="${_decrypted_path}"
  fi

  if ((_print_bookmark_url))
  then
    if ! _file_is_bookmark "${_target_path:-}"
    then
      _warn printf "%s\\n" "Not a bookmark.\\n"
    fi

    local _url_match_patterns=()

    local __url_match_pattern=
    for   __url_match_pattern in "${_URL_PATTERNS[@]}"
    do
      _url_match_patterns+=(-e "<${__url_match_pattern}>")
    done

    local _target_url=
    _target_url="$(
      grep -E                                 \
        "${_url_match_patterns[@]:-}"         \
        "${_target_path}"                     \
        | head -n 1                           \
        | LC_ALL=C sed "s/^[[:space:]]*<//g"  \
        | LC_ALL=C sed "s/>[[:space:]]*$//g"  || :
    )"

    if [[ -z "${_target_url:-}"       ]]
    then
      _warn printf "No URL found.\\n"

      return 1
    fi

    printf "%s\\n" "${_target_url:-}"

    return 0
  fi

  if _file_is_archive "${_target_path}"     &&
     [[ ! "${_target_path}" =~ docx$  ]]
  then
    _exit_1 printf "\
Can't show archives. Export archive and expand to edit.\\n"
  fi

  # change directory to folder path to enable relative paths
  cd "${_folder_path}"

  # turn on case-insensitive matching
  shopt -s nocasematch

  if [[ -z "${_tool:-}" ]]                  &&
     _file_is_image "${_target_path:-}"     &&
     _contains      "${NB_IMAGE_TOOL:-}"    \
        "catimg"                            \
        "chafa"                             \
        "icat"                              \
        "imgcat"                            \
        "magick"                            \
        "termvisage"                        \
        "timg"                              \
        "viu"
  then
    _tool="${NB_IMAGE_TOOL:-}"
  fi

  if  _contains "${_target_path##*.}"        \
        "csv" "json" "mysql" "postgres"      \
        "sqlite" "tab" "tar" "tsv" "usv" "vds" "xml" "xlsx" "zip"     &&
      _command_exists "vd"                                            &&
      {
        _contains "${_tool:-${NB_DATA_TOOL:-vd}}" "vd" "visidata"     ||
        [[  "${_tool:-${NB_DATA_TOOL:-vd}}" =~ visidata|vd ]]
      }
  then
    local _visidata_command=
    IFS=' ' read -ra _visidata_command <<< "${_tool:-${NB_DATA_TOOL:-vd}}"

    "${_visidata_command[@]:-}" "${_target_path}"
  elif  _contains "${_target_path##*.}" "csv" "sc" "tab" "tsv" "xlsx" &&
        _command_exists "sc-im"                                       &&
        [[  "${_tool:-${NB_DATA_TOOL:-sc-im}}" =~ sc-im ]]
  then
    local _sc_im_command=
    IFS=' ' read -ra _sc_im_command <<< "${_tool:-${NB_DATA_TOOL:-sc-im}}"

    "${_sc_im_command[@]:-}" "${_target_path}"
  elif  _contains "${_target_path##*.}" "csv" "psv" "tsv"             &&
        _command_exists "tidy-viewer"                                 &&
        {
          _contains "${_tool:-${NB_DATA_TOOL:-tidy-viewer}}" "tv" "tidy-viewer" "tidyviewer" ||
          [[  "${_tool:-${NB_DATA_TOOL:-tidy-viewer}}" =~ tidy-*viewer|tv ]]
        }
  then
    local _tidy_viewer_command=
    IFS=' ' read -ra _tidy_viewer_command <<< "${_tool:-${NB_DATA_TOOL:-tidy-viewer}}"

    "${_tidy_viewer_command[@]:-}" "${_target_path}"
  elif ! _file_is_text "${_target_path}"    &&
     ! {
       ((_render))                          &&
       [[       "${_target_path:-}" =~ (\.docx$|\.epub$|\.odt$) ]]
     } || [[ -d "${_target_path:-}"                             ]]
  then
    if [[ -d "${_target_path}"  ]]
    then
      if [[ -z "${_tool:-}"     ]]          &&
        _contains "${NB_DIRECTORY_TOOL:-}"  \
          "joshuto"                         \
          "lsd"                             \
          "mc"                              \
          "exa"                             \
          "eza"                             \
          "ranger"                          \
          "vifm"                            &&
        _command_exists "${NB_DIRECTORY_TOOL:-}"
      then
        _tool="${NB_DIRECTORY_TOOL}"
      fi

      if [[ -n "${NB_BROWSE_SERVER_TOOL:-}" ]]  &&
         _command_exists "pandoc"               &&
         _web_browser --check                   &&
         [[ -z "${_tool:-}"     ]]
      then
        cd "${_CURRENT_WORKING_DIR}"

        _defer "_browse" "${_target_path}/"

        return 0
      elif _command_exists "ranger"   && [[ "${_tool:-ranger}"  == "ranger"   ]]
      then
        ranger "${_target_path}"
      elif _command_exists "mc"       && [[ "${_tool:-mc}"      == "mc"       ]]
      then
        mc "${_target_path}"
      elif _command_exists "vifm"     && [[ "${_tool:-vifm}"    == "vifm"     ]]
      then
        vifm "${_target_path}"
      elif _command_exists "joshuto"  && [[ "${_tool:-joshuto}" == "joshuto"  ]]
      then
        local _joshuto_version=
        _joshuto_version="$(joshuto --version)"
        _joshuto_version="${_joshuto_version#*-}"

        local _joshuto_major_minor="${_joshuto_version%.*}"

        if  [[  "${_joshuto_major_minor%.*}"  -le "0" ]] &&
            [[  "${_joshuto_major_minor#*.}"  -le "9" ]] &&
            [[  "${_joshuto_version##*.}"     -lt "5" ]]
        then
          joshuto --path "${_target_path}"
        else
          joshuto "${_target_path}"
        fi
      elif _command_exists "lsd"      && [[ "${_tool:-lsd}"     == "lsd"      ]]
      then
        lsd                                       \
          -1Al                                    \
          --blocks=permission,size,date,git,name  \
          --color=always                          \
          --date '+%F %R'                         \
          --git                                   \
          --icon=always                           \
          --icon-theme=fancy                      \
          --ignore-config                         \
          --group-directories-first               \
          --size=short                            \
          "${_target_path}"
      elif _command_exists "eza"      && [[ "${_tool:-eza}"     == "eza"      ]]
      then
        eza                         \
          -1labm                    \
          --icons                   \
          --color=always            \
          --color-scale             \
          --git                     \
          --git-ignore              \
          --group-directories-first \
          --no-user                 \
          --sort=name               \
          --time-style=long-iso     \
          "${_target_path}"
      elif _command_exists "exa"      && [[ "${_tool:-exa}"     == "exa"      ]]
      then
        # TODO: remove in favor of eza
        exa -lah --git "${_target_path}"
      else
        # gnu || bsd
        ls -lah --color=always "${_target_path}" 2>/dev/null  ||
          ls -lah -G "${_target_path}"
      fi
    elif _command_exists "termvisage"     &&
         _file_is_image "${_target_path}" &&
         [[   "${_tool:-termvisage}"  == "termvisage" ]]
    then
      local _render_style="auto"

      if    [[ -n "${VIMRUNTIME:-}"                   ]] ||
            [[ -n "${MYVIMRC:-}"                      ]]
      then
        _render_style="block"
      elif  [[    "${TERM_PROGRAM:-}" == "iTerm.app"  ]]
      then
        _render_style="iterm2"
      elif  [[ -n "${KITTY_WINDOW_ID:-}"              ]]
      then
        _render_style="kitty"
      fi

      termvisage "${_target_path}"  \
        --cli                       \
        --force-style               \
        --quiet                     \
        --style "${_render_style}"  |   {
        if _command_exists "less"   &&  ! ((_print_output))
        then
          less -r --prompt="$(_less_prompt)"
        else
          cat
        fi
      }
    elif _command_exists "imgcat"                     &&
         _file_is_image "${_target_path}"             &&
         [[ ! "${_target_path}"   =~ \.afphoto$   ]]  &&
         [[ ! "${_target_path}"   =~ \.svg$       ]]  &&
         [[   "${TERM_PROGRAM:-}" == "iTerm.app"  ]]  &&
         [[   "${_tool:-imgcat}"  == "imgcat"     ]]
    then
      imgcat "${_target_path}"    |   {
        if _command_exists "less" &&  ! ((_print_output))
        then
          less -r --prompt="$(_less_prompt)"
        else
          cat
        fi
      }
    elif _command_exists "chafa"                      &&
         _file_is_image "${_target_path}"             &&
         [[ ! "${_target_path}"   =~ \.afphoto$   ]]  &&
         [[ ! "${_target_path}"   =~ \.svg$       ]]  &&
         [[   "${_tool:-chafa}"   == "chafa"      ]]
    then
      chafa "${_target_path}"     |   {
        if _command_exists "less" &&  ! ((_print_output))
        then
          less -r --prompt="$(_less_prompt)"
        else
          cat
        fi
      }
    elif _command_exists "timg"                       &&
         _file_is_image "${_target_path}"             &&
         [[ ! "${_target_path}"   =~ \.afphoto$   ]]  &&
         [[ ! "${_target_path}"   =~ \.svg$       ]]  &&
         [[   "${_tool:-timg}"    == "timg"       ]]
    then
      timg "${_target_path}"      |   {
        if _command_exists "less" &&  ! ((_print_output))
        then
          less -r --prompt="$(_less_prompt)"
        else
          cat
        fi
      }
    elif _command_exists "viu"                        &&
         _file_is_image "${_target_path}"             &&
         [[   "${_tool:-viu}"  == "viu"           ]]
    then
      viu "${_target_path}"
    elif _command_exists "catimg"                     &&
         _file_is_image "${_target_path}"             &&
         [[   "${_tool:-catimg}"  == "catimg"     ]]
    then
      catimg "${_target_path}"
    elif _command_exists "magick"                     &&
         _file_is_image "${_target_path}"             &&
         [[ ! "${_target_path}"   =~ afphoto$     ]]  &&
         {
           # Detect sixel support. Via: https://git.io/JfCel
           local __reply=
           IFS=";" read -ra __reply -s -t 1 -d "c" -p $'\e[c' >&2

           [[ "${__reply[*]}"     =~ 4            ]]  ||
           [[ "$TERM"             == yaft*        ]]
         } && {
           [[ "${_tool:-magick}"  == "magick"     ]]
         }
    then
      magick "${_target_path}" sixel:-  | {
        if _command_exists "less" &&    ! ((_print_output))
        then
          less -r --prompt="$(_less_prompt)"
        else
          cat
        fi
      }
    elif [[ -n  "${KITTY_WINDOW_ID:-}"            ]]  &&
         _file_is_image "${_target_path}"             &&
         [[     "${_tool:-icat}"  == "icat"       ]]
    then
      kitty +kitten icat "${_target_path}"  | {
        if _command_exists "less" &&  ! ((_print_output))
        then
          less -r --prompt="$(_less_prompt)"
        else
          cat
        fi
      }
    elif ((${NB_VIDEO_TO_ASCII_ENABLED:-0}))          &&
         _command_exists "video-to-ascii"             &&
         _file_is_video "${_target_path:-}"           &&
         [[ "${_tool:-"video-to-ascii"}" == "video-to-ascii"        ]]
    then # https://github.com/joelibaceta/video-to-ascii
      video-to-ascii -f "${_target_path:-}"
    elif _command_exists "mplayer"                    &&
         _file_is_audio "${_target_path}"             &&
         [[ "${_tool:-${NB_AUDIO_TOOL:-mplayer}}"   == "mplayer"    ]]
    then
      printf "Playing audio. Press %s to quit.\\n" "$(_color_primary "Ctrl-C")"
      mplayer "${_target_path}"
    elif _command_exists "afplay"                     &&
         _file_is_audio "${_target_path}"             &&
         [[ "${_tool:-${NB_AUDIO_TOOL:-afplay}}"      == "afplay"   ]]
    then
      printf "Playing audio. Press %s to quit.\\n" "$(_color_primary "Ctrl-C")"
      afplay "${_target_path}"
    elif _command_exists "mpg123"                     &&
         _file_is_audio "${_target_path}"             &&
         [[ "${_tool:-afplay}"    == "afplay"     ]]  &&
         [[ "${_target_path}"     =~ mp[(1|2|3)]$ ]]  &&
         [[ "${_tool:-${NB_AUDIO_TOOL:-mpg123}}"      == "mpg123"   ]]
    then
      printf "Playing audio. Press %s to quit.\\n" "$(_color_primary "Ctrl-C")"
      mpg123 "${_target_path}"
    elif _command_exists "ffplay"                     &&
         _file_is_audio "${_target_path}"             &&
         [[ "${_tool:-${NB_AUDIO_TOOL:-ffplay}}"      == "ffplay"   ]]
    then
      printf "Playing audio. Press %s to quit.\\n" "$(_color_primary "Ctrl-C")"
      ffplay -loglevel quiet "${_target_path}"
    elif _command_exists "termpdf.py"                 &&
         [[     "${_target_path}" =~ pdf$         ]]  &&
         [[ -n  "${KITTY_WINDOW_ID:-}"            ]]  &&
         _contains "${_tool:-termpdf.py}" "termpdf.py" "termpdf"
    then
      termpdf.py "${_target_path}"
    elif _command_exists "pdftotext"                  &&
         [[     "${_target_path}" =~ pdf$         ]]  &&
         [[ "${_tool:-pdftotext}" == "pdftotext"  ]]
    then
      pdftotext "${_target_path}" - | tr -d '\014'  | {
        if ! ((_print_output))
        then
          _pager
        else
          cat
        fi
      }
    elif [[ "${_target_path}" =~ docx$  ]]  &&
         _command_exists "pandoc"
    then
      pandoc                                \
        --from  docx                        \
        --to    markdown                    \
        "${_target_path}"                   \
        | LC_ALL=C sed -E                   \
          -e 's/\\\[\\\[/\[\[/g'            \
          -e 's/\\\]\\\]/\]\]/g'            \
          | _highlight_syntax_if_available  \
          | if ! ((_print_output))
            then
              _pager
            else
              cat
            fi
    elif [[ "${_target_path}" =~ epub$  ]]  &&
         _command_exists "pandoc"           &&
         _web_browser --check
    then
      pandoc          \
        --from  epub  \
        --to    html  \
        "${_target_path}" | _web_browser
    elif _open_in_gui_app "${_target_path:-}"
    then
      return 0
    else
      _exit_1 printf                                \
        "%s doesn't know how to show this item.\\n" \
        "$(_color_primary "${_ME}")"
    fi
  else # file is text
    if ((_browse))                              &&
         [[ -n "${NB_BROWSE_SERVER_TOOL:-}" ]]  &&
         _command_exists "pandoc"               &&
         _web_browser --check
    then
      cd "${_CURRENT_WORKING_DIR}"

      local _browse_arguments=("${_target_path}")
      ((_print_output)) && _browse_arguments+=("--print")
      ((_browse_gui))   && _browse_arguments+=("--gui")

      _defer "_browse" "${_browse_arguments[@]:-}"

      return 0
    elif ((_render))                &&
         _command_exists "pandoc"   &&
         _web_browser --check
    then
      local _rendered_temp_file_path=
      _rendered_temp_file_path="$(_temp file ".html" --touch)"

      if [[ "${_target_path:-}" =~ (\.asciidoc$|\.adoc$)    ]]  &&
         _file_is_text "${_target_path:-}"                      &&
         _command_exists "asciidoctor"
      then
        {
          asciidoctor           \
            -o -                \
            --no-header-footer  \
            "${_target_path:-}"
        } | {
          _resolve_links "${_notebook_path}"
        } | {
          _render
        } | {
          cat >> "${_rendered_temp_file_path}"
        }
      elif [[ "${_target_path}" =~ \.org                    ]]
      then # resolve Org [[wiki-style links]] before rendering to HTML
        {
          cat "${_target_path}"
        } | {
          _resolve_links "${_notebook_path}" --type org
        } | {
          # avoid pandoc bug with brackets in Org link descriptions
          LC_ALL=C sed -E                                   \
            -e "s/\]\[\[\[/\]\[${_ME}-placeholder-${_ME}/g" \
            -e "s/\]\]\]\]/${_ME}-placeholder-${_ME}\]\]/g"
        } | {
          _pandoc --standard-input --from org --to html
        } | {
          LC_ALL=C sed -E                                   \
            -e "s/>${_ME}-placeholder-${_ME}/>\[\[/g"       \
            -e "s/${_ME}-placeholder-${_ME}</\]\]</g"
        } | {
          _render
        } | {
          cat >> "${_rendered_temp_file_path}"
        }
      else
        {
          _render "${_target_path}" --pandoc --body
        } | {
          if [[ "${_target_path}" =~ \.bookmark\.md ]]
          then
            _resolve_links "${_notebook_path}" --bookmark
          else
            _resolve_links "${_notebook_path}"
          fi
        } | {
          _render
        } | {
          cat >> "${_rendered_temp_file_path}"
        }
      fi

      if ((_print_output))
      then
        if ((_COLOR_ENABLED))
        then
          cat "${_rendered_temp_file_path}" | _web_browser --dump
        else
          cat "${_rendered_temp_file_path}"
        fi
      elif _web_browser --gui
      then
        (_web_browser "file://${_rendered_temp_file_path:-}") &

        printf "Serving: %s\\n" "$(_color_primary "${_rendered_temp_file_path}")"

        while true
        do
          read -n 1 -s -r -p "Press any key to quit$(_color_muted "...")"

          printf "\\n"

          exit 0
        done
      else
        _web_browser "file://${_rendered_temp_file_path:-}"
      fi

      rm -f "${_rendered_temp_file_path:?}"
    else # default
      if ((_print_output))
      then # `show --print [--no-color]`
        if ((_COLOR_ENABLED))
        then # `show --print`
          _highlight_syntax_if_available "${_target_path}"
        else # `show --print --no-color`
          cat "${_target_path}"
        fi
      else # `show`
        local _target_extension=
        local _target_filename="${_target_path##*/}"

        if [[ "${_target_filename:-}" =~ \. ]]
        then
          _target_extension="${_target_filename##*.}"
        fi

        {
          cat "${_target_path}"
        } | {
          local _markdown_tool="${_tool:-${NB_MARKDOWN_TOOL:-}}"

          if _contains "${_target_extension:-}" "markdown" "md" &&
             [[ ! "${_markdown_tool:-}" =~ \                 ]] &&
             _command_exists "${_markdown_tool:-}"              &&
             _contains "${_markdown_tool:-}"                    \
               "bat"                                            \
               "batcat"                                         \
               "glow"                                           \
               "lowdown"                                        \
               "mdcat"                                          \
               "mdless"                                         \
               "mdv"
          then
            case "${_markdown_tool:-}" in
              bat|batcat)
                _bat --language "${_target_extension:-md}"
                ;;
              glow)
                glow --tui
                ;;
              lowdown)
                lowdown                         \
                  -Tterm                        \
                  --term-columns="${_COLUMNS}"  \
                  --term-width="${_COLUMNS}"    \
                  | _pager
                ;;
              mdcat)
                mdcat --paginate
                ;;
              mdless)
                mdless
                ;;
              mdv)
                mdv "${_target_path}" | _pager
                ;;
            esac
          elif _contains "${_target_extension:-}" "markdown" "md" &&
               [[ "${_markdown_tool:-}" =~ \                      ]]
          then
            local _markdown_command=

            IFS=' ' read -r -a _markdown_command <<< "${_markdown_tool:-}"

            "${_markdown_command[@]}" "${_target_path}"
          else
            {
              # fold to current terminal width and preserve list formatting
              LC_ALL=C sed -E                                    \
                  -e "s/^([[:space:]]*-) /\1${_ME}-ph-${_ME}/g"  \
                  -e "s/^([[:space:]]*\*) /\1${_ME}-ph-${_ME}/g" \
              | LC_ALL=C fold -s -w "${_COLUMNS}"                \
              | LC_ALL=C sed -E                                  \
                  -e "s/^([[:space:]]*-)${_ME}-ph-${_ME}/\1 /g"  \
                  -e "s/^([[:space:]]*\*)${_ME}-ph-${_ME}/\1 /g"
            } | {
              _highlight_syntax_if_available "${_target_extension:-}"
            } | {
              _pager
            }
          fi
        }
      fi
    fi
  fi

  # turn off case-insensitive matching
  shopt -u nocasematch

  if [[ -n "${_decrypted_path:-}" ]] && [[ -e "${_decrypted_path}" ]]
  then
    rm "${_decrypted_path:?}"
  fi
}
_alias_subcommand "show" "s"
_alias_subcommand "show" "view"

# unpin ################################################################# unpin

_describe_unpin() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} unpin ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])

$(_color_primary "Description"):
  Unpin a pinned item.

$(_color_primary "Read More"):
  ${_README_URL}#-pinning

$(_color_primary "See Also"):
  ${_ME} help browse
  ${_ME} help list
  ${_ME} help ls
  ${_ME} help pin

$(_color_primary "Examples"):
  ${_ME} unpin 123
  ${_ME} unpin example:sample/321
HEREDOC
}
_unpin() {
  _pin unpin "${@:-}"
}

# use ##################################################################### use

_describe_use() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} use <notebook>

$(_color_primary "Description"):
  Switch to the specified notebook. Shortcut for \`${_ME} notebooks use\`.

$(_color_primary "Read More"):
  ${_README_URL}#-notebooks

$(_color_primary "See Also"):
  ${_ME} help notebooks

$(_color_primary "Example"):
  ${_ME} use example

$(_color_primary "Shortcut Alias"):
  ${_ME} u
HEREDOC
}
_use() {
  local _name="${1:-}"
  if [[ -z "${_name}" ]]
  then
    _exit_1 _help use
  fi
  _notebooks use "${_name}"
}
_alias_subcommand "use" "u"

# version ############################################################# version

_describe_version() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} version

$(_color_primary "Description"):
  Display version information.

$(_color_primary "See Also"):
  ${_ME} help env
  ${_ME} help update
HEREDOC
}
_version() {
  printf "%s\\n" "${_VERSION}"
}

###############################################################################
# Call Deferred Command: Group 2                 Call Deferred Command: Group 2
###############################################################################
# --------------------------------------------------------------------------- #

_call_deferred_command --group 2

###############################################################################
# Subcommands: Group 3                                     Subcommands: Group 3
# --------------------                                     --------------------
###############################################################################
# --------------------------------------------------------------------------- #

# archive ############################################################# archive

_describe_archive() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} archive [<name>]

$(_color_primary "Description"):
  Set the current notebook or notebook <name> to "archived" status.

  This is an alias for \`${_ME} notebooks archive\`.

$(_color_primary "Read More"):
  ${_README_URL}#archiving-notebooks

$(_color_primary "See Also"):
  ${_ME} help notebooks
  ${_ME} help status
  ${_ME} help unarchive

$(_color_primary "Examples"):
  ${_ME} archive
  ${_ME} archive example

$(_color_primary "Shortcut Alias"):
  ${_ME} ar
HEREDOC
}
_archive() {
  _notebooks archive "${@:-}"
}
_alias_subcommand "archive" "ar"

# browse ############################################################### browse

_describe_browse() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} browse [<notebook>:][<folder-path>/][<id> | <filename> | <title>] [--daemon]
            [-g | --gui] [-n | --notebooks] [-p | --print] [-q | --query <query>]
            [-s | --serve] [-t <tag> | --tag <tag> | --tags <tag1>,<tag2>...]
  ${_ME} browse add [<notebook>:][<folder-path>/][<filename>]
            [-c <content> | --content <content>] [--tags <tag1>,<tag2>...]
            [-t <title> | --title <title>]
  ${_ME} browse delete ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
  ${_ME} browse edit ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])

$(_color_primary "Subcommands"):
  (default)  Open a notebook, folder, or item in the terminal or GUI web browser.
  add        Open the add view in the browser.
             Shortcut Aliases: \`a\`, \`+\`
  delete     Open the delete view in the browser.
             Shortcut Aliases: \`d\`, \`-\`
  edit       Open the edit view in the browser.
             Shortcut Alias:   \`e\`

$(_color_primary "Options"):
  -c, --content <content>      Add content to the new note.
  --daemon                     Start the web server. Close with <CTRL-C>.
  -g, --gui                    Open in the system's primary GUI web browser.
  -n, --notebooks              Browse notebooks.
  -p, --print                  Print to standard output.
  -q, --query <query>          Open to the search results for <query>.
  -s, --serve                  Start the web server. Close with any key.
  -t, --tag <tag>              Search for a tag.
  --tags <tag1>,<tag2>...      A comma-separated list of tags.
  -t, --title <title>          Add a title to the new note.

$(_color_primary "Description"):
  Browse, view, and edit linked notes, bookmarks, notebooks, folders, and
  other items using terminal and GUI web browsers.

  \`browse\` includes an embedded web application designed for terminal
  and GUI web browsers that renders [[wiki-style links]] and #tags as
  internal links, providing the ability to browse notes and notebooks,
  as well as seamlessly browse to and from the offsite links in
  bookmarks and notes.

  To link to a note or bookmark from another, include the selector for the
  target item within double square brackets anywhere in the linking document:

    # link to item 123 in the "sample" folder in the "example" notebook
    [[example:sample/123]]

    # link to the item titled "Example Title" in the "demo" notebook
    [[demo:Example Title]]

  \`browse\` supports \`w3m\` [1] and \`links\` [2], and depends on
  \`ncat\` [3] or \`socat\` [4] and \`pandoc\` [5]:

    1. https://en.wikipedia.org/wiki/W3m
    2. https://en.wikipedia.org/wiki/Links_(web_browser)
    3. https://nmap.org/ncat/
    4. https://www.kali.org/tools/socat/
    5. https://pandoc.org/

$(_color_primary "Read More"):
  ${_README_URL}#-browsing

$(_color_primary "See Also"):
  ${_ME} help add
  ${_ME} help delete
  ${_ME} help edit
  ${_ME} help list
  ${_ME} help ls
  ${_ME} help open
  ${_ME} help peek
  ${_ME} help pin
  ${_ME} help search
  ${_ME} help show
  ${_ME} help unpin

$(_color_primary "Examples"):
  ${_ME} browse
  ${_ME} browse example:
  ${_ME} browse Example\ Folder/
  ${_ME} browse 123
  ${_ME} browse demo:456
  ${_ME} br

$(_color_primary "Shortcut Alias"):
  ${_ME} b
HEREDOC
}
_browse() {
  # Inspired by bashttpd: https://github.com/avleen/bashttpd

  # _browse_http_response_message()
  #
  # Usage:
  #   _browse_http_response_message <status-code>
  #
  # Description:
  #   Print the response message for a given status code.
  _browse_http_response_message() {
    local _status_code="${1:-}"

    case "${_status_code}" in
      200) printf "OK\\n"                     ;;
      302) printf "Found\\n"                  ;;
      400) printf "Bad Request\\n"            ;;
      403) printf "Forbidden\\n"              ;;
      404) printf "Not Found\\n"              ;;
      405) printf "Method Not Allowed\\n"     ;;
      415) printf "Unsupported Media Type\\n" ;;
      500) printf "Internal Server Error\\n"  ;;
    esac
  }

  # _browse_item_create()
  #
  # Usage:
  #   _browse_item_create <container-path> --message-body <message-body>
  #
  # Description:
  #   Add a new item in the folder or notebook at <container-path>.
  _browse_item_create() {
    local _message_body=
    local _selector=
    local _subcommand_options=()

    while ((${#}))
    do
      case "${1:-}" in
        --col*|--limit|--local|--page|-n|--num|--number|--per*)
          _option_value_is_present "${2:-}" && shift
          ;;
        --message*body)
          _message_body="$(_option_get_value "${1:-}" "${2:-}")"

          shift
          ;;
        --terminal)
          :
          ;;
        *)
          if [[ -z "${_selector:-}" ]]
          then
            _selector="${1:-}"
          else
            _subcommand_options+=("${1:-}")
          fi
          ;;
      esac

      shift
    done

    if [[ -z "${_selector:-}"       ]]
    then
      _browse_respond_with 404
    fi

    local _notebook_path=
    _notebook_path="$(
      _notebooks show "${_selector:-}" --path 2>/dev/null ||
        _notebooks current --path
    )"

    local _fields=()
    IFS='&' read -r -a _fields <<< "${_message_body}"

    local _add_options=()
    local _prepared_encoded_content=

    local __field=
    for   __field in "${_fields[@]:-}"
    do
      case "${__field:-}" in
        content=*)
          _prepared_encoded_content="${__field#content=}"
          _prepared_encoded_content="${_prepared_encoded_content//+/ }"
          _prepared_encoded_content="${_prepared_encoded_content//%/\\x}"
          ;;
        *)
          if [[ "${__field:-}" =~ \= ]]
          then
            _add_options+=("${__field%%=*}")

            local _value=
            _value="$(_get_uri --decode "${__field#*=}")"
            _value="${_value//$'\r'}"

            _add_options+=("${_value:-}")
          else
            _add_options+=("${__field:-}")
          fi
          ;;
      esac
    done

    if [[   -n "${_prepared_encoded_content:-}" ]]
    then
      if [[ -n "${_selector:-}"                 ]]
      then
        _add_options=("${_selector:-}" "${_add_options[@]:-}")
      fi

      _add_options=("--no-color" "${_add_options[@]:-}")

      local _new_info_line=
      _new_info_line="$(
        _add "${_add_options[@]:-}" --content "$(
          printf "%b\\n" "${_prepared_encoded_content:-}" \
            | tr -d $'\r'
        )" --skip-standard-input
      )"

      local _new_selector="${_new_info_line#*[}"
      _new_selector="${_new_selector%%]*}"
      _new_selector="${_new_selector//'\ '/ }"

      printf "%s\\n" "${_new_selector}"
    fi
  }

  # _browse_item_delete()
  #
  # Usage:
  #   _browse_item_delete <path>
  #
  # Description:
  #   Delete the item at <path>.
  _browse_item_delete() {
    local _source_path=

    while ((${#}))
    do
      case "${1:-}" in
        --col*|--limit|--local|-n|--num|--number|--page|--per*|--raw-url)
          _option_value_is_present "${2:-}" && shift
          ;;
        --terminal)
          :
          ;;
        *)
          _source_path="${1:-}"
          ;;
      esac

      shift
    done

    [[ -z "${_source_path:-}" ]] && _browse_respond_with 404

    _delete "${_source_path:-}" --force
  }

  # _browse_item_update()
  #
  # Usage:
  #   _browse_item_update <path> --message-body <message-body>
  #
  # Description:
  #   Update the content of item at <path>.
  _browse_item_update() {
    local _message_body=
    local _source_path=
    local _subcommand_options=()

    while ((${#}))
    do
      case "${1:-}" in
        --col*|--limit|--local|-n|--num|--number|--page|--per*|--raw-url)
          _option_value_is_present "${2:-}" && shift
          ;;
        --message*body)
          _message_body="$(_option_get_value "${1:-}" "${2:-}")"

          shift
          ;;
        --terminal)
          :
          ;;
        *)
          if [[ -z "${_source_path:-}" ]] && [[ "${1:-}" =~ ^/ ]]
          then
            _source_path="${1:-}"
          else
            _subcommand_options+=("${1:-}")
          fi
          ;;
      esac

      shift
    done

    if [[ -z "${_source_path:-}" ]]
    then
      _browse_respond_with 404
    fi

    local _notebook_path=
    _notebook_path="$(
      _notebooks show "${_source_path:-}" --path 2>/dev/null ||
        _notebooks current --path
    )"

    if [[ "${_message_body:-}" =~ ^content= ]]
    then
      local _prepared_encoded_content="${_message_body#content=}"
      _prepared_encoded_content="${_prepared_encoded_content//+/ }"
      _prepared_encoded_content="${_prepared_encoded_content//%/\\x}"

      printf "%b\\n" "${_prepared_encoded_content:-}" \
        | tr -d $'\r'                                 \
        > "${_source_path}"

      _git checkpoint "${_notebook_path}"             \
        "[${_ME}] Edit: ${_source_path#"${_notebook_path}"/}"
    fi
  }

  # _browse_render_add()
  #
  # Usage:
  #   _browse_render_add [--columns <columns>] [--content <content>]
  #                      [--limit <limit>] [--local <url-encoded-path>]
  #                      [--tags <tag-list>] [--terminal] [--title <title>]
  #                      [--type <type>] [<add-option>...]
  #
  # Description:
  #   Print an HTML page for creating a text file.
  _browse_render_add() {
    local _columns="${NB_BROWSE_COLUMNS:-70}"
    local _content=
    local _encoded_local_notebook_path=
    local _limit="${NB_BROWSE_LIMIT:-30}"
    local _pagination_options=()
    local _selector=
    local _subcommand_options=()
    local _tag_list=
    local _target_type=
    local _title=

    while ((${#}))
    do
      case "${1:-}" in
        --col*)
          _columns="$(_option_get_value "${1:-}" "${2:-}")"
          _pagination_options+=("${1:?}" "${2:?}")

          shift
          ;;
        -c|--content)
          _content="$(_option_get_value "${1:-}" "${2:-}")"

          shift
          ;;
        --limit|-n|--num|--number|--per*)
          _limit="${2:?}"
          _pagination_options+=("${1:?}" "${2:?}")

          shift
          ;;
        --local)
          _encoded_local_notebook_path="$(_option_get_value "${1:-}" "${2:-}")"
          _pagination_options+=("${1:?}" "${2:?}")

          shift
          ;;
        --page)
          _option_value_is_present "${2:-}" && shift
          ;;
        --tags)
          _tag_list="$(_option_get_tags "${1:-}" "${2:-}")"

          shift
          ;;
        --terminal)
          _pagination_options+=("--terminal")
          ;;
        -t|--title)
          _title="$(_option_get_value "${1:-}" "${2:-}")"

          shift
          ;;
        --type)
          _target_type="$(_option_get_value "${1:-}" "${2:-}")"
          _subcommand_options+=("${1:-}" "${2:-}")

          shift
          ;;
        --*)
          _subcommand_options+=("${1:-}")

          if _option_value_is_present "${2:-}"
          then
            _subcommand_options+=("${2:-}")

            shift
          fi
          ;;
        -*)
          _subcommand_options+=("${1:-}")
          ;;
        *)
          if [[ -z "${_selector:-}" ]]
          then
            _selector="${1:-}"
          else
            _subcommand_options+=("${1:-}")
          fi
          ;;
      esac

      shift
    done

    if [[ "${_selector:-}" =~ ^/    ]] &&
       [[ -d "${_selector}"         ]]
    then # file already exists
      _browse_respond_with 302 \
"//${NB_SERVER_HOST}:${NB_SERVER_PORT}/$(_get_id_selector "${_selector:-}"  --notebook)"
    elif [[ -n "${_selector:-}"     ]]
    then
      local _notebook_name=
      _notebook_name="$(
        _notebooks show "${_selector:-}" --name 2>/dev/null ||
          _notebooks current --name
      )"

      if [[ ! "${_selector:-}" =~ : ]]
      then
        _selector="${_notebook_name}:${_selector:-}"
      fi
    fi

    local _html_title="${_ME} browse add ${_selector// /\\ }"
    local _rows=30
    local _text_area_columns="${_columns:-}"
    local _url_params=

    if _contains "--terminal" "${_pagination_options[@]:-}"
    then
      _url_params+="&--columns=${_columns}"
      _text_area_columns="$((_text_area_columns - 3))"

      _url_params+="&--limit=${_limit}"
      _rows="$((_limit + 2))"
    fi

    if [[ "${_target_type:-not-folder}" != "folder" ]]
    then
      _target_type="${NB_DEFAULT_EXTENSION:-}"
    fi

    if [[ -n "${_encoded_local_notebook_path:-}"    ]]
    then
      _url_params+="&--local=${_encoded_local_notebook_path}"
    fi

    local _form_content=

    if [[ -n  "${_title:-}"                 ]]
    then
      if [[   "${_target_type:-}" == "org"  ]]
      then
        _form_content+="#+TITLE: ${_title}${_NEWLINE}"
      else
        _form_content+="# ${_title}${_NEWLINE}"
      fi
    fi

    if [[ -n "${_tag_list:-}"     ]]
    then
      [[ -n "${_form_content:-}"  ]] && _form_content+="${_NEWLINE}"

      _form_content+="${_tag_list:-}${_NEWLINE}"
    fi

    if [[ -n "${_content:-}"      ]]
    then
      [[ -n "${_form_content:-}"  ]] && _form_content+="${_NEWLINE}"

      _form_content+="${_content:-}${_NEWLINE}"
    fi

    {
      # TODO: https://stackoverflow.com/a/15844977
      cat <<HEREDOC
<form
  accept-charset="UTF-8"
  action="/${_selector//' '/%20}?--add${_url_params:-}"
  method="post">
<textarea
  class="content"
  cols="${_text_area_columns}"
  id="content"
  name="content"
  rows="${_rows}">${_form_content:-}</textarea>
<br><br>
<input
  type="submit"
  value="add">
$(_browse_render_option_fields "${_subcommand_options[@]:-}")
</form>
HEREDOC
    } | {
      printf "%s\\n" "$(
        _browse_render_header           \
          "${_selector}"                \
          "${_pagination_options[@]:-}" \
          --add
      )"

      printf "<div class=\"main\">\\n"

      cat

      printf "</div>\\n"
    } | {
      _render                                             \
        --source-extension "${NB_DEFAULT_EXTENSION:-md}"  \
        --title "${_html_title}"
    }
  }

  # _browse_render_container()
  #
  # Usage:
  #   _browse_render_container <target-path> [--columns <columns>]
  #                            [--local <url-encoded-path>]
  #                            [--page <page-number>] [--limit <limit>]
  #                            [--query <query>] [--terminal]
  #
  # Description:
  #   Render a notebook or folder as an HTML page.
  _browse_render_container() {
    local _columns="${NB_BROWSE_COLUMNS:-70}"
    local _current_page=1
    local _encoded_local_notebook_path=
    local _limit="${NB_BROWSE_LIMIT:-30}"
    local _pagination_options=()
    local _query=
    local _target_path=
    local _terminal_browser=0

    while ((${#}))
    do
      case "${1:-}" in
        --col*)
          _columns="$(_option_get_value "${1:-}" "${2:-}")"
          _pagination_options+=("${1:-}" "${2:?}")

          shift
          ;;
        --limit|-n|--num|--number|--per*)
          _limit="${2:?}"
          _pagination_options+=("${1:-}" "${2:?}")

          shift
          ;;
        --local)
          _encoded_local_notebook_path="$(_option_get_value "${1:-}" "${2:-}")"
          _pagination_options+=("${1:-}" "${2:?}")
          ;;
        --page)
          _current_page="${2:?}"
          _pagination_options+=("${1:-}" "${2:?}")

          shift
          ;;
        --query)
          if [[ -n "${2:-}" ]]
          then
            _query="${2:-}"
          else
            _exit_1 printf                        \
              "%s requires a valid argument.\\n"  \
              "$(_color_primary "${1:-}")"
          fi

          shift
          ;;
        -t|--tag*)
          if _option_value_is_present "${2:-}"
          then
            shift
          fi
          ;;
        --terminal)
          _terminal_browser=1
          _pagination_options+=("${1:-}")
          ;;
        *)
          _target_path="${1:-}"
          _pagination_options+=("${1:-}")
          ;;
      esac

      shift
    done

    if [[ -z "${_target_path:-}"  ]]
    then
      _target_path="$(_notebooks current --path)"
    fi

    local _encoded_query=

    if [[ -n "${_query:-}"        ]]
    then
      _query_arguments=($(
        printf "%s\\n" "${_query}" | xargs -n 1 printf "%s\\n" 2>/dev/null
      )) || IFS=' ' read -ra _query_arguments <<< "${_query}"

      _encoded_query="$(
        LC_ALL=C sed          \
          -e "s/&/\&amp;/g"   \
          -e "s/</\&lt;/g"    \
          -e "s/>/\&gt;/g"    \
          -e "s/\"/\&quot;/g" \
          -e "s/#/\&#35;/g"   \
          -e "s/'/\&#39;/g"   <<< "${_query}"
      )"
    fi

    [[ ! "${_target_path}" =~ /$ ]] && _target_path="${_target_path}/"

    local _url_params=

    if ((_terminal_browser))
    then
      _url_params+="?--columns=${_columns}&--limit=${_limit}"
    fi

    if [[   -n "${_encoded_local_notebook_path:-}"  ]]
    then
      if [[ -z "${_url_params:-}"                   ]]
      then
        _url_params+="?"
      else
        _url_params+="&"
      fi

      _url_params+="--local=${_encoded_local_notebook_path:-}"
    fi

    local _maybe_columns_input=

    if ((${_columns:-}))
    then
      _maybe_columns_input="\
<input type=\"hidden\" name=\"--columns\"   value=\"${_columns}\">"
    fi

    local _current_selector=
    local _maybe_local_input=

    local _local_notebook_path=
    _local_notebook_path="$(_get_uri --decode "${_encoded_local_notebook_path:-}")"

    if [[ "${_target_path%/}" == "${_local_notebook_path%/}" ]]
    then
      _current_selector="local:"
      _maybe_local_input="\
<input type=\"hidden\" name=\"--local\"     value=\"${_local_notebook_path}\">${_NEWLINE}"
    else
      _current_selector="$(_get_id_selector "${_target_path%/}" || :)"
    fi

    local _url_encoded_selector="${_current_selector//' '/%20}"

    {
      if [[ -n "${_query:-}" ]]
      then
        _search "${_target_path}"         \
          "${_query_arguments[@]:-}"      \
          --limit "${_limit}"             \
          --list                          \
          --no-color                      \
          --notebook-selectors            \
          --page  "${_current_page}"      \
          2>&1 || :
      else
        local _list_options=(
          --limit "${_limit}"
          --no-color
          --notebook-selectors
          --page  "${_current_page}"
          --with-pinned
        )

        if ((${NB_FOLDERS_FIRST:-0}))
        then
          _list_options+=("--folders-first")
        fi

        _list "${_target_path}" "${_list_options[@]:-}"
      fi
    } | {
      local _truncate_length=9999

      if ((_terminal_browser))
      then
        case "${NB_BROWSER:-}" in
          # TODO: improve
          *elinks*) _truncate_length="$((_columns - 23))" ;;
          *links*)  _truncate_length="$((_columns - 5))"  ;;
          *)        _truncate_length="$((_columns - 2))"  ;;
        esac
      else
        _truncate_length="$((_columns + 6))"
      fi

      local         __list_item=
      while read -r __list_item
      do
        if [[ -n "${_truncate_length:-}"          ]] &&
           [[ ! "${__list_item:-}" =~ Not\ found  ]]
        then
          local _list_item_length="${#__list_item}"
          local _list_item_visible_length=
          _list_item_visible_length="$(_get_visible_length "${__list_item}")"

          local _difference=
          _difference="$((_list_item_visible_length - _list_item_length))"

          local _adjusted_truncate_length=
          _adjusted_truncate_length="$((_truncate_length - _difference))"

          if [[ "${_list_item_visible_length}" -ge "${_adjusted_truncate_length}" ]]
          then
            __list_item="${__list_item:0:$((_adjusted_truncate_length))}…"
          fi
        fi

        local _display_item="${__list_item:-}"

        local _maybe_escaped_ampersand='\&'

        if [[ "${BASH_VERSINFO[0]:-999999999}"  -lt 5   ]]  ||  {
             [[ "${BASH_VERSINFO[0]:-999999999}"  ==  5 ]]  &&
             [[ "${BASH_VERSINFO[1]:-999999999}"  -lt 2 ]]
           }
        then
          _maybe_escaped_ampersand="&"
        fi

        local _35="${_maybe_escaped_ampersand}#35;"
        local _36="${_maybe_escaped_ampersand}#36;"
        local _40="${_maybe_escaped_ampersand}#40;"
        local _41="${_maybe_escaped_ampersand}#41;"
        local _60="${_maybe_escaped_ampersand}#60;"
        local _62="${_maybe_escaped_ampersand}#62;"
        local _64="${_maybe_escaped_ampersand}#64;"

        _display_item="${_display_item//'&'/&amp;}"
        _display_item="${_display_item//'#'/${_35}}"
        _display_item="${_display_item//'$'/${_36}}"
        _display_item="${_display_item//'('/${_40}}"
        _display_item="${_display_item//')'/${_41}}"
        _display_item="${_display_item//'<'/${_60}}"
        _display_item="${_display_item//'>'/${_62}}"
        _display_item="${_display_item//'@'/${_64}}"
        _display_item="${_display_item//\\\ /${_NBSP}}"
        _display_item="${_display_item//' '/${_NBSP}}"

        # shellcheck disable=SC2140
        _display_item="${_display_item//\[/<span class=\"muted\">[</span><span class=\"identifier\">}"
        _display_item="${_display_item//\]/</span><span class=\"muted\">]</span>}"

        if [[   "${_display_item:-}" =~ ^0${_NBSP}items.        ]]
        then
          printf "%s\\n<br>\\n" "${_display_item}"

          break
        elif [[ "${_display_item:-}" =~ ^.*\!.*Not${_NBSP}found ]]
        then
          _display_item="Not${_display_item#*Not}"
          printf "%s\\n<br>\\n" "${_display_item//${_NBSP}in*:/:}"

          break
        fi

        local _item_selector="${__list_item%%]*}"
        _item_selector="${_item_selector#[}"
        _item_selector="${_item_selector//\\/}"

        local _link_selector=
        _link_selector="$(_get_id_selector "${_item_selector}" --notebook)"
        _link_selector="${_link_selector//' '/%20}"

        printf "<a href=\"//%s:%s/%s%s\" class=\"list-item\">%s</a><br>\\n"  \
          "${NB_SERVER_HOST}"                                                \
          "${NB_SERVER_PORT}"                                                \
          "${_link_selector:-}"                                              \
          "${_url_params:-}"                                                 \
          "${_display_item:-}"
      done
    } | {
      local _list_count=
      _list_count="$(_count "${_target_path}")"

      local _print_prev=0

      if ((_list_count)) && [[ "${_current_page}" -gt 1 ]]
      then
        _print_prev=1
      fi

      local _print_next=0

      if ((_list_count)) &&
         [[ "$((_current_page * _limit))" -lt "${_list_count}" ]]
      then
        _print_next=1
      fi

      cat <<HEREDOC
<form
  accept-charset="UTF-8"
  action="/${_url_encoded_selector}${_url_params:-}"
  id="search"
  method="get">
<label for="search-input">search:</label>
<input
  autocapitalize="off"
  autocomplete="off"
  id="search-input"
  name="--query"
  placeholder="search"
  type="text"
  value="${_encoded_query}">
<i></i>
<input type="hidden" name="--limit" value="${_limit}">
<input type="hidden" name="--page"  value="${_current_page}">
${_maybe_columns_input:-}
${_maybe_local_input:-}</form>
<br>
HEREDOC

      printf "<p class=\"item-list\">\\n"

      local _pagination_count=0

      local         __line=
      while read -r __line
      do
        printf "%s\\n" "${__line}"

        _pagination_count="$((_pagination_count+1))"
      done

      printf "</p>\\n"

      if [[ -n "${_query:-}"                              ]] &&
         [[ "${_pagination_count}" -lt "${_limit:-0}"  ]]
      then
        _print_next=0
      fi

      if ((_print_prev)) || ((_print_next))
      then
        printf "<p class=\"pagination\">\\n"
      fi

      if [[ -n "${_query:-}" ]]
      then
        local _url_encoded_query=
        _url_encoded_query="$(_get_uri --encode "${_query:-}")"

        _url_params+="&--query=${_url_encoded_query}"
      fi

      if ! ((_terminal_browser)) &&
         _contains "--limit" "${_pagination_options[@]:-}"
      then
        _url_params+="&--limit=${_limit}"
      fi

      if ((_print_prev))
      then
        local _prev_page_number=
        _prev_page_number="$((_current_page - 1))"

        local _prev_url_params="${_url_params#$'?'}"

        if [[ "${_prev_page_number:-0}" -gt 1     ]]
        then
          _prev_url_params+="&--page=${_prev_page_number:-}"
        fi

        _prev_url_params="${_prev_url_params#$'&'}"

        if [[ -n "${_prev_url_params:-}"          ]]
        then
          _prev_url_params="?${_prev_url_params:-}"
        fi

        printf                                    \
          "<a href=\"//%s:%s/%s%s\">%s prev</a>"  \
          "${NB_SERVER_HOST}"                     \
          "${NB_SERVER_PORT}"                     \
          "${_url_encoded_selector}"              \
          "${_prev_url_params:-}"                 \
          "${_CHEVRON_LEFT}"
      fi

      if ((_print_prev)) && ((_print_next))
      then
        printf " <span class=\"muted\">%s</span> " "${_MD}"
      fi

      if ((_print_next))
      then
        local _next_url_params=
        _next_url_params="${_url_params#$'?'}&--page=$((_current_page + 1))"

        printf                                    \
          "<a href=\"//%s:%s/%s?%s\">next %s</a>" \
          "${NB_SERVER_HOST}"                     \
          "${NB_SERVER_PORT}"                     \
          "${_url_encoded_selector}"              \
          "${_next_url_params#$'&'}"              \
          "${_CHEVRON_RIGHT}"
      fi

      if ((_print_prev)) || ((_print_next))
      then
        printf "</p>\\n"
      fi
    } | {
      printf "%s\\n" "$(_browse_render_header "${_pagination_options[@]:-}")"

      printf "<div class=\"main\">\\n"

      cat

      printf "</div>\\n"
    } | {
      local _html_title="${_ME} browse"

      if [[ -n "${_current_selector:-}" ]]
      then
        _html_title+=" ${_current_selector// /\\ }"
      fi

      if [[ -n "${_encoded_query:-}"    ]]
      then
        _html_title+=" --query \"${_encoded_query:-}\""
      fi

      if [[ "${_current_page:-0}" -gt 1 ]]
      then
        _html_title+=" --page ${_current_page}"
      fi

      _render --title "${_html_title}"
    }
  }

  # _browse_render_delete()
  #
  # Usage:
  #   _browse_render_delete <path> [--columns <columns>]
  #                         [--limit <limit>] [--local <url-encoded-path>]
  #                         [--terminal]
  #
  # Description:
  #   Print an form for deleting an item.
  _browse_render_delete() {
    local _columns="${NB_BROWSE_COLUMNS:-70}"
    local _encoded_local_notebook_path=
    local _limit="${NB_BROWSE_LIMIT:-30}"
    local _pagination_options=()
    local _raw_url=
    local _source_path=

    while ((${#}))
    do
      case "${1:-}" in
        --col*)
          _columns="$(_option_get_value "${1:-}" "${2:-}")"
          _pagination_options+=("${1:?}" "${2:?}")

          shift
          ;;
        --limit|-n|--num|--number|--per*)
          _limit="${2:?}"
          _pagination_options+=("${1:?}" "${2:?}")

          shift
          ;;
        --local)
          _encoded_local_notebook_path="$(_option_get_value "${1:-}" "${2:-}")"
          _pagination_options+=("${1:?}" "${2:?}")

          shift
          ;;
        --page)
          _option_value_is_present "${2:-}" && shift
          ;;
        --raw-url)
          _raw_url="${2:?}"

          shift
          ;;
        --terminal)
          _pagination_options+=("--terminal")
          ;;
        *)
          _source_path="${1:-}"
          ;;
      esac

      shift
    done

    local _info_line=
    _info_line="$(_show "${_source_path}" --info-line --no-color)"

    local _id_selector=
    _id_selector="$(_get_id_selector "${_source_path}")"

    local _url_params=

    if [[ -n "${_encoded_local_notebook_path:-}" ]]
    then
      _url_params+="&--local=${_encoded_local_notebook_path}"
    fi

    if _contains "--terminal" "${_pagination_options[@]:-}"
    then
      _url_params+="&--columns=${_columns}"
      _url_params+="&--limit=${_limit}"
    fi

    {
      cat <<HEREDOC
<h2 align="center">deleting</h2>

<p align="center">
<a href="//${NB_SERVER_HOST}:${NB_SERVER_PORT}/${_id_selector}${_url_params/&/?}">
${_info_line//'\ '/ }
</a>
</p>
<p align="center" class="muted">
  This item will still be available in git history.
</p>
<div align="center">
<form
  accept-charset="UTF-8"
  action="/${_id_selector:-}?--delete${_url_params:-}"
  align="center"
  method="post">
<input
  align="center"
  type="submit"
  value="delete">
</form>
</div>
HEREDOC
    } | {
      printf "%s\\n" "$(
        _browse_render_header           \
          "${_source_path}"             \
          "${_pagination_options[@]:-}" \
          --raw-url "${_raw_url}"       \
          --delete
      )"

      printf "<div class=\"main\">\\n"

      cat

      printf "</div>\\n"
    } | {
      _render --title "${_ME} browse delete ${_id_selector// /\\ }"
    }
  }

  # _browse_render_edit()
  #
  # Usage:
  #   _browse_render_edit <path> [--columns <columns>]
  #                       [--limit <limit>] [--local <url-encoded-path>]
  #                       [--terminal] [<edit-option>...]
  #
  # Description:
  #   Print an HTML page for editing a text file.
  _browse_render_edit() {
    local _columns="${NB_BROWSE_COLUMNS:-70}"
    local _encoded_local_notebook_path=
    local _limit="${NB_BROWSE_LIMIT:-30}"
    local _pagination_options=()
    local _raw_url=
    local _source_path=
    local _subcommand_options=()

    while ((${#}))
    do
      case "${1:-}" in
        --col*)
          _columns="$(_option_get_value "${1:-}" "${2:-}")"
          _pagination_options+=("${1:?}" "${2:?}")

          shift
          ;;
        --limit|-n|--num|--number|--per*)
          _limit="${2:?}"
          _pagination_options+=("${1:?}" "${2:?}")

          shift
          ;;
        --local)
          _encoded_local_notebook_path="$(_option_get_value "${1:-}" "${2:-}")"
          _pagination_options+=("${1:?}" "${2:?}")

          shift
          ;;
        --page)
          _option_value_is_present "${2:-}" && shift
          ;;
        --raw-url)
          _raw_url="${2:?}"

          shift
          ;;
        --terminal)
          _pagination_options+=("--terminal")
          ;;
        *)
          if [[ -z "${_source_path:-}"  ]] && [[    "${1:-}" =~ ^/    ]]
          then
            _source_path="${1:-}"
          elif [[ "${1:-}" =~ :         ]] && [[ !  "${1:-}" =~ \-\-  ]]
          then
            : # skip selector
          else
            _subcommand_options+=("${1:-}")
          fi
          ;;
      esac

      shift
    done

    local _content=
    _content="$(_show "${_source_path}" --print --no-color)"

    local _id_selector=
    _id_selector="$(_get_id_selector "${_source_path}" --notebook)"

    local _form_action_selector=
    _form_action_selector="${_id_selector// /%20}"

    local _last_saved_at=
    _last_saved_at="$(_show "${_source_path}" --updated)"
    _last_saved_at="${_last_saved_at% -[0-9][0-9][0-9][0-9]}"

    local _rows=30
    local _text_area_columns="${_columns:-}"
    local _url_params=

    if _contains "--terminal" "${_pagination_options[@]:-}"
    then
      _url_params+="&--columns=${_columns}"
      _text_area_columns="$((_text_area_columns - 3))"

      _url_params+="&--limit=${_limit}"
      _rows="$((_limit + 2))"
    fi

    if [[ -n "${_encoded_local_notebook_path:-}" ]]
    then
      _url_params+="&--local=${_encoded_local_notebook_path}"
    fi

    {
      # TODO: https://stackoverflow.com/a/15844977
      cat <<HEREDOC
<form
  accept-charset="UTF-8"
  action="/${_form_action_selector:-}?--edit${_url_params:-}"
  method="post">
<textarea
  class="content"
  cols="${_text_area_columns}"
  id="content"
  name="content"
  rows="${_rows}">${_content}</textarea>
<br><br>
<input
  type="submit"
  value="save"> <span class="muted">${_MD}</span> <span class="muted last-saved">last: ${_last_saved_at}</span>
$(_browse_render_option_fields "${_subcommand_options[@]:-}")
</form>
HEREDOC
    } | {
      printf "%s\\n" "$(
        _browse_render_header           \
          "${_source_path}"             \
          "${_pagination_options[@]:-}" \
          --raw-url "${_raw_url}"       \
          --edit
      )"

      printf "<div class=\"main\">\\n"

      cat

      printf "</div>\\n"
    } | {
      _render                                     \
        --source-extension "${_source_path##*.}"  \
        --title "${_ME} browse edit ${_id_selector// /\\ }"
    }
  }

  # _browse_render_header()
  #
  # Usage:
  #   _browse_render_header <selector> [--columns <columns>]
  #                         [--local <url-encoded-path>] [--limit <limit>]
  #                         [--raw-url <url>] [--terminal]
  #
  # Description:
  #   Print a context-aware, linked nav header.
  _browse_render_header() {
    local _action=
    local _columns="${NB_BROWSE_COLUMNS:-70}"
    local _encoded_local_notebook_path=
    local _limit="${NB_BROWSE_LIMIT:-30}"
    local _raw_url=
    local _selector=
    local _terminal_browser=0

    while ((${#}))
    do
      case "${1:-}" in
        '') : ;;
        --add|--delete|--edit)
          _action="${1#--}"
          ;;
        --col*)
          _columns="${2:?}"

          shift
          ;;
        --limit|-n|--num|--number|--per*)
          _limit="${2:?}"

          shift
          ;;
        --local)    _encoded_local_notebook_path="${2:?}" && shift  ;;
        --page)     _option_value_is_present     "${2:-}" && shift  ;;
        --raw-url)  _raw_url="${2:?}"                     && shift  ;;
        --terminal) _terminal_browser=1                             ;;
        --*)        _option_value_is_present "${2:-}"     && shift  ;;
        -*)         :                                               ;;
        *)          _selector="${1:-}"                              ;;
      esac

      shift
    done

    local _url_params=()

    if [[ -n "${_encoded_local_notebook_path:-}" ]]
    then
      _url_params+=("--local=${_encoded_local_notebook_path}")
    fi

    if ((_terminal_browser))
    then
      _url_params+=(
        "--columns=${_columns}"
        "--limit=${_limit}"
      )
    fi

    local _url_param_string=
    _url_param_string="$(_join "&" "${_url_params[@]:-}")"

    if [[ -n "${_url_param_string:-}" ]]
    then
      _url_param_string="?${_url_param_string}"
      local _url_params_ext="${_url_param_string}&"
    else
      local _url_params_ext="?"
    fi

    local _header_content="\
<a href=\"//${NB_SERVER_HOST}:${NB_SERVER_PORT}/${_url_param_string:-}\">"
    _header_content+="<span class=\"muted\">${_CHEVRON_RIGHT}</span>${_ME}</a>"
    _header_content+=" <span class=\"muted\">${_MD}</span>"

    if [[ -z "${_selector:-}"         ]]
    then
      _header_content+=" <span class=\"muted\">notebooks</span>"
    else
      local _notebook_name=

      if [[ "${_selector}" =~ (:|^/)  ]]
      then
        _notebook_name="$(_notebooks show "${_selector}" --name)"
      fi

      if [[ -z "${_notebook_name}"    ]]
      then
        _notebook_name="$(_notebooks current --name)"
      fi

      local _notebook_path=
      _notebook_path="$(_notebooks show "${_notebook_name}" --path)"

      _notebooks select "${_notebook_path}"

      _header_content+="\
 <a href=\"//${NB_SERVER_HOST}:${NB_SERVER_PORT}/${_notebook_name//' '/%20}:${_url_param_string:-}\">${_notebook_name}</a>"
      _header_content+=" <span class=\"muted\">:</span>"

      local _relative_folder_path=
      local _selector_relative_folder_path=

      if [[ "${_selector}" =~ ^/      ]]
      then
        local _relative_path="${_selector#"${_notebook_path}"/}"

        if [[ "${_relative_path:-}" == "${_notebook_path:-}" ]]
        then
          _relative_path=
        fi

        if [[ -d "${_selector}"       ]]
        then
          _relative_folder_path="${_relative_path:-}"
        else
          if [[ "${_relative_path:-}" =~ / ]]
          then
            _relative_folder_path="${_relative_path%/*}"
          else
            _relative_folder_path=
          fi
        fi

        _selector_relative_folder_path="${_relative_folder_path:-}"
      else
        _selector_relative_folder_path="${_selector#*:}"
        _relative_folder_path="$(
          _selector_resolve_folders "${_selector_relative_folder_path}" || :
        )"
      fi

      if [[ -n "${_relative_folder_path:-}"                  ]] &&
         [[ -d "${_notebook_path}/${_relative_folder_path}"  ]]
      then
        local _selector_folders=()
        IFS='/' read -ra _selector_folders <<< "${_relative_folder_path}"

        local _folder_id_path=
        _folder_id_path="$(
          _get_id_selector "$(
            _join "/" "${_selector_folders[@]:-}"
          )/" "${_notebook_path}"
        )"

        local _selector_folder_ids=()
        IFS='/' read -ra _selector_folder_ids <<< "${_folder_id_path}"

        local _url_path="${_notebook_name}:"

        local i=
        for ((i=0; i < ${#_selector_folders[@]}; i++))
        do
          _url_path+="${_selector_folder_ids[i]:-}/"

          _header_content+="\
 <a href=\"//${NB_SERVER_HOST}:${NB_SERVER_PORT}/${_url_path}${_url_param_string:-}\">${_selector_folders[i]}</a>"
          _header_content+=" <span class=\"muted\">/</span>"
        done
      fi
    fi

    local _item_path=
    _item_path="$(_show "${_selector:-}" --path 2>/dev/null || :)"

    if [[ -f "${_item_path:-}"  ]]
    then
      local _id_selector=
      _id_selector="$(_get_id_selector "${_selector:-}" --notebook)"

      local _selector_id="${_id_selector#*:}"
      _selector_id="${_selector_id##*/}"

      if _contains "${_action:-}" "edit" "delete"
      then
        _header_content+="\
 <a href=\"//${NB_SERVER_HOST}:${NB_SERVER_PORT}/${_id_selector:-}${_url_param_string:-}\">${_selector_id:-}</a>"
      elif [[ "${_action:-}" != "add"   ]]
      then
        _header_content+=" <span class=\"muted\">${_selector_id:-}</span>"
      fi

      # NOTE: backup _raw_url calculation. TODO: remove
      if [[ -z "${_raw_url:-}"  ]]
      then
        local _raw_url="//${NB_SERVER_HOST}:${NB_SERVER_PORT}/--original/"

        if [[ !   "${_item_path:-}" =~ ^${NB_DIR}     ]] &&
           [[ -n  "${_encoded_local_notebook_path:-}" ]]
        then
          local _local_notebook_path=
          _local_notebook_path="$(_get_uri --decode "${_encoded_local_notebook_path}")"

          _raw_url+="local/${_item_path#"${_local_notebook_path}"/}?--local=${_encoded_local_notebook_path}"
        else
          _raw_url+="${_item_path#"${NB_DIR}"/}"
        fi
      fi

      if [[ -n "${_raw_url:-}"  ]]
      then
        _header_content+=" <span class=\"muted\">${_MD}</span>"
        _header_content+=" <a href=\"${_raw_url}\">↓</a>"
      fi

      if [[ "${_action:-}"  == "edit"   ]]
      then
        _header_content+=" <span class=\"muted\">${_MD}</span>"
        _header_content+=" <span class=\"muted\">editing</span>"
      elif _file_is_text "${_selector:-}"
      then
        _header_content+=" <span class=\"muted\">${_MD}</span>"
        _header_content+="\
 <a href=\"//${NB_SERVER_HOST}:${NB_SERVER_PORT}/${_id_selector:-}${_url_params_ext:-}--edit\">edit</a>"
      fi

      case "${_action:-}" in
        delete)
          _header_content+=" <span class=\"muted\">${_MD}</span>"
          _header_content+=" <span class=\"muted\">-</span>"
          _header_content+=" <span class=\"muted\">|</span>"
          ;;
        edit)
          _header_content+=" <span class=\"muted\">${_MD}</span>"
          _header_content+="\
 <a href=\"//${NB_SERVER_HOST}:${NB_SERVER_PORT}/${_id_selector:-}${_url_params_ext:-}--delete\">-</a>"
          _header_content+=" <span class=\"muted\">|</span>"
          ;;
        *)
          _header_content+=" <span class=\"muted\">|</span>"
          ;;
      esac
    fi

    if [[ -n "${_selector:-}"           ]]
    then
      if [[ "${_action:-}"  == "add"    ]]
      then
        _header_content+=" <span class=\"muted\">+</span>"
      else
        _header_content+="\
 <a href=\"//${NB_SERVER_HOST}:${NB_SERVER_PORT}/${_notebook_name}:${_folder_id_path:-}${_url_params_ext:-}--add\">+</a>"
      fi
    fi

    cat <<HEREDOC
<nav class="header-crumbs"><strong>${_header_content:-}</strong></nav>
<p class="header-crumbs-spacer"></p>
HEREDOC
  }

  # _browse_render_item()
  #
  # Usage:
  #   _browse_render_item <path> [--columns <columns>]
  #                       [--limit <limit>] [--local <url-encoded-path>]
  #                       [--raw-url <url>] [--terminal]
  #
  # Description:
  #   Render an item to HTML with links resolved to internal web server.
  _browse_render_item() {
    local _columns="${NB_BROWSE_COLUMNS:-70}"
    local _pagination_options=()
    local _raw_url=
    local _respond_with_arguments=("--standard-input")
    local _source_path=

    while ((${#}))
    do
      case "${1:-}" in
        --col*)
          _columns="$(_option_get_value "${1:-}" "${2:-}")"
          _pagination_options+=("${1:-}" "${2:?}")

          shift
          ;;
        --headers)
          _respond_with_arguments+=("${1:-}")
          ;;
        --limit|-n|--num|--number|--per*)
          _pagination_options+=("${1:?}" "${2:?}")

          shift
          ;;
        --local)
          _pagination_options+=("${1:-}" "${2:?}")

          shift
          ;;
        --page)
          _option_value_is_present "${2:-}" && shift
          ;;
        --raw-url)
          _raw_url="${2:?}"

          shift
          ;;
        --terminal)
          _pagination_options+=("--terminal")
          ;;
        *)
          if [[ -z "${_source_path:-}"  ]]
          then
            _source_path="${1:-}"
          fi
          ;;
      esac

      shift
    done

    local _header_options=("${_pagination_options[@]:-}")

    if [[ -n "${_raw_url:-}" ]]
    then
      _header_options+=("--raw-url" "${_raw_url}")
    fi

    local _id_selector=
    _id_selector="$(_get_id_selector "${_source_path:-}" --notebook)"

    local _html_title="${_ME} browse ${_id_selector// /\\\ }"

    local _render_type=

    if _file_is_text "${_source_path:-}"  ||
       [[   "${_source_path:-}" =~ (\.docx$|\.epub$|\.odt$) ]]
    then
      _render_type="pandoc"
    elif _contains "${_source_path##*.}"  \
           apng avif gif jfif jpeg jpg pjpeg pjp png svg webp
    then
      _render_type="image"
    elif _file_is_audio "${_source_path:-}"
    then
      _render_type="audio"
    elif _file_is_video "${_source_path:-}"
    then
      _render_type="video"
    elif [[ "${_source_path}" =~ \.pdf    ]]
    then
      _render_type="pdf"
    else
      {
        printf "%s\\n" "$(
          _browse_render_header           \
            "${_source_path}"             \
            "${_header_options[@]:-}"
        )"

        printf "<div class=\"main\">\\n<p>\\n"

        if _file_is_encrypted "${_source_path:-}"
        then
          printf "415 %s: File is encrypted\\n" \
            "$(_browse_http_response_message 415)"
        else
          printf "415 %s\\n"                    \
            "$(_browse_http_response_message 415)"
        fi

        printf "</p>\\n</div>\\n"
      } | {
        _render --title "${_html_title}"
      } | {
        _browse_respond_with 415 "${_respond_with_arguments[@]:-}"
      }

      return 1
    fi

    local _notebook_path=
    _notebook_path="$(
      _notebooks show "${_source_path:-}" --path 2>/dev/null  ||
        _notebooks current --path
    )"

    if [[ "${_source_path:-}" =~ (\.asciidoc$|\.adoc$)  ]]    &&
       _file_is_text "${_source_path:-}"                      &&
       _command_exists "asciidoctor"
    then
      {
        asciidoctor           \
          -o -                \
          --no-header-footer  \
          "${_source_path:-}"
      } | {
        printf "%s\\n" "$(
          _browse_render_header           \
            "${_source_path}"             \
            "${_header_options[@]:-}"
        )"

        printf "<div class=\"main\">\\n"

        cat

        printf "</div>\\n"
      } | {
        _resolve_links                    \
          "${_notebook_path}"             \
          "${_pagination_options[@]:-}"   \
          --browse
      } | {
        _render --title "${_html_title}"
      }
    elif [[ "${_source_path:-}" =~ \.org$               ]]    &&
         _file_is_text "${_source_path:-}"
    then # resolve Org [[wiki-style links]] before rendering to HTML
      {
        cat "${_source_path}"
      } | {
        _resolve_links                    \
          "${_notebook_path}"             \
          "${_pagination_options[@]:-}"   \
          --browse                        \
          --type org
      } | {
        # avoid pandoc bug with brackets in Org link descriptions
        LC_ALL=C sed -E                                   \
          -e "s/\]\[\[\[/\]\[${_ME}-placeholder-${_ME}/g" \
          -e "s/\]\]\]\]/${_ME}-placeholder-${_ME}\]\]/g"
      } | {
        if _command_exists "pandoc"
        then
          _pandoc             \
            --standard-input  \
            --from  org       \
            --to    html
        else
          cat
        fi
      } | {
        LC_ALL=C sed -E                                   \
          -e "s/>${_ME}-placeholder-${_ME}/>\[\[/g"       \
          -e "s/${_ME}-placeholder-${_ME}</\]\]</g"
      } | {
        # undo pandoc adding "file://" or "file:///" to protocol-relative URLs
        LC_ALL=C sed -E -e "s/file:\/\/\/\/\/?/\/\//g"
      } | {
        printf "%s\\n" "$(
          _browse_render_header           \
            "${_source_path}"             \
            "${_header_options[@]:-}"
        )"

        printf "<div class=\"main\">\\n"

        cat

        printf "</div>\\n"
      } | {
        _render --title "${_html_title}"
      }
    else # render non-Org to HTML before resolving [[wiki-style links]]
      {
        case "${_render_type:-}" in
          pandoc)
            local _render_options=("--pandoc" "--body" "--title" "${_html_title}")

            if [[ "${_source_path:-}" =~ \.bookmark\.md ]]
            then
              _render_options+=("--bookmark")
            fi

            {
              printf "" | _render "${_source_path}" "${_render_options[@]:-}"
            } | {
              if _command_exists "pandoc"
              then
                cat
              else
                if ! _contains "--terminal" "${_pagination_options[@]:-}"
                then
                  printf "<br>"
                fi

                LC_ALL=C sed -E                               \
                  -e "/<span class=\"muted\"/!s/</\&lt;/g"    \
                  -e "/<span class=\"muted\"/!s/\//\&#47;/g"  \
                  -e "s/.*/&<br>/g" # " TODO: vim highlighting bug
              fi
            }
            ;;
          *)
            { # begin media markup pipeline
              case "${_render_type:-}" in
                audio)
                  local _mime_type=
                  _mime_type="$(file -b --mime-type "${_source_path}" 2>/dev/null || :)"

                  # handle `file` 5.40 bug: https://bugs.astron.com/view.php?id=259
                  _mime_type="${_mime_type//audio\/mpegapplication\/octet-stream/audio/mpeg}"
                  _mime_type="${_mime_type//audio\/mpegaudio\/mpeg/audio/mpeg}"

                  cat <<HEREDOC
<audio controls>
  <source src="${_raw_url}" type="${_mime_type:-}">
</audio>
HEREDOC
                  ;;
                image)
                  cat <<HEREDOC
<a href="${_raw_url}">
  <img src="${_raw_url}" alt="${_NB_INDICATOR_IMAGE:-}${_source_path##*/}" />
</a>
HEREDOC
                  ;;
                pdf)
                  if ((${NB_BROWSE_PDF_TO_TEXT_ENABLED:-0}))  &&
                     _command_exists "pdftotext"
                  then
                    # TODO: spacing
                    # NOTE: add uniform newlines: `sed  '/^$/d' | sed G`
                    pdftotext "${_source_path}" - \
                      | tr -d '\014'              \
                      | _render --from="md" --pandoc --body
                  else
                    cat <<HEREDOC
<iframe src="${_raw_url}" width="100%" height="700px"></iframe>
HEREDOC
                  fi
                  ;;
                video)
                  local _mime_type=
                  _mime_type="$(file -b --mime-type "${_source_path}" 2>/dev/null || :)"

                  cat <<HEREDOC
<video width="320" height="240" controls>
  <source src="${_raw_url}" type="${_mime_type}">
</video>
HEREDOC
                  ;;
              esac
            } | { # media markup pipeline
              cat <<HEREDOC
<div align="center" class="media-item">
  $(cat)
</div>

<p align="center" class="media-caption">
  <a href="${_raw_url}">
    ${_source_path##*/}
  </a>
</p>
HEREDOC
            } # end media markup pipeline
            ;;
        esac
      } | {
        printf "%s\\n" "$(
          _browse_render_header           \
            "${_source_path}"             \
            "${_header_options[@]:-}"
        )"

        printf "<div class=\"main\">\\n"

        cat

        printf "</div>\\n"
      } | {
        local _resolve_links_options=(${_pagination_options[@]:-})

        if [[ "${_source_path:-}" =~ \.bookmark\.md ]]
        then
          _resolve_links_options+=("--bookmark")
        fi

        _resolve_links                      \
          "${_notebook_path}"               \
          "${_resolve_links_options[@]:-}"  \
          --browse
      } | {
        _render --title "${_html_title}"
      }
    fi | {
      # rewrite relative image paths to use --original URLs

      local _encoded_notebook_name="${_raw_url#//"${NB_SERVER_HOST}":"${NB_SERVER_PORT}"/--original/}"
      _encoded_notebook_name="${_encoded_notebook_name%%/*}"

      local _raw_url_base_pattern="\/\/${NB_SERVER_HOST}:${NB_SERVER_PORT}\/--original\/${_encoded_notebook_name}\/"
      local _raw_url_pattern="${_raw_url_base_pattern}\1"

      local _sed_arguments=()

      _sed_arguments+=(
-e "s/<img src=\"([^\"]+)\"/<img src=\"${_raw_url_pattern}\"/g"
-e "s/<img src=\"${_raw_url_base_pattern}(https?:[^\"]+)\"/<img src=\"\1\"/g"
-e "s/<img src=\"${_raw_url_base_pattern}(\/\/[^\"]+)\"/<img src=\"\1\"/g"
      )

      if [[ -n "${_encoded_local_notebook_path:-}" ]]
      then
        local _local_param_pattern="\1\?--local=${_encoded_local_notebook_path}"

        _sed_arguments+=(
-e "s/<img src=\"(${_raw_url_base_pattern}[^\"]+)\"/<img src=\"${_local_param_pattern}\"/g"
-e "s/<img src=\"([^\"]+\?--local=[^\"]+)\?--local=[^\"]+\"/<img src=\"\1\"/g"
        )
      fi

      LC_ALL=C sed -E "${_sed_arguments[@]:-}"
    } | {
      _browse_respond_with 200 "${_respond_with_arguments[@]:-}"
    }

    return 0
  }

  # _browse_render_notebooks()
  #
  # Usage:
  #   _browse_render_notebooks [--columns <columns>]
  #                            [--limit <limit>] [--local <url-encoded-path>]
  #                            [--terminal]
  #
  # Description:
  #   Print an HTML page listing notebooks.
  _browse_render_notebooks() {
    local _add_line_breaks=0
    local _columns="${NB_BROWSE_COLUMNS:-70}"
    local _encoded_local_notebook_path=
    local _limit="${NB_BROWSE_LIMIT:-30}"
    local _pagination_options=()
    local _user_agent=

    while ((${#}))
    do
      case "${1:-}" in
        --col*)
          _columns="$(_option_get_value "${1:-}" "${2:-}")"
          _pagination_options+=("${1:-}" "${2:?}")
          _add_line_breaks=1

          shift
          ;;
        --limit|-n|--num|--number|--per*)
          _limit="${2:?}"
          _pagination_options+=("${1:-}" "${2:?}")

          shift
          ;;
        --local)
          _encoded_local_notebook_path="$(_option_get_value "${1:-}" "${2:-}")"
          _pagination_options+=("${1:?}" "${2:?}")

          shift
          ;;
        --page)
          _option_value_is_present "${2:-}" && shift
          ;;
        --terminal)
          _pagination_options+=("--terminal")
          _add_line_breaks=1
          ;;
        --user-agent)
          if [[ -n "${2:-}" ]]
          then
            _user_agent="$(_option_get_value "${1:-}" "${2:-}")"

            shift
          fi
          ;;
      esac

      shift
    done

    local _notebook_names=()
    _notebook_names=($(_notebooks --names --unarchived --no-color --global))

    local _url_param_string=

    if [[ -n "${_encoded_local_notebook_path:-}" ]]
    then
      _notebook_names=("local" "${_notebook_names[@]:-}")
      _url_param_string+="&--local=${_encoded_local_notebook_path}"
    fi

    if _contains "--terminal" "${_pagination_options[@]:-}"
    then
      _url_param_string+="&--columns=${_columns}&--limit=${_limit}"
    fi

    # turn on case-insensitive matching
    shopt -s nocasematch
    case "${_user_agent:-}" in
      *elinks*)
        _columns="$((_columns - 30))"
        ;;
      *links*)
        _columns="$((_columns - 5))"
        ;;
    esac
    # turn off case-insensitive matching
    shopt -u nocasematch

    {
      printf "<p>"

      local _first=1
      local _test_line=

      local __name=
      for   __name in "${_notebook_names[@]:-}"
      do
        if ((_first))
        then
          _first=0
          _test_line+="${__name}${_NBSP}${_MD}"
        else
          _test_line+=" ${__name}${_NBSP}${_MD}"

          if ((_add_line_breaks)) && [[ "${#_test_line}" -gt "${_columns}" ]]
          then
            printf "<br>\\n"
            _test_line="${__name}${_NBSP}${_MD}"
          else
            printf "%s<span class=\"muted\">%s</span> " "${_NBSP}" "${_MD}"
          fi
        fi

        printf                                \
          "<a href=\"//%s:%s/%s:%s\">%s</a>"  \
          "${NB_SERVER_HOST}"                 \
          "${NB_SERVER_PORT}"                 \
          "${__name//' '/%20}"                \
          "${_url_param_string/&/?}"          \
          "${__name//\ /${_NBSP}}"
      done

      printf "</p>\\n"
    } | {
      printf "%s\\n" "$(_browse_render_header "${_pagination_options[@]:-}")"

      printf "<div class=\"main\">\\n"

      cat

      if ((${NB_BROWSE_SUPPORT_LINKS:-1})) &&
         ((${#_notebook_names[@]} - 40))
      then
        printf "<br /><div align=\"center\" class=\"muted\">"
        printf "<a href=\"https://github.com/sponsors/xwmx\">Sponsor</a>\\n"
        printf "<span class=\"muted\">•</span>\\n"
        printf "<a href=\"https://www.paypal.com/paypalme/WilliamMelody\">Donate</a>"
        printf "</div>\\n"
      fi

      printf "</div>\\n"
    } | {
      _render --title "${_ME} browse --notebooks"
    }
  }

  # _browse_render_option_fields
  #
  # Usage:
  #   _browse_render_option_fields <option>...
  #
  # Description:
  #   Render a series of hidden form fields for the given options.
  _browse_render_option_fields() {
    local _subcommand_options=("${@:-}")

    local i=
    for ((i=0; i < ${#_subcommand_options[@]}; i++))
    do
      if [[   "${_subcommand_options[i]}"           =~ \--  ]] &&
         [[ ! "${_subcommand_options[$((i+1))]:--}" =~ ^-   ]]
      then
        printf "<input type=\"hidden\" name=\"%s\" value=\"%s\">\\n"  \
          "$(_get_uri --encode "${_subcommand_options[i]}")"          \
          "$(_get_uri --encode "${_subcommand_options[$((i+1))]}")"

        i="$((i+1))"
      elif [[ -n "${_subcommand_options[i]:-}" ]]
      then
        printf "<input type=\"hidden\" name=\"%s\">\\n"               \
          "$(_get_uri --encode "${_subcommand_options[i]}")"
      fi
    done
  }

  # _browse_respond()
  #
  # Usage:
  #   _browse_respond
  #
  # Description:
  #   Build a response using standard input and print to standard output.
  _browse_respond() {
    # ---------------
    # Request parsing

    # Request-Line HTTP RFC 2616 §5
    # https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html
    local   _request_line=
    read -r _request_line || _browse_respond_with 400

    # strip trailing CR if it exists
    _request_line="${_request_line%%$'\r'}"

    local _request_http_version=
    local _request_method=
    local _request_uri=

    IFS=' ' read -r   \
      _request_method \
      _request_uri    \
      _request_http_version <<< "${_request_line}"

    if [[ -z "${_request_method:-}"       ]] ||
       [[ -z "${_request_uri:-}"          ]] ||
       [[ -z "${_request_http_version:-}" ]]
    then
      _browse_respond_with 400
    fi

    # parse headers and message body

    local _content_length=

    case "${_request_method:-}" in
      POST) local _looking_for_content_length=1 ;;
      *)    local _looking_for_content_length=0 ;;
    esac

    local _looking_for_end_of_headers=1
    local _looking_for_user_agent=1
    local _request_user_agent=
    local _terminal_browser=1

    while ((_looking_for_user_agent))     ||
          ((_looking_for_content_length)) ||
          ((_looking_for_end_of_headers))
    do
      local   __request_line=
      read -r __request_line

      if ((_looking_for_user_agent))  &&
         [[ "${__request_line:-}"     =~ User-Agent             ]]
      then # detect browser type
        # turn on case-insensitive matching
        shopt -s nocasematch
        if [[ ! "${__request_line}"   =~ (curl|Links|Lynx|w3m)  ]]
        then
          _terminal_browser=0
        fi
        # turn off case-insensitive matching
        shopt -u nocasematch

        _looking_for_user_agent=0
        _request_user_agent="${__request_line:-}"
      elif ((_looking_for_content_length)) &&
           [[ "${__request_line:-}"   =~ Content-Length ]]
      then # assign content length
        _content_length="${__request_line##*: }"
        _content_length="${_content_length%%$'\r'}"

        _looking_for_content_length=0
      elif [[ -z "${__request_line%%$'\r'}"             ]]
      then
        _looking_for_end_of_headers=0

        break
      fi
    done

    # get message body

    local _message_body=

    if [[ "${_request_method}"  == "POST"         ]]  &&
       ((${_content_length:-0}))
    then
      read -r -n "${_content_length}" _message_body
    fi

    # serve ace editor files

    if [[ "${_request_uri}"     =~ /--ace/.*      ]]
    then
      local _target_relative_path="${_request_uri#/--ace/}"

      _browse_respond_with 200 \
        "${NB_DIR}/.assets/ace-builds/src-min-noconflict/${_target_relative_path}"

      return 0
    fi

    # serve mathjax files

    if [[ "${_request_uri}"     =~ /--mathjax/.*  ]]
    then
      local _target_relative_path="${_request_uri#/--mathjax/}"

      if [[   -e "${NB_DIR}/.assets/MathJax/es5/${_target_relative_path}"   ]]
      then
        _browse_respond_with 200 \
          "${NB_DIR}/.assets/MathJax/es5/${_target_relative_path}"
      elif [[ -e "${NB_DIR}/.assets/MathJax/${_target_relative_path}"  ]]
      then
        _browse_respond_with 200 \
          "${NB_DIR}/.assets/MathJax/${_target_relative_path}"
      else
        _browse_respond_with 404
      fi

      return 0
    fi

    # query string

    local _query_string=

    if [[ "${_request_uri:-}" =~ \? ]]
    then
      _query_string="${_request_uri#*\?}"
    fi

    local _action=
    local _columns=1
    local _encoded_local_notebook_path=
    local _limit="${NB_BROWSE_LIMIT:-30}"
    local _local_notebook_path=
    local _page_number=1
    local _query=
    local _render_function_options=()
    local _request_parameters=()

    if [[ -n "${_query_string:-}"   ]]
    then
      IFS='&' read -r -a _request_parameters <<< "${_query_string}"

      local __parameter=
      for   __parameter in "${_request_parameters[@]:-}"
      do
        case "${__parameter:-}" in
          url=*)
            _browse_respond_with 302 "$(_get_uri --decode "${__parameter#*=}")"
            ;;
          --add|--delete|--edit)
            _action="${__parameter#--}"
            ;;
          --columns=*)
            _columns="${__parameter#*=}"
            _render_function_options+=("--columns" "${_columns}")
            ;;
          --gui)
            _terminal_browser=0
            ;;
          --limit=*|-n=*|-num=*|--number=*|--per*page=*)
            _limit="${__parameter#*=}"
            _render_function_options+=("--limit" "${_limit}")
            ;;
          --local=*)
            _encoded_local_notebook_path="${__parameter#*=}"
            _local_notebook_path="$(
              _get_uri --decode "${_encoded_local_notebook_path}"
            )"
            ;;
          --page=*)
            _page_number="${__parameter#*=}"
            ;;
          --query=*)
            _query="$(_get_uri --decode "${__parameter#*=}")"
            ;;
          --terminal)
            _terminal_browser=1
            ;;
          -*)
            _render_function_options+=("${__parameter%=*}")

            if [[ "${__parameter:-}" =~ \=    ]]
            then
              _render_function_options+=("$(
                _get_uri --decode "${__parameter#*=}"
              )")
            fi
            ;;
        esac
      done
    fi

    # serve raw files

    if [[ "${_request_uri}" =~ /--original/.* ]]
    then
      local _target_relative_path_with_notebook="${_request_uri#/--original/}"
      _target_relative_path_with_notebook="${_target_relative_path_with_notebook%%\?*}"

      _target_relative_path_with_notebook="$(
        _get_uri --decode "${_target_relative_path_with_notebook:-}"
      )"

      if [[ "${_target_relative_path_with_notebook}" =~ ^local/ ]] &&
         [[ -n "${_local_notebook_path:-}"                      ]]
      then
        _browse_respond_with 200  \
          --original              \
          "${_local_notebook_path:-}/${_target_relative_path_with_notebook#*/}"
      else
        _browse_respond_with 200  \
          --original              \
          "${NB_DIR}/${_target_relative_path_with_notebook}"
      fi

      return 0
    fi

    # prepare response

    local _request_uri_base="${_request_uri%\?--*}" # strip parameters
    local _target_selector="${_request_uri_base#\/}"

    _target_selector="$(_get_uri --decode "${_target_selector:-}")"

    local _response_url_params=

    if ((_terminal_browser))
    then
      _render_function_options+=("--terminal")
      _response_url_params+="&--limit=${_limit}"
    fi

    if [[ -n "${_encoded_local_notebook_path:-}"  ]]
    then
      _render_function_options+=("--local" "${_encoded_local_notebook_path:-}")
      _response_url_params+="&--local=${_encoded_local_notebook_path:-}"
    fi

    _response_url_params="${_response_url_params/&/?}"

    local _respond_with_200_arguments=("--standard-input")

    case "${_request_method}" in
      HEAD) _respond_with_200_arguments+=("--headers")  ;;
    esac

    # respond

    if [[ -z "${_target_selector:-}"  ]]
    then
      _browse_render_notebooks                    \
        "${_render_function_options[@]:-}"        \
        --user-agent "${_request_user_agent:-}"   \
        | _browse_respond_with 200                \
          "${_respond_with_200_arguments[@]:-}"

      return 0
    fi

    if [[ "${_action:-}" == "add"     ]]
    then
      _render_function_options+=("${_target_selector:-}")

      case "${_request_method:-}" in
        GET)
            _browse_render_add                    \
              "${_render_function_options[@]:-}"  \
              | _browse_respond_with 200          \
                "${_respond_with_200_arguments[@]:-}"
          ;;
        POST)
          local _new_selector=
          _new_selector="$(
            _browse_item_create                   \
              "${_render_function_options[@]:-}"  \
              --message-body "${_message_body:-}"
          )"

          _browse_respond_with 302                \
"//${NB_SERVER_HOST}:${NB_SERVER_PORT}/${_new_selector}${_response_url_params:-}"
          ;;
      esac

      return 0
    fi

    local _selector_path=

    if [[ "${_target_selector}" =~ ^local:  ]]
    then
      if [[ -z "${_local_notebook_path:-}"  ]]
      then
        _browse_respond_with 400

        return 1
      fi

      _selector_path="$(
        cd "${_local_notebook_path:-}"      &&
          __set_notebook_paths              &&
          _show "${_target_selector%%\?*}" --path --no-color 2>&1 || :
      )"
    else
      _selector_path="$(
        _show "${_target_selector%%\?*}" --path 2>/dev/null || :
      )"
    fi

    if [[ -n "${_selector_path:-}"    ]]
    then
      _render_function_options+=("${_selector_path}")
    else
      _browse_respond_with 404

      return 1
    fi

    if [[ -d "${_selector_path:-}"    ]]
    then
      if [[ -n "${_page_number:-}"    ]]
      then
        _render_function_options+=("--page" "${_page_number}")
      fi

      if [[ -n "${_query:-}"          ]]
      then
        _render_function_options+=("--query" "${_query}")
      fi

      _browse_render_container "${_render_function_options[@]:-}"   \
        | _browse_respond_with 200 "${_respond_with_200_arguments[@]:-}"

      return 0
    fi

    local _raw_url="//${NB_SERVER_HOST}:${NB_SERVER_PORT}/--original/"

    if [[ !   "${_selector_path:-}" =~ ^${NB_DIR} ]] &&
       [[ -n  "${_encoded_local_notebook_path:-}" ]] &&
       [[ -n  "${_local_notebook_path:-}"         ]]
    then
      _raw_url+="local/${_selector_path#"${_local_notebook_path}"/}?--local=${_encoded_local_notebook_path}"
    else
      _raw_url+="${_selector_path#"${NB_DIR}"/}"
    fi

    _render_function_options+=("--raw-url" "${_raw_url}")

    if [[ "${_action:-}" == "delete"  ]]
    then
      case "${_request_method:-}" in
        GET)
          _browse_render_delete                 \
            "${_render_function_options[@]:-}"  \
            | _browse_respond_with 200          \
              "${_respond_with_200_arguments[@]:-}"
          ;;
        POST)
          local _container_id_selector=
          _container_id_selector="$(
            _get_id_selector "${_selector_path%/*}" --notebook
          )"

          _browse_item_delete         \
            "${_render_function_options[@]:-}" &>/dev/null

          _browse_respond_with 302    \
"//${NB_SERVER_HOST}:${NB_SERVER_PORT}/${_container_id_selector}${_response_url_params:-}"
          ;;
      esac

      return 0
    elif [[ "${_action:-}" == "edit"  ]]        &&
         _file_is_text "${_selector_path:-}"
    then
      if [[ "${_request_method}"  == "POST"     ]]
      then
        _browse_item_update                     \
          "${_render_function_options[@]:-}"    \
          --message-body "${_message_body:-}"
      fi

      _browse_render_edit                       \
        "${_render_function_options[@]:-}"      \
        | _browse_respond_with 200              \
          "${_respond_with_200_arguments[@]:-}"

      return 0
    else
      _browse_render_item                       \
        "${_render_function_options[@]:-}"      \
        "${_respond_with_200_arguments[@]:-}"

      return 0
    fi

    # fall back to 500 response

    _browse_respond_with 500

    return 1
  }

  # _browse_respond_with()
  #
  # Usage:
  #   _browse_respond_with <status-code> [<path> | <string>] [--headers]
  #                        [--standard-input]
  #
  # Options:
  #   --headers  Only print headers.
  #
  # Description:
  #   Send a response with <status-code> as status and an optional <file>
  #   or <string>.
  #
  # Exit / Error / Return Status:
  #   0 (success, true)  HTTP status 200 or 302.
  #   1 (error,  false)  All others.
  _browse_respond_with() {
    local _only_headers=0
    local _path=
    local _read_from_standard_input=0
    local _serve_original_file=0
    local _status_code="${1:-}"
    local _string=

    local _date=
    _date=$(date +"%a, %d %b %Y %H:%M:%S %Z")

    local _response_headers=(
         "Date: ${_date}"
      "Expires: ${_date}"
       "Server: ${_ME}"
    )

    local __arg=
    for   __arg in "${@:-}"
    do
      case "${__arg:-}" in
        '')
          :
          ;;
        --*header*)
          _only_headers=1
          ;;
        --original)
          _serve_original_file=1
          ;;
        --standard*input)
          _read_from_standard_input=1
          ;;
        *)
          if [[     "${__arg:-}" =~ ^/  ]] &&
             [[ -f  "${__arg:-}"        ]]
          then
            _path="${__arg:-}"
          fi
          ;;
      esac
    done

    if [[ -n "${_path:-}"             ]]
    then
      if _file_is_text "${_path}" && ((_serve_original_file))
      then
        _response_headers+=("Content-Type: text/plain; charset=UTF-8")
      elif [[ "${_path}" =~ \.svg$    ]]
      then
        _response_headers+=("Content-Type: image/svg+xml")
     elif [[ "${_path}" =~ \.js$      ]]
      then
        _response_headers+=("Content-Type: application/javascript")
      else
        if _command_exists "file"
        then
          _response_headers+=("Content-Type: $(file -b --mime-type "${_path}")")
        fi
      fi

      local _content_length=
      _content_length="$(wc -c < "${_path}" | xargs)"

      if [[ -n "${_content_length:-}" ]]
      then
        _response_headers+=("Content-Length: ${_content_length}")
      fi
    elif _contains "${_status_code:-}" "302"
    then
      _only_headers=1
      _response_headers+=("Location: ${2:-}")
    else
      _string="${2:-}"

      _response_headers+=("Content-Type: text/html; charset=UTF-8")
    fi

    printf "%s\\r\\n" \
      "HTTP/1.0 ${_status_code} $(_browse_http_response_message "${_status_code}")"

    local __response_header=
    for   __response_header in "${_response_headers[@]:-}"
    do
      [[ -n "${__response_header:-}"  ]] || continue

      printf "%s\\r\\n" "${__response_header:-}"
    done

    if ! ((_only_headers))
    then
      printf "\\r\\n"

      if ((_read_from_standard_input))
      then
        cat
      elif [[ -n "${_string:-}"     ]]
      then
        printf "%s\\n" "${_string}" | _render
      elif [[ "${_path:-}" =~ ^/    ]]
      then
        cat "${_path}"
      else
        printf                                                            \
          "<div class=\"main\"><h1 class=\"center\">%s %s</h1></div>\\n"  \
          "${_status_code}"                                               \
          "$(_browse_http_response_message "${_status_code}")"            \
          | _render
      fi
    fi

    if _contains "${1:-}" "200" "302"
    then
      return 0
    else
      return 1
    fi
  }

  # _browse_serve()
  #
  # Usage:
  #   _browse_serve
  #
  # Description:
  #   Start the HTTP server in the background.
  _browse_serve() {
    case "${NB_BROWSE_SERVER_TOOL:-}" in
      ncat)
        (
          ncat                                      \
            --exec "${_MY_PATH} browse --respond"   \
            --keep-open                             \
            --listen                                \
            "${NB_SERVER_HOST}" "${NB_SERVER_PORT}" \
            2>/dev/null
        ) &
        ;;
      nc|netcat)
        # TODO: improve concurrency
        (
          while true
          do
            nc                                      \
              --exec "${_MY_PATH} browse --respond" \
              --listen                              \
              --local-port="${NB_SERVER_PORT}"      \
              --source="${NB_SERVER_HOST}"          \
              2>/dev/null
          done
        ) &
        ;;
      socat)
        (
          socat                                                                               \
            tcp-listen:"${NB_SERVER_PORT}",bind="${NB_SERVER_HOST:-localhost}",reuseaddr,fork \
            "system:{ ${_MY_PATH} browse --respond; }"                                        \
            2>/dev/null
        ) &
        ;;
      accept|bash)
        # More info: https://github.com/dzove855/Bash-web-server
        # TODO: improve concurrency

        local _bash_root_path="${BASH%/bin/bash}"

        if [[ -d "${_bash_root_path}/lib/bash"    ]]
        then
          export BASH_LOADABLE_PATH="${_bash_root_path}/lib/bash"
        fi

        if [[ -f "${BASH_LOADABLE_PATH:-}/accept" ]]
        then
          enable -f "${BASH_LOADABLE_PATH%/}/accept" accept ||
            _exit_1 printf "%s\\n" "Could not load accept..."
        fi

        (
          local _server_temp_file=
          _server_temp_file="$(_temp file --touch)"

          while true
          do
            : > "${_server_temp_file:?}"

            (
              accept -r "${NB_SERVER_HOST}" "${NB_SERVER_PORT}" 2>/dev/null

              if [[ -n "${ACCEPT_FD:-}"           ]]
              then
                if [[ -f "${_server_temp_file:?}" ]]
                then
                  printf "1\\n" >> "${_server_temp_file}"
                fi

                "${_MY_PATH}" browse --respond <&"${ACCEPT_FD}" >&"${ACCEPT_FD}"

                exec {ACCEPT_FD}>&- # close connection
              fi
            ) &

            until [[ -s "${_server_temp_file}"    ]]
            do
              :
            done
          done

          if [[ -f "${_server_temp_file:?}"       ]]
          then
            rm "${_server_temp_file:?}"
          fi
        ) &
        ;;
    esac

    local _pid="${!}"

    _temp pid "${_pid}"

    sleep 0.05
  }

  local _action=
  local _browse_columns="${_COLUMNS}"
  local _browse_notebooks=0
  local _browse_limit=
  local _daemon=0
  local _force_terminal_request=0
  local _only_serve=0
  local _open_gui=0
  local _print_browse_render_function=
  local _print_headers=0
  local _print_output=0
  local _search_query=
  local _selector=
  local _subcommand_options=()
  local _target_page=

  while ((${#}))
  do
    case "${1:-}" in
      a|add|-a|--add|--create|--new|+)
        _action="add"
        ;;
      --and)
        [[ -n "${_search_query:-}" ]] && _search_query="${_search_query:-} "

        case "${2:-}" in
          -t|--tag*)
            _search_query+="--and $(_option_get_tags "${2:-}" "${3:-}")"

            shift
            ;;
          *)
            _search_query+="--and ${2:-}"
            ;;
        esac

        shift
        ;;
      --col*)
        _browse_columns="$(_option_get_value "${1:-}" "${2:-}")"

        shift
        ;;
      --*container)
        _print_browse_render_function="container"
        ;;
      --daemon)
        _daemon=1
        _only_serve=1
        ;;
      d|delete|rm|trash|-d|--delete|-)
        _action="delete"
        ;;
      e|edit|-e|--edit)
        _action="edit"
        ;;
      -g|--gui)
        _open_gui=1
        ;;
      --*header)
        _print_browse_render_function="header"
        ;;
      --headers)
        _print_headers=1
        ;;
      --*item)
        _print_browse_render_function="item"
        ;;
      --limit|--num|--number|--per*)
        _browse_limit="$(_option_get_value "${1:-}" "${2:-}")"

        shift
        ;;
      ls|list|--ls|--list)
        : # skip, since this is the default
        ;;
      -n)
        if _option_value_is_present "${2:-}"
        then
          _browse_limit="${2:-}"

          shift
        else
          _browse_notebooks=1
        fi
        ;;
      --notebook*|--nb*)
        _browse_notebooks=1
        ;;
      --or)
        [[ -n "${_search_query:-}" ]] && _search_query="${_search_query:-} "

        case "${2:-}" in
          -t|--tag*)
            _search_query+="--or $(_option_get_tags "${2:-}" "${3:-}")"

            shift
            ;;
          *)
            _search_query+="--or ${2:-}"
            ;;
        esac

        shift
        ;;
      --page)
        _target_page="$(_option_get_value "${1:-}" "${2:-}")"

        shift
        ;;
      -p|--print)
        _print_output=1
        ;;
      --render*add)
        _print_browse_render_function="add"
        _action="add"
        ;;
      --render*delete)
        _print_browse_render_function="delete"
        _action="delete"
        ;;
      --render*edit)
        _print_browse_render_function="edit"
        _action="edit"
        ;;
      --render*notebooks)
        _print_browse_render_function="notebooks"
        ;;
      --respond)
        _browse_respond

        exit 0
        ;;
      --search|search|q|-q|--query)
        if [[ -n "${2:-}" ]]
        then
          _search_query="${2:-}"
        else
          _exit_1 printf                        \
            "%s requires a valid argument.\\n"  \
            "$(_color_primary "${1:-}")"
        fi

        shift
        ;;
      s|serve|-s|--serve*)
        _only_serve=1
        ;;
      -t|--tag*)
        if [[ -n "${_search_query:-}" ]]
        then
          _search_query="${_search_query:-} "
        fi

        _search_query+="$(_option_get_tags "${1:-}" "${2:-}")"

        _subcommand_options+=("${1:-}" "${2:-}")

        shift
        ;;
      --terminal)
        _force_terminal_request=1
        ;;
      -*)
        if [[ "${1:-}" =~ ^-+[0-9]+$  ]]
        then
          _browse_limit="${1##*-}"

          _subcommand_options+=(--limit "${_browse_limit:-}")
        else
          _subcommand_options+=("${1:-}")

          if [[ "${1:-}" =~ ^-- ]] && _option_value_is_present "${2:-}"
          then
            _subcommand_options+=("${2:-}")

            shift
          fi
        fi
        ;;
      *)
        if [[ -z "${_selector:-}"     ]]
        then
          _selector="${1:-}"
        fi
        ;;
    esac

    shift
  done

  if ! ((_browse_notebooks))                                        &&
       [[   "${_print_browse_render_function}"  != "notebooks"  ]]  &&
       [[ ! "${_selector:-}"                    =~ :            ]]
  then
    _selector="$(_notebooks current --name --no-color):${_selector:-}"
  fi

  local _arguments=()

  if ! ((_browse_notebooks))                                        &&
     ! [[ "${_action:-}"                        == "add"        ]]  &&
     ! [[ "${_print_browse_render_function:-}"  == "add"        ]]  &&
     ! [[ "${_print_browse_render_function:-}"  == "notebooks"  ]]
  then
    _arguments+=("$(
      _show "${_selector:-}" --path 2>/dev/null || :
    )")
  fi

  if [[ -z "${NB_BROWSE_SERVER_TOOL:-}" ]]
  then
    _show "${_selector:-}" --render
    _warn cat <<HEREDOC
Install \`ncat\`, GNU \`nc\` / \`netcat\`, \`socat\`, or Bash 5.2+ for full browsing and linking:
$(_color_primary "https://nmap.org/ncat/")
$(_color_primary "https://en.wikipedia.org/wiki/Netcat")
$(_color_primary "http://www.dest-unreach.org/socat/")
HEREDOC

    exit 0
  fi

  # install enabled assets

  if ! ((${NB_TESTING:-0}))
  then
    if ((${NB_ACE_ENABLED:-0}))
    then
      if [[ ! -e "${NB_DIR}/.assets/ace-builds" ]]
      then
        printf "Installing %s%s\\n"         \
          "$(_color_primary "Ace Editor")"  \
          "$(_color_muted "...")"

        _env install --ace
      elif [[ -e "${NB_DIR}/.assets/ace-builds/.git/FETCH_HEAD" ]]
      then
        local _ace_last_modified=
        _ace_last_modified="$(
          _get_last_modified_timestamp "${NB_DIR}/.assets/ace-builds/.git/FETCH_HEAD"
        )"

        local _my_last_modified=
        _my_last_modified="$(
          _get_last_modified_timestamp "${_MY_PATH}"
        )"

        if (( _my_last_modified > _ace_last_modified ))
        then
          printf "Updating %s%s\\n"           \
            "$(_color_primary "Ace Editor")"  \
            "$(_color_muted "...")"

          _env install --ace
        fi
      fi
    fi

    if   ((${NB_MATHJAX_ENABLED:-0})) &&
       [[ ! -e "${NB_DIR}/.assets/MathJax"    ]]
    then
      printf "Installing %s%s\\n"         \
        "$(_color_primary "MathJax")"     \
        "$(_color_muted "...")"

      _env install --mathjax
    elif [[ -e "${NB_DIR}/.assets/MathJax/.git/FETCH_HEAD"      ]]
    then
      local _mathjax_last_modified=
      _mathjax_last_modified="$(
        _get_last_modified_timestamp "${NB_DIR}/.assets/MathJax/.git/FETCH_HEAD"
      )"

      local _my_last_modified=
      _my_last_modified="$(
        _get_last_modified_timestamp "${_MY_PATH}"
      )"

      if (( _my_last_modified > _mathjax_last_modified ))
      then
        printf "Updating %s%s\\n"         \
          "$(_color_primary "MathJax")"   \
          "$(_color_muted "...")"

        _env install --mathjax
      fi
    fi
  fi

  # build initial request URL parameters and arguments

  local _url_params=()

  if _notebooks current --local
  then
    local _encoded_local_path=
    _encoded_local_path="$(_get_uri --encode "$(_notebooks current --path)")"

    _arguments+=("--local" "${_encoded_local_path}")
    _url_params+=("--local=${_encoded_local_path}")
  fi

  if [[ -n "${_search_query:-}" ]]
  then
    _arguments+=("--query" "${_search_query}")

    local _encoded_query=
    _encoded_query="$(_get_uri --encode "${_search_query}")"
    _url_params+=("--query=${_encoded_query}")
  fi

  if [[ -n "${_action:-}"       ]]
  then
    _arguments+=("--${_action}")
    _url_params+=("--${_action}")
  fi

  local i=
  for ((i=0; i < ${#_subcommand_options[@]}; i++))
  do
    [[ -z "${#_subcommand_options[i]}" ]] && continue

    _arguments+=("${_subcommand_options[i]:-}")

    if [[   "${_subcommand_options[i]}"           =~ \--  ]] &&
       [[ ! "${_subcommand_options[$((i+1))]:--}" =~ ^-   ]]
    then
      local _field="${_subcommand_options[i]:-}"
      local _value="${_subcommand_options[$((i+1))]:--}"

      _arguments+=("${_value}")
      _url_params+=("${_field}=$(_get_uri --encode "${_value}")")

      i="$((i+1))"
    else
      _url_params+=("${_subcommand_options[i]:-}")
    fi
  done

  # configure pagination

  if ((_force_terminal_request))  ||
     ! {
        ((_open_gui))             ||
        _web_browser --gui        ||
        ((_only_serve))
     }
  then
    if [[ -z "${_browse_limit:-}"  ]]
    then # set per page based on terminal height
      if [[   "${NB_BROWSER:-}" =~ links  ]]
      then
        _browse_limit="$(($(_tput lines) - 9))"
      elif [[ "${NB_BROWSER:-}" =~ lynx   ]]
      then
        _browse_limit="$(($(_tput lines) - 10))"
      else
        _browse_limit="$(($(_tput lines) - 8))"
      fi
    fi

    if [[ -n "${_browse_limit:-}"  ]]
    then
      _arguments+=("--limit" "${_browse_limit}")
      _arguments+=("--terminal")

      _url_params+=("--limit=${_browse_limit}")
      _url_params+=("--terminal")
    fi

    if [[ -n "${_browse_columns:-}"   ]]
    then
      _arguments+=("--columns" "${_browse_columns}")
      _url_params+=("--columns=${_browse_columns}")
    fi

    if [[ -n "${_target_page:-}"      ]]
    then
      _arguments+=("--page" "${_target_page:-}")
      _url_params+=("--page=${_target_page}")
    fi
  fi

  # build initial request URL

  local _request_url_base="http://${NB_SERVER_HOST}:${NB_SERVER_PORT}"

  if [[ "${_action:-}" == "add" ]]
  then
    local _selector_path=
    _selector_path="$(_show "${_selector:-}" --path 2>/dev/null || :)"

    local _notebook_path=
    _notebook_path="$(_notebooks show "${_selector:-}" --path 2>/dev/null || :)"

    if [[ ! "${_selector}"      =~ /$                     ]] &&
       [[ -d "${_selector_path:-}"                        ]] &&
       [[ "${_selector_path:-}" != "${_notebook_path:-}"  ]]
    then
      _selector="${_selector:-}/"
    fi

    _arguments=("${_selector:-}" "${_arguments[@]:-}")
  fi

  local _request_url_base="http://${NB_SERVER_HOST}:${NB_SERVER_PORT}"
  local _request_url="${_request_url_base}/${_selector:-}"

  if ((${#_url_params[@]}))
  then
    _request_url+="?$(_join "&" "${_url_params[@]:-}")"
  fi

  # call functions directly

  if [[ -n "${_print_browse_render_function:-}" ]]
  then
    case "${_print_browse_render_function:-}" in
      add)        _browse_render_add        "${_arguments[@]:-}" ;;
      container)  _browse_render_container  "${_arguments[@]:-}" ;;
      delete)     _browse_render_delete     "${_arguments[@]:-}" ;;
      edit)       _browse_render_edit       "${_arguments[@]:-}" ;;
      header)     _browse_render_header     "${_arguments[@]:-}" ;;
      item)       _browse_render_item       "${_arguments[@]:-}" ;;
      notebooks)  _browse_render_notebooks  "${_arguments[@]:-}" ;;
    esac

    return 0
  fi

  # start server

  _browse_serve || : # TODO: return status

  # request URL

  if ((_print_output))
  then
    local _retry_counter=0
    local _printable_response=

    while [[ -z "${_printable_response:-}"  ]]
    do
      ((_retry_counter)) && sleep 0.5

      _printable_response="$(
        if ((_print_headers))
        then
          curl -s -I      "${_request_url//' '/%20}"              || :
        else
          _download_from  "${_request_url//' '/%20}" --no-chrome  || :
        fi
      )"

      _retry_counter=$((_retry_counter+1))
    done

    printf "%s\\n" "${_printable_response:-}"
  elif ((_open_gui))  || _web_browser --gui || ((_only_serve))
  then
    local _display_params=

    if _notebooks current --local     ||
       _notebooks current --selected  ||
       [[ "${_selector}" != "$(_notebooks current --name):" ]]
    then
      _display_params="${_request_url#"${_request_url_base}"}"
    fi

    printf "Listening: %s%s\\n"                   \
      "$(_color_primary "${_request_url_base}")"  \
      "${_display_params//\ /%20}"

    if ! ((_only_serve))
    then
      if _web_browser --gui
      then
        _web_browser "${_request_url:-}"
      elif ((_open_gui))
      then
        _open_in_gui_app "${_request_url:-}"
      fi
    fi

    if ((_daemon))
    then
      printf "Press %s%s%s to exit%s" \
        "$(_color_muted "<")"         \
        "$(_color_primary "CTRL-C")"  \
        "$(_color_muted ">")"         \
        "$(_color_muted "...")"

      while true
      do
        sleep 1
      done
    else
      while true
      do
        read -n 1 -s -r -p "Press any key to exit$(_color_muted "...")"

        printf "\\n"

        break
      done
    fi
  else
    _web_browser "${_request_url}"
  fi

  # make a final request to clear any listening process

  (sleep 0.5 && _download_from "${_request_url_base}" --no-chrome &>/dev/null) &

  exit 0
}
_alias_subcommand "browse" "b"
_alias_subcommand "browse" "br"
_alias_subcommand "browse" "browser"

# copy ################################################################### copy

_describe_copy() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} copy ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
          [[<notebook>:][<folder-path>/]<filename>]

$(_color_primary "Description"):
  Copy or duplicate an item.

$(_color_primary "Read More"):
  ${_README_URL}#-moving--renaming

$(_color_primary "See Also"):
  ${_ME} help move

$(_color_primary "Examples"):
  ${_ME} copy 321
  ${_ME} copy 456 example:
  ${_ME} copy 987 sample/demo.md

$(_color_primary "Alias"):
  ${_ME} duplicate
HEREDOC
}
_copy() {
  local _source_selector="${1:-}"
  local _target_selector="${2:-}"

  if [[ -z "${_source_selector:-}" ]]
  then
    _help "copy"

    exit 1
  fi

  local _source_notebook_path=
  _source_notebook_path="$(
    _notebooks show "${_source_selector:-}" --path 2>/dev/null  ||
      _notebooks current --path
  )"

  local _source_relative_path=
  _source_relative_path="$(
    _show "${_source_selector}" --relative-path 2>/dev/null || :
  )"

  local _source_basename="${_source_relative_path##*/}"

  if [[   -z "${_source_relative_path:-}"                         ]] ||
     [[ ! -e "${_source_notebook_path}/${_source_relative_path}"  ]]
  then
    _warn printf "Not found: %s\\n" "$(
      _color_primary "${_source_selector:-}"
    )"

    return 1
  fi

  local _target_folder_path=
  local _target_notebook_path=
  local _target_relative_path=

  if [[ -n "${_target_selector:-}" ]]
  then
    _target_notebook_path="$(
      _notebooks show "${_target_selector:-}" --path 2>/dev/null  ||
        _notebooks current --path
    )"

    local _target_folder_relative_path=
    _target_folder_relative_path="$(
      _selector_resolve_folders "${_target_selector:-}" --build   || :
    )"

    _target_folder_path="${_target_notebook_path:-}/${_target_folder_relative_path:-}"

    _target_relative_path="$(
      _selector_get_identifier "${_target_selector:-}"
    )"

    if [[ -z "${_target_relative_path:-}" ]]
    then
      _target_relative_path="${_source_basename:-}"
    fi

    _target_relative_path="${_target_relative_path%/}"

    if [[ "${_target_selector:-}" =~ /$   ]]
    then
      _target_relative_path="${_target_relative_path:-}/${_source_basename:-}"
    fi

    if [[ -e "${_target_notebook_path:-}/${_target_relative_path:-}"  ]]
    then
      _warn printf "Already exists: %s\\n" "$(
        _color_primary "${_target_selector:-}"
      )"

      return 1
    fi
  else
    _target_notebook_path="$(
      _notebooks show "${_source_selector}" --path 2>/dev/null    ||
        _notebooks current --path
    )"

    _target_relative_path="$(
      _notebooks current --filename "${_source_relative_path}"
    )"

    if [[ "${_target_relative_path:-}" =~ / ]]
    then
      _target_folder_path="${_source_notebook_path}/${_target_relative_path%/*}"
    else
      _target_folder_path="${_source_notebook_path}"
    fi
  fi

  if _show "${_source_notebook_path}/${_source_relative_path}" --type text
  then # Text can use `_add`.
    # Print the source contents and pipe to `_add`:
    _show "${_source_notebook_path}/${_source_relative_path}"     \
      --no-color --print                                          \
      | _add "${_target_notebook_path}/${_target_relative_path}" --no-template
  else
    local _copy_arguments=(
      "${_source_notebook_path}/${_source_relative_path}"
      "${_target_notebook_path}/${_target_relative_path}"
    )

    if [[ -d "${_source_notebook_path}/${_source_relative_path}"  ]]
    then
      _copy_arguments=("-R" "${_copy_arguments[@]:-}")
    fi

    if [[ ! -e "${_target_folder_path:-}"   ]]
    then
      mkdir -p "${_target_folder_path:-}"
    fi

    cp "${_copy_arguments[@]:-}"

    _index add "${_target_relative_path##*/}" "${_target_folder_path}"

    _git checkpoint "${_target_notebook_path:-}" "[${_ME}] Add: ${_target_relative_path}"

    printf "Added: %s\\n" "$(
      _show "${_target_notebook_path}/${_target_relative_path}" --info-line
    )"
  fi
}
_alias_subcommand "copy" "duplicate"

# do ####################################################################### do

_describe_do() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} do ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
        [<task-number>]

$(_color_primary "Description"):
  Mark a todo or task as done.

$(_color_primary "Read More"):
  ${_README_URL}#-todos

$(_color_primary "See Also"):
  ${_ME} help tasks
  ${_ME} help todo
  ${_ME} help undo

$(_color_primary "Examples"):
  ${_ME} do 123
  ${_ME} do example:sample/321
  ${_ME} do 543 7
HEREDOC
}
_do() {
  _todo "do" "${@:-}"
}
_alias_subcommand "do" "done"
_alias_subcommand "do" "close"

# folders ############################################################# folders

_describe_folders() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} folders add [<notebook>:][<folder-path>/]<folder-name>
  ${_ME} folders delete [<notebook>:][<folder-path>/]<folder-name>
  ${_ME} folders <list-options>...

$(_color_primary "Subcommands"):
  (default)  List folders.
  add        Add a new folder.
  delete     Delete a folder.

$(_color_primary "Description"):
  Add, delete, and list folders.

$(_color_primary "Read More"):
  ${_README_URL}#-folders

$(_color_primary "See Also"):
  ${_ME} help add
  ${_ME} help delete
  ${_ME} help list
  ${_ME} help ls

$(_color_primary "Examples"):
  ${_ME} folders
  ${_ME} folders add example
  ${_ME} folders delete example:sample

$(_color_primary "Alias"):
  ${_ME} folder

$(_color_primary "Shortcut Alias"):
  ${_ME} f
HEREDOC
}
_folders() {
  local _arguments=()
  local _selector=
  local _subcommand=

  while ((${#}))
  do
    case "${1:-}" in
      add|a|+)
        _subcommand="add"
        ;;
      delete|d|rm|trash|-)
        _subcommand="delete"
        ;;
      list|ls)
        _subcommand="list"
        ;;
      *)
        if [[ -z "${_selector:-}" ]]
        then
          _selector="${1:-}"
        fi

        _arguments+=("${1:-}")
        ;;
    esac

    shift
  done

  if [[ -z "${_subcommand:-}"     ]]
  then
    _subcommand="list"
  fi

  if [[ -z "${_selector:-}"       ]] &&
     _contains "${_subcommand:-}" "+" "-" "a" "add" "d" "delete" "rm" "trash"
  then
    _help "folders"

    return 1
  fi

  case "${_subcommand:-}" in
    add)
      _add folder "${_arguments[@]:-}"
      ;;
    delete)
      local _target_path=
      _target_path="$(_show "${_selector:-}" --path)"

      if [[ ! -e "${_target_path:-}"    ]]
      then
        _warn printf "Not found: %s\\n"     \
          "$(_color_primary "${_selector:-}")"

        return 1
      elif [[ ! -d "${_target_path:-}"  ]]
      then
        _warn printf "Not a folder: %s\\n"  \
          "$(_color_primary "${_selector:-}")"

        return 1
      fi

      _delete "${_arguments[@]:-}"
      ;;
    list)
      if [[ -n "${_selector:-}"         ]]
      then
        local _selector_path=
        _selector_path="$(_show "${_selector:-}" --path)"

        if [[ -n "${_selector_path:-}"  ]]
        then
          _notebooks select "${_selector_path:-}"
        fi
      fi

      _list --type folder "${_arguments[@]:-}" --with-pinned
      ;;
  esac
}
_alias_subcommand "folders" "f"
_alias_subcommand "folders" "folder"

# helpers ############################################################# helpers

_describe_helpers() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} helpers <name> [<options≥...]

$(_color_primary "Description"):
  Call helper functions.
HEREDOC
}
_helpers() {
  local _name="${1:-}"

  shift

  local _options=("${@:-}")

  case "${_name:-}" in
    *browser*)
      _web_browser                    "${_options[@]:-}"
      ;;
    build*|*related*)
      _build_related_list             "${_options[@]:-}"
      ;;
    *decryption*)
      _get_decryption_tool            "${_options[@]:-}"
      ;;
    decrypt*)
      _decrypt_file                   "${_options[@]:-}"
      ;;
    download*)
      _download_from                  "${_options[@]:-}"
      ;;
    edit*)
      _edit_file                      "${_options[@]:-}"
      ;;
    encrypt*)
      _encrypt_file                   "${_options[@]:-}"
      ;;
    *archive*)
      _file_is_archive                "${_options[@]:-}"
      ;;
    *audio*)
      _file_is_audio                  "${_options[@]:-}"
      ;;
    *bookmark*)
      _file_is_bookmark               "${_options[@]:-}"
      ;;
    *document*)
      _file_is_document               "${_options[@]:-}"
      ;;
    *encrypted*)
      _file_is_encrypted              "${_options[@]:-}"
      ;;
    *image*)
      _file_is_image                  "${_options[@]:-}"
      ;;
    *text*)
      _file_is_text                   "${_options[@]:-}"
      ;;
    *video*)
      _file_is_video                  "${_options[@]:-}"
      ;;
    *content*)
      _get_content                    "${_options[@]:-}"
      ;;
    *d*selector)
      _get_id_selector                "${_options[@]:-}"
      ;;
    *hash*)
      _get_hash                       "${_options[@]:-}"
      ;;
    *http*)
      _get_http_status                "${_options[@]:-}"
      ;;
    *last*mod*)
      _get_last_modified_timestamp    "${_options[@]:-}"
      ;;
    *unique*basename*|*unique*relative*)
      _get_unique_relative_path       "${_options[@]:-}"
      ;;
    *unique*path*)
      _get_unique_path                "${_options[@]:-}"
      ;;
    *highlight*|*syntax*)
      _highlight_syntax_if_available  "${_options[@]:-}"
      ;;
    join)
      _join                           "${_options[@]:-}"
      ;;
    less*|*prompt)
      _less_prompt                    "${_options[@]:-}"
      ;;
    line*wrap*off|unwrap)
      _wrap off                       "${_options[@]:-}"
      ;;
    line*wrap*on|wrap)
      _wrap on                        "${_options[@]:-}"
      ;;
    list*files)
      _list_files                     "${_options[@]:-}"
      ;;
    *line)
      _print_line                     "${_options[@]:-}"
      ;;
    *norm*|*options*)
      _print_normalized_options       "${_options[@]:-}"
      ;;
    *padding)
      _print_padding                  "${_options[@]:-}"
      ;;
    pandoc)
      _pandoc                         "${_options[@]:-}"
      ;;
    *piped*|*input*)
      _piped_input                    "${_options[@]:-}"
      ;;
    *print*welcome|welcome)
      _print_welcome                  "${_options[@]:-}"
      ;;
    *option*|*get*tag*)
      _option_get_tags                "${_options[@]:-}"
      ;;
    render)
      _render                         "${_options[@]:-}"
      ;;
    resolve*links)
      _resolve_links                  "${_options[@]:-}"
      ;;
    *selector*folder*)
      _selector_resolve_folders       "${_options[@]:-}"
      ;;
    *selector*path*)
      _selector_resolve_path          "${_options[@]:-}"
      ;;
    spinner)
      _spinner                        "${_options[@]:-}"
      ;;
    *email)
      _string_is_email                "${_options[@]:-}"
      ;;
    *uri*)
      _get_uri                        "${_options[@]:-}"
      ;;
    *url)
      _string_is_url                  "${_options[@]:-}"
      ;;
    *)
      _exit_1 _help "helpers"
      ;;
  esac
}

# plugins ############################################################# plugins

_describe_plugins() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} plugins [<name>] [--paths]
  ${_ME} plugins install [<path> | <url>] [--force]
  ${_ME} plugins uninstall <name> [--force]

$(_color_primary "Options"):
  --force  Skip the confirmation prompt.
  --paths  Print the full path to each plugin.

$(_color_primary "Subcommands"):
  (default)  List plugins.
  install    Install a plugin from a <path> or <url>.
  uninstall  Uninstall the specified plugin.

$(_color_primary "Description"):
  Manage plugins and themes.

$(_color_primary "Read More"):
  ${_README_URL}#-plugins

$(_color_primary "Plugin Extensions"):
  .${_ME}-theme   Plugins defining color themes.
  .${_ME}-plugin  Plugins defining new subcommands and functionality.

$(_color_primary "See Also"):
  ${_ME} help subcommands

$(_color_primary "Alias"):
  ${_ME} plugin
HEREDOC
}
_plugins() {
  local _basename=
  local _force=0
  local _name=
  local _path=
  local _print_paths=0
  local _subcommand=
  local _url=

  local __arg=
  for   __arg in "${@:-}"
  do
    case "${__arg}" in
      -f|--force|--skip*|-y|--yes)
        _force=1
        ;;
      --path*)
        _print_paths=1
        ;;
      *)
        if [[ "${__arg}" =~ ^install$|^uninstall$ ]]
        then
          _subcommand="${__arg}"
        elif [[ "${_subcommand}" == "install"   ]]
        then
          if [[ "${__arg:-}" =~ (^http|^file\:) ]]
          then
            _url="${__arg}"
          else
            _path="${__arg}"
          fi
        else
          _name="${__arg}"
        fi
        ;;
    esac
  done

  case "${_subcommand}" in
    install)
      [[ ! -e "${NB_DIR}/.plugins"      ]] && mkdir "${NB_DIR}/.plugins"

      if [[ -n "${_path:-}"             ]]
      then
        if ! [[ -f "${_path:-}"         ]] ||
           ! [[ "${_path}" =~ ${_ME}\-  ]]
        then
          _exit_1 printf "Not a valid \`%s\` plugin: %s\\n" "${_ME}" "${_path}"
        fi

        _basename="$(basename -- "${_path}")"

        if [[ -f "${NB_DIR}/.plugins/${_basename}"  ]]
        then
          _warn printf "Plugin already installed: %s\\n" "${_basename}"

          if ! ((_force))
          then
            while true
            do
              local __yn=
              IFS='' read -r -e -d $'\n' -p         \
"$(_color_primary "Reinstall?") $(_color_brackets "y/N") " __yn

              case "${__yn}" in
                [Yy]*)
                  break
                  ;;
                *)
                  printf "Exiting%s\\n" "$(_color_muted "...")"

                  exit 0
                  ;;
              esac
            done
          fi
        fi

        if cp "${_path}" "${NB_DIR}/.plugins/${_basename}"
        then
          printf "Plugin installed:\\n%s\\n"        \
            "$(_color_primary "${NB_DIR}/.plugins/${_basename}")"
        else
          _exit_1 printf "Unable to install plugin: %s\\n" "${_path}"
        fi
      else
        _basename="$(basename -- "${_url}" | tr -d '[:space:]')"

        if [[ "${_url:-}" =~ https\:\/\/github.com ]]
        then
          _url="$(
            printf "%s\\n" "${_url}"  \
              | LC_ALL=C sed          \
                -e 's/\/blob//g'      \
                -e 's/https:\/\/github.com/https:\/\/raw.githubusercontent.com/g'
          )"
        fi

        if _download_from "${_url}" "${NB_DIR}/.plugins/${_basename}" --no-chrome
        then
          printf "Plugin installed:\\n%s\\n"  \
            "$(_color_primary "${NB_DIR}/.plugins/${_basename}")"
        else
          _exit_1 printf "Unable to download and install: %s\\n"  "${_url}"
        fi
      fi
      ;;
    uninstall)
      local _plugin_path=

      if ! _plugin_path="$(_plugins "${_name}" --paths 2>/dev/null)"  ||
           [[ -z "${_plugin_path:-}"  ]]                              ||
         ! [[ -f "${_plugin_path}"    ]]
      then
        _exit_1 printf "Plugin not found: %s\\n" "$(_color_primary "${_name}")"
      fi

      if ! ((_force))
      then
        cat <<HEREDOC
Uninstalling plugin. Warning: This will permanently delete the following file:
$(_color_primary "${_plugin_path}")
HEREDOC
        while true
        do
          local __yn=
          IFS='' read -r -e -d $'\n' -p \
"$(_color_primary "Proceed?") $(_color_brackets "y/N") " __yn

          case "${__yn}" in
            [Yy]*)
              break
              ;;
            *)
              printf "Exiting%s\\n" "$(_color_muted "...")"

              exit 0
              ;;
          esac
        done
      fi

      if [[ -f "${_plugin_path}" ]] && rm "${_plugin_path:?}"
      then
        printf "Plugin successfully uninstalled:\\n%s\\n" \
          "$(_color_primary "${_plugin_path}")"
      else
        _exit_1 printf "Unable to uninstall plugin:\\n%s\\n" "${_plugin_path}"
      fi
      ;;
    *)
      local _query="*${_ME}-*"

      if [[ -n "${_name}" ]]
      then
        _query="${_name}"
      fi

      if [[ ! -e "${NB_DIR}/.plugins" ]]
      then
        (return 1)
      else
        {
          if ((_print_paths))
          then
            find "${NB_DIR}"/.plugins \
              ! \( -type d \)         \
              -name "${_query}"
          else
            find "${NB_DIR}"/.plugins \
              ! \( -type d \)         \
              -name "${_query}"       \
              -exec basename {} \;
          fi
        } | {
          # `grep` for non-0 `find`. More info: https://serverfault.com/a/855083
          grep . | sort
        }
      fi || if [[ -n "${_name:-}" ]]
            then
              _exit_1 printf "No matching plugins found: %s\\n" "${_name}"
            else
              _exit_1 printf "No plugins found.\\n"
            fi
      ;;
  esac
}
_alias_subcommand "plugins" "plugin"

# remote ############################################################### remote

_describe_remote() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} remote
  ${_ME} remote branches [<url>]
  ${_ME} remote delete <branch-name>
  ${_ME} remote remove
  ${_ME} remote rename [<branch-name>] <name>
  ${_ME} remote reset <branch-name>
  ${_ME} remote set <url> [<branch-name>]

$(_color_primary "Subcommands"):
  (default)  Print the remote URL and branch for the notebook.
  branches   List branches on the current or given remote.
  delete     Delete <branch-name> from the remote.
             Caveat: only orphan branches can be deleted.
  remove     Remove the remote URL from the notebook.
             Alias: \`unset\`
  rename     Rename the current orphan branch or <branch-name> to <name>.
             Caveat: only orphan branches can be renamed.
  reset      Reset <branch-name> on the remote to a blank initial state.
  set        Set the remote URL and branch for the notebook.

$(_color_primary "Description"):
  Configure the remote repository URL and branch for the current notebook.

$(_color_primary "Read More"):
  ${_README_URL}#-git-sync
  ${_README_URL}#-revision-history

$(_color_primary "See Also"):
  ${_ME} help history
  ${_ME} help notebooks
  ${_ME} help status
  ${_ME} help sync

$(_color_primary "Examples"):
  ${_ME} remote set https://github.com/example/example.git
  ${_ME} remote remove
  ${_ME} example-notebook:remote set https://github.com/example/example.git
HEREDOC
}
_remote() {
  local _new_branch=
  local _new_remote_url=
  local _only_url=0
  local _remote_branch_name=
  local _rename_arguments=()
  local _skip_confirmation=0
  local _skip_preamble=0
  local _subcommand=

  while ((${#}))
  do
    case "${1:-}" in
      --skip*confirm*)  _skip_confirmation=1    ;;
      --skip*preamble)  _skip_preamble=1        ;;
      --url|url)        _only_url=1             ;;
      *)
        case "${_subcommand:-}" in
          '') _subcommand="${1:-}"              ;;
          add|branches|set)
            if [[   -z "${_new_remote_url:-}"   ]]
            then
              _new_remote_url="${1:-}"
            elif [[ -z "${_new_branch:-}"       ]]
            then
              _new_branch="${1:-}"
            fi
            ;;
          delete|reset|rm|trash)
            _remote_branch_name="${1:-}"
            ;;
          rename)
            _rename_arguments+=("${1:-}")
            ;;
        esac
        ;;
    esac

    shift
  done

  local _notebook_path=
  _notebook_path="$(_notebooks current --path)"

  local _current_branch=
  _current_branch="$(
    git -C "${_notebook_path}" rev-parse --abbrev-ref HEAD
  )"

  local _current_remote_url=
  _current_remote_url="$(
    git -C "${_notebook_path:-}" remote get-url origin 2>/dev/null || :
  )"

  local _remote_exists=0

  if [[ -n "${_current_remote_url:-}"           ]]
  then
    _remote_exists=1
  fi

  case "${_subcommand:-}" in
    branches)
      {
        if [[ -n "${_new_remote_url:-}"         ]]
        then
          git -C "${_notebook_path}" ls-remote  \
            --heads "${_new_remote_url:-}"      \
            2>/dev/null                         \
            | LC_ALL=C sed "s/.*\///g"
        elif ((_remote_exists))
        then
          git -C "${_notebook_path}" ls-remote  \
            --heads                             \
            2>/dev/null                         \
            | LC_ALL=C sed "s/.*\///g"
        else
          _exit_1 printf "No remote configured.\\n"
        fi
      } | {
        local _highlight_matching_branch=0

        if ((_remote_exists))                   &&
           [[ -z  "${_new_remote_url:-}"  ]]    ||
           [[     "${_new_remote_url:-}"  ==    "${_current_remote_url:-}"  ]]
        then
          _highlight_matching_branch=1
        fi

        local         __line=
        while read -r __line
        do
          if ((_highlight_matching_branch))     &&
             [[   "${__line:-}"           ==    "${_current_branch:-}"      ]]
          then
            printf "%s\\n" "$(_color_primary "${__line}")"
          else
            printf "%s\\n" "${__line}"
          fi
        done
      }

      return 0
      ;;
    delete)
      if ! ((_remote_exists))
      then
        _exit_1 printf "No remote configured.\\n"
      fi

      if [[ -z "${_remote_branch_name:-}"       ]]
      then
        _exit_1 _help "remote"
      fi

      # TODO: combine into single `ls-remote` operation
      local _remote_branches=()
      _remote_branches=($(
        git -C "${_notebook_path}" ls-remote        \
          --heads "${_current_remote_url:-}"        \
           2>/dev/null                              \
          | LC_ALL=C sed "s/.*\///g" || :
      ))

      local _primary_remote_branch=
      _primary_remote_branch="$(
        git -C "${_notebook_path}" ls-remote        \
          --symref "${_current_remote_url:-}" HEAD  \
          2>/dev/null                               \
          | awk '/^ref:/ {sub(/refs\/heads\//, "", $2); print $2}' || :
      )"

      if [[ -z "${_remote_branches[*]:-}"       ]] ||
         [[ -z "${_primary_remote_branch:-}"    ]]
      then
        _exit_1 printf "Unable to contact remote.\\n"
      fi

      if ! _contains "${_remote_branch_name:-}" "${_remote_branches[@]:-}"
      then
        _exit_1 printf "Remote branch not found: %s\\n" \
          "${_remote_branch_name:-}"
      fi

      if [[ "${_remote_branch_name:-}" == "${_primary_remote_branch:-}" ]]
      then
        _remote reset "${_remote_branch_name:-}"
      fi

      printf "Deleting remote branch: %s\\n"    \
        "$(_color_primary "${_remote_branch_name:-}")"

      _print_line "-----------------------"

      while true
      do
        local __yn=
        IFS='' read -r -e -d $'\n' -p           \
"$(_color_primary "Proceed?") $(_color_brackets "y/N") " __yn

        case "${__yn}" in
          [Yy]*)
            break
            ;;
          *)
            printf "Exiting%s\\n" "$(_color_muted "...")"

            exit 0
            ;;
        esac
      done

      git -C "${_notebook_path:-}" push origin  \
        ":${_remote_branch_name}"  --force      \
        &>/dev/null                             ||
        _exit_1 printf "Unable to delete remote branch: %s\\n" \
          "${_remote_branch_name}"

      printf "Remote branch deleted.\\n"
      ;;
    remove|rm|unset)
      if ((_remote_exists))
      then
        printf "Removing remote: %s\\n"         \
          "$(_color_primary "${_current_remote_url:-}")"

        if ! ((_skip_confirmation))
        then
          while true
          do
            local __yn=
            IFS='' read -r -e -d $'\n' -p       \
"$(_color_primary "Proceed?") $(_color_brackets "y/N") " __yn

            case "${__yn}" in
              [Yy]*)
                break
                ;;
              *)
                printf "Exiting%s\\n" "$(_color_muted "...")"

                exit 0
                ;;
            esac
          done
        fi

        # TODO: combine into single `ls-remote` operation
        local _remote_branches=()
        _remote_branches=($(
          git -C "${_notebook_path}" ls-remote        \
            --heads "${_current_remote_url:-}"        \
             2>/dev/null                              \
            | LC_ALL=C sed "s/.*\///g" || :
        ))

        local _primary_remote_branch=
        _primary_remote_branch="$(
          git -C "${_notebook_path}" ls-remote        \
            --symref "${_current_remote_url:-}" HEAD  \
            2>/dev/null                               \
            | awk '/^ref:/ {sub(/refs\/heads\//, "", $2); print $2}' || :
        )"

        if [[ -z "${_remote_branches[*]:-}"       ]] ||
           [[ -z "${_primary_remote_branch:-}"    ]]
        then
          _warn printf "Unable to contact remote.\\n"
        else
          local _delete_remote_branch=0

          if _contains "${_current_branch}" "${_remote_branches[@]:-}"
          then
            local _delete_action="Remove"

            if [[ "${_current_branch:-}" == "${_primary_remote_branch:-}" ]]
            then
              _delete_action="Reset"
            fi

            local _branch_delete_prompt=
            _branch_delete_prompt="\
$(_color_primary "${_delete_action} branch on remote?") ($(_color_primary "${_current_branch}"))"

            while true
            do
              local __yn=
              IFS='' read -r -e -d $'\n' -p             \
                "${_branch_delete_prompt} $(_color_brackets "y/N") " __yn

              case "${__yn}" in
                [Yy]*)
                  _delete_remote_branch=1

                  break
                  ;;
                q*|exit)
                  printf "Exiting%s\\n" "$(_color_muted "...")"

                  exit 0
                  ;;
                *)
                  break
                  ;;
              esac
            done
          fi

          if ((_delete_remote_branch))
          then
            if [[ "${_current_branch}" == "${_primary_remote_branch}" ]]
            then
              _remote reset "${_current_branch}"        \
                <<< "y${_NEWLINE}" 1>/dev/null          &&
                printf "Remote branch reset: %s\\n"     \
                  "$(_color_primary "${_current_branch}")"
            else
              _remote delete "${_current_branch}"       \
                <<< "y${_NEWLINE}" 1>/dev/null          &&
                printf "Remote branch deleted: %s\\n"   \
                  "$(_color_primary "${_current_branch}")"
            fi
          fi
        fi

        git -C "${_notebook_path:-}" remote rm origin &&
          printf "Remote removed.\\n"

        return 0
      else
        _exit_1 printf "No remote configured.\\n"
      fi
      ;;
    rename)
      local _target_branch_name=

      local _remote_branches=()

      if ((_remote_exists))
      then
        _remote_branches=($(
          git -C "${_notebook_path}" ls-remote  \
            --heads "${_current_remote_url:-}"  \
            | LC_ALL=C sed "s/.*\///g" || :
        ))

        if [[ -z "${_remote_branches[*]:-}"     ]]
        then
          _exit_1 printf "Unable to contact remote.\\n"
        fi
      fi

      if [[ "${#_rename_arguments[@]}" -gt 1    ]]
      then
        if _contains "${_rename_arguments[0]:-}" "${_remote_branches[@]:-}"
        then
          _remote_branch_name="${_rename_arguments[0]:-}"
          _target_branch_name="${_rename_arguments[1]:-}"
        else
          _exit_1 printf                        \
            "Remote branch not found: %s\\n"    \
            "$(_color_primary "${_rename_arguments[0]:-}")"
        fi
      else
        _target_branch_name="${_rename_arguments[0]:-}"
      fi

      if [[ -z "${_target_branch_name:-}"       ]]
      then
        _exit_1 _help "remote"
      fi

      if _contains "${_target_branch_name:-}" "${_remote_branches[@]:-}"
      then
        _exit_1 printf "A remote branch with that name already exists.\\n"
      fi

      local _remote_head_branch=

      if [[ -n "${_current_remote_url:-}"       ]]
      then
        _remote_head_branch="$(
          git ls-remote --symref "${_current_remote_url:-}" HEAD      \
            | awk '/^ref:/ {sub(/refs\/heads\//, "", $2); print $2}'
        )"
      fi

      if [[ -n  "${_remote_head_branch:-}"                            ]] &&
         [[     "${_remote_branch_name:-"${_current_branch}"}" ==     \
                  "${_remote_head_branch:-}"                          ]]
      then
        _exit_1 printf "Only orphan branches can be renamed.\\n"
      fi

      if [[ -n "${_remote_branch_name:-}"                             ]] &&
         [[    "${_remote_branch_name:-}" != "${_current_branch:-}"   ]]
      then
        printf      "Renaming remote branch\\n"
        _print_line "----------------------"
      else
        printf      "Renaming current branch\\n"
        _print_line "-----------------------"
      fi

      printf        "From: %s\\n" "${_remote_branch_name:-"${_current_branch:-}"}"
      printf        "To:   %s\\n" "$(_color_primary "${_target_branch_name:-}")"

      _print_line   "-----------"

      while true
      do
        local __yn=
        IFS='' read -r -e -d $'\n' -p                     \
"$(_color_primary "Proceed?") $(_color_brackets "y/N") " __yn

        case "${__yn}" in
          [Yy]*)
            break
            ;;
          *)
            printf "Exiting%s\\n" "$(_color_muted "...")"

            exit 0
            ;;
        esac
      done

      if ((_remote_exists))
      then
        if [[   -z  "${_remote_branch_name:-}"                           ]] ||
           [[       "${_remote_branch_name:-}" == "${_current_branch:-}" ]]
        then
          {
            git -C "${_notebook_path}" checkout           \
              -b "${_target_branch_name}"                 \
              "${_current_branch}"                        &&
              git -C "${_notebook_path}" push             \
                -u origin "${_target_branch_name}"        &&
              git -C "${_notebook_path}" branch           \
                -d "${_current_branch}"                   &&
              git -C "${_notebook_path}" push             \
                --delete origin "${_current_branch}"      &&
              git -C "${_notebook_path}" remote prune origin
          } &>/dev/null || _exit_1 printf "Unable to rename branch.\\n"
        elif [[ -n  "${_remote_branch_name:-}"                           ]] &&
             [[     "${_remote_branch_name:-}" != "${_current_branch:-}" ]]
        then
          local _temp_repo_path="${_NB_TEMP_DIRECTORY}/${RANDOM}"

          {
            cd "${_NB_TEMP_DIRECTORY}"                    &&
              git clone --no-local                        \
                --single-branch                           \
                --branch "${_remote_branch_name:-}"       \
                "${_current_remote_url}"                  \
                "${_temp_repo_path}"                      &&
              git -C "${_temp_repo_path}" checkout        \
                -b "${_target_branch_name}"               \
                "${_remote_branch_name}"                  &&
              git -C "${_temp_repo_path}" push            \
                -u origin "${_target_branch_name}"        &&
              git -C "${_temp_repo_path}" branch          \
                -d "${_remote_branch_name}"               &&
              git -C "${_temp_repo_path}" push            \
                --delete origin "${_remote_branch_name}"  &&
              git -C "${_temp_repo_path}" remote prune origin
          } &>/dev/null || _exit_1 printf "Unable to rename branch.\\n"
        fi
      else
        git -C "${_notebook_path}" branch                 \
          -m "${_target_branch_name}"                     \
          &>/dev/null || _exit_1 printf "Unable to rename branch.\\n"
      fi

      printf "Renamed to: %s\\n" "$(_color_primary "${_target_branch_name}")"
      ;;
    reset)
      if ! ((_remote_exists))
      then
        _exit_1 printf "No remote configured.\\n"
      fi

      if [[ -z "${_remote_branch_name:-}"     ]]
      then
        _exit_1 _help "remote"
      fi

      local _remote_branches=()
      _remote_branches=($(
        git -C "${_notebook_path}" ls-remote  \
          --heads "${_current_remote_url:-}"  \
           2>/dev/null                        \
          | LC_ALL=C sed "s/.*\///g" || :
      ))

      if [[ -z "${_remote_branches[*]:-}"     ]]
      then
        _exit_1 printf "Unable to contact remote.\\n"
      fi

      if ! _contains "${_remote_branch_name:-}" "${_remote_branches[@]:-}"
      then
        _exit_1 printf "Remote branch not found: %s\\n" \
          "${_remote_branch_name:-}"
      fi

      printf "Resetting remote branch: %s\\n"           \
        "$(_color_primary "${_remote_branch_name:-}")"

      _print_line "------------------------"

      while true
      do
        local __yn=
        IFS='' read -r -e -d $'\n' -p         \
"$(_color_primary "Proceed?") $(_color_brackets "y/N") " __yn

        case "${__yn}" in
          [Yy]*)
            break
            ;;
          *)
            printf "Exiting%s\\n" "$(_color_muted "...")"

            exit 0
            ;;
        esac
      done

      local _blank_repo_path="${_NB_TEMP_DIRECTORY:-/tmp}/${RANDOM}"

      mkdir -p "${_blank_repo_path}"
      cd "${_blank_repo_path}" || return 1

      {
        git -C "${_blank_repo_path}" init             \
            --initial-branch "${_remote_branch_name}" &&
          touch "${_blank_repo_path}/.index"          &&
          git -C "${_blank_repo_path}" add --all      &&
          git -C "${_blank_repo_path}" commit         \
            -a -m "[${_ME}] Initialize"               &&
          git -C "${_blank_repo_path}" remote add     \
            origin "${_current_remote_url:-}"         &&
          git -C "${_blank_repo_path}" push origin    \
            "${_remote_branch_name}" --force
      } &>/dev/null ||
        _exit_1 printf "Unable to reset remote branch: %s\\n" \
          "$(_color_primary "${_remote_branch_name}")"

      printf "Remote branch reset.\\n"
      ;;
    set|add)
      if [[ -z "${_new_remote_url:-}" ]]
      then
        _exit_1 _help "remote"
      fi

      if [[ -z "${_new_branch:-}"     ]]
      then
        _new_branch="${_current_branch}"
      fi

      if ! ((_skip_preamble))
      then
        if ((_remote_exists))
        then
          printf "Updating remote for: %s\\n" \
            "$(_color_primary "$(_notebooks current --name)")"

          printf "From:   %s (%s)\\n" "${_current_remote_url}" "${_current_branch}"

          _print_line "Updating remote for: $(_notebooks current --name)"
        else
          printf "Adding remote to: %s\\n"    \
            "$(_color_primary "$(_notebooks current --name)")"

          _print_line "Adding remote to: $(_notebooks current --name)"
        fi

        printf "URL:    %s\\n" "$(_color_primary "${_new_remote_url}")"
        printf "Branch: %s\\n" "$(_color_primary "${_new_branch}")"

        _print_line "--------------"

        while true
        do
          local __yn=

          IFS='' read -r -e -d $'\n' -p                               \
            "$(_color_primary "Proceed?") $(_color_brackets "y/N") "  \
            __yn

          case "${__yn:-}" in
            [Yy]*)
              break
              ;;
            *)
              printf "Exiting%s\\n" "$(_color_muted "...")"

              exit 0
              ;;
          esac
        done
      fi

      local _remote_branches=()
      _remote_branches=($(
        git -C "${_notebook_path}" ls-remote    \
          --heads "${_new_remote_url:-}"        \
          | LC_ALL=C sed "s/.*\///g" || :
      ))

      local _selected_push_option=
      local _show_branch_selection_prompt=0
      local _show_branch_name_prompt=1

      if [[ "${#_remote_branches[@]}" -eq 0     ]]
      then
        _selected_push_option=2
        _show_branch_name_prompt=0
      elif ! _contains "${_new_branch}" "${_remote_branches[@]:-}"
      then
        _print_line "--------------"

        cat <<HEREDOC
Branch not present on remote: $(_color_primary "${_new_branch:-}")

$(_color_brackets "1") Merge and sync with an existing remote branch.
$(_color_brackets "2") Sync as a new orphan branch on the remote.

HEREDOC

        while true
        do
          IFS='' read -r -e -d $'\n' -p                                   \
"$(_color_primary "Choose an option") or $(_color_primary "q") to quit: " \
            _selected_push_option

          case "${_selected_push_option:-}" in
            1)
              _show_branch_selection_prompt=1

              break
              ;;
            2)
              break
              ;;
            q*|exit)
              printf "Exiting%s\\n" "$(_color_muted "...")"

              exit 0
              ;;
          esac
        done
      else
        local _temp_repo_path="${_NB_TEMP_DIRECTORY}/${RANDOM}"

        (
          cd "${_NB_TEMP_DIRECTORY}"                            &&
            git clone --no-local                                \
              --single-branch --branch "${_new_branch:-}"       \
              "${_new_remote_url}"                              \
              "${_temp_repo_path}" &>/dev/null
        )

        local _local_branch_root_hash=
        _local_branch_root_hash="$(
          git -C "${_notebook_path}" rev-list --max-parents=0   \
            "${_current_branch}"
        )"

        local _remote_branch_root_hash=
        _remote_branch_root_hash="$(
          git -C "${_temp_repo_path}" rev-list --max-parents=0  \
            "remotes/origin/${_new_branch}"
        )"

        local _remote_branch_commit_hashes=()
        _remote_branch_commit_hashes=($(
          git -C "${_temp_repo_path}" rev-list                  \
            --max-count 3 "remotes/origin/${_new_branch}"
        ))

        local _remote_branch_files=()
        _remote_branch_files=($(
          git -C "${_temp_repo_path}" ls-tree --name-only "origin/${_new_branch}"
        ))

        if [[ "${_local_branch_root_hash:-}"  ==  "${_remote_branch_root_hash:-}" ]]
        then
          _selected_push_option=1
        else
           if [[ "${#_remote_branch_commit_hashes[@]}"  -eq 1         ]]  &&
              [[ "${#_remote_branch_files[@]}"          -eq 1         ]]  &&
              [[ "${_remote_branch_files[0]}"           ==  ".index"  ]]
          then
            _selected_push_option=1
          else
            _print_line "--------------"

            cat <<HEREDOC
Remote branch has existing history: $(_color_primary "${_new_branch:-}")

$(_color_brackets "1") Merge and sync with the existing remote branch: $(_color_primary "${_new_branch:-}")
HEREDOC

            if [[ "${#_remote_branches[@]}" -le 1 ]]
            then
              cat <<HEREDOC
$(_color_brackets "2") Sync as a new orphan branch on the remote.

HEREDOC
            else
              cat <<HEREDOC
$(_color_brackets "2") Merge and sync with a different existing remote branch.
$(_color_brackets "3") Sync as a new orphan branch on the remote.

HEREDOC
            fi

            local _existing_history_prompt_option=

            while true
            do
              IFS='' read -r -e -d $'\n' -p                               \
"$(_color_primary "Choose an option") or $(_color_primary "q") to quit: " \
              _existing_history_prompt_option

              case "${_existing_history_prompt_option:-}" in
                1)
                  _selected_push_option=1

                  break
                  ;;
                2)
                  if [[ "${#_remote_branches[@]}" -le 1 ]]
                  then
                    _selected_push_option=2
                  else
                    _selected_push_option=1
                    _show_branch_selection_prompt=1
                  fi

                  break
                  ;;
                3)
                  _selected_push_option=2

                  break
                  ;;
                q*|exit)
                  printf "Exiting%s\\n" "$(_color_muted "...")"

                  exit 0
                  ;;
              esac
            done
          fi
        fi
      fi

      if ((_show_branch_selection_prompt))
      then
        _print_line "------------------------------"

        printf "Remote branches:\\n\\n"

        local i=
        for ((i=0; i < ${#_remote_branches[@]}; i++))
        do
          printf "%s %s\\n"                       \
            "$(_color_brackets "$((i+1))")"       \
            "${_remote_branches[${i}]:-}"
        done

        printf "\\n"

        local _selected_branch=

        while true
        do
          IFS='' read -r -e -d $'\n' -p                                               \
            "$(_color_primary "Choose a branch") or $(_color_primary "q") to quit: "  \
            _selected_branch

          case "${_selected_branch:-}" in
            q*|exit)
              printf "Exiting%s\\n" "$(_color_muted "...")"

              exit 0
              ;;
            [0-9]*)
              if [[ -n "${_remote_branches[$((_selected_branch - 1))]:-}" ]]
              then
                _new_branch="${_remote_branches[$((_selected_branch - 1))]:-}"

                break
              fi
              ;;
          esac
        done
      fi

      if [[ "${_selected_push_option:-}" == "2"               ]]
      then
        local _target_orphan_branch_name="${_new_branch}"

        if _contains "${_new_branch}" "${_remote_branches[@]:-}"
        then
          if [[ "${_new_branch:-}" == "${_current_branch:-}"  ]]
          then
            local _notebook_name_branch_name="${_notebook_path##*/}"
            _notebook_name_branch_name="${_notebook_name_branch_name//' '/-}"
            _notebook_name_branch_name="$(
              printf "%s\\n" "${_notebook_name_branch_name}"  \
                | tr '[:upper:]' '[:lower:]'
            )"
          fi

          local _uniqueness_counter=0
          local _unique_branch_name="${_notebook_name_branch_name}"

          while _contains "${_unique_branch_name}" "${_remote_branches[@]:-}"
          do
            _uniqueness_counter="$((_uniqueness_counter+1))"

            printf -v _unique_branch_name -- "%s-%01d"        \
              "${_notebook_name_branch_name}"                 \
              "${_uniqueness_counter}"
          done

          _target_orphan_branch_name="${_unique_branch_name}"
        fi

        if ! ((_show_branch_name_prompt))
        then
          _new_branch="${_target_orphan_branch_name}"
        else
          _print_line "------------------------------"

          local _bk_name=  && _bk_name="$(_color_brackets "${_target_orphan_branch_name}")"
          local _hi_enter= && _hi_enter="$(_color_primary 'enter')"
          local _hi_q=     && _hi_q="$(_color_primary 'q')"
          local _hi_type=  && _hi_type="$(_color_primary 'type')"

          cat <<HEREDOC
Press ${_hi_enter} to use the selected name, ${_hi_type} a new name, or press ${_hi_q} to quit.

HEREDOC

          while true
          do
            local _orphan_branch_prompt_response=

            IFS='' read -r -e -d $'\n' -p                     \
              "Name ${_bk_name}: "                            \
              _orphan_branch_prompt_response

            case "${_orphan_branch_prompt_response:-}" in
              '')
                _new_branch="${_target_orphan_branch_name}"

                break
                ;;
              q*|exit)
                printf "Exiting%s\\n" "$(_color_muted "...")"

                exit 0
                ;;
              *)
                _new_branch="${_orphan_branch_prompt_response}"

                break
                ;;
            esac
          done
        fi
      fi

      if [[ "${_new_branch:-}" != "${_current_branch:-}"      ]]
      then
        git -C "${_notebook_path}" branch -m "${_new_branch:-}"
      fi

      if ((_remote_exists))
      then
        _print_line "--------------"
        _remote unset --skip-confirmation
        _print_line "---------------"
      fi

      git -C "${_notebook_path}" remote add origin "${_new_remote_url}" ||
        return 1

      _git sync "${_notebook_path}" --skip-prompt

      local _updated_current_branch=
      _updated_current_branch="$(
        git -C "${_notebook_path}" rev-parse --abbrev-ref HEAD
      )"

      local __local_branch=
      for   __local_branch in $(git -C "${_notebook_path}" branch --all)
      do
        if [[   "${__local_branch:-}" =~ ^\ \ remotes/              ]] &&
           [[ ! "${__local_branch:-}" =~ ^\ \ remotes/origin/HEAD   ]] &&
           [[ ! "${__local_branch:-}" =~ ^\ \ remotes/origin/${_updated_current_branch}$ ]]
        then
          git -C "${_notebook_path}" branch               \
            --delete --remotes "${__local_branch#\ \ remotes/}" &>/dev/null
        fi
      done

      local _updated_remote_url=
      _updated_remote_url="$(
        git -C "${_notebook_path}" remote get-url origin 2>/dev/null
      )"

      printf "Remote set to: %s (%s)\\n"                  \
        "$(_color_primary "${_updated_remote_url}")"      \
        "$(_color_primary "${_updated_current_branch}")"

      return 0
      ;;
    *)
      if ((_remote_exists))
      then
        if ((_only_url))
        then
          printf "%s\\n" "${_current_remote_url:-}"
        else
          printf "%s (%s)\\n" "${_current_remote_url:-}" "${_current_branch:-}"
        fi
      else
        _warn printf "No remote configured.\\n"

        return 1
      fi
      ;;
  esac
}

# settings ########################################################### settings

_describe_settings() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} set [<name> [<value>] | <number> [<value>]]
  ${_ME} settings colors [<number> | themes]
  ${_ME} settings edit
  ${_ME} settings get   (<name> | <number>)
  ${_ME} settings list  [--long]
  ${_ME} settings set   (<name> | <number>) <value>
  ${_ME} settings show  (<name> | <number>)
  ${_ME} settings unset (<name> | <number>)

$(_color_primary "Subcommands"):
  (default)  Open the settings prompt, to <name> or <number>, if present.
             When <value> is also present, assign <value> to the setting.
  colors     Print a table of available colors and their xterm color numbers.
             When <number> is provided, print the number in its color.
             \`settings colors themes\` prints a list of installed themes.
  edit       Open the \`${_ME}\` configuration file in \`\$EDITOR\`.
  get        Print the value of a setting.
  list       List information about available settings.
  set        Assign <value> to a setting.
  show       Print the help information and current value of a setting.
  unset      Unset a setting, returning it to the default value.

$(_color_primary "Description"):
  Configure \`${_ME}\`. Use \`${_ME} settings set\` to customize a setting and
  \`${_ME} settings unset\` to restore the default for a setting.

  Use the \`${_ME} set\` alias to quickly assign values to settings:

    ${_ME} set color_theme blacklight
    ${_ME} set limit 40

$(_color_primary "Read More"):
  ${_README_URL}#%EF%B8%8F-set--settings

$(_color_primary "See Also"):
  ${_ME} help unset

$(_color_primary "Examples"):
  ${_ME} settings
  ${_ME} set 5 "org"
  ${_ME} set color_primary 105
  ${_ME} set unset color_primary
  ${_ME} set color_secondary unset
  ${_ME} settings colors
  ${_ME} settings colors 105
  ${_ME} set limit 15

$(_color_primary "Alias"):
  ${_ME} set
HEREDOC
}
_settings() {
  # Usage: _settings_colors [<number>] [themes]
  _settings_colors() {
    # Usage: _settings_colors_print <number>
    _settings_colors_print() {
      printf '\e[38;5;%dm %3d ' "${1:-}" "${1:-}"
    }

    if [[   -n  "${1:-}"              ]]
    then
      if [[     "${1}" == "themes"    ]]
      then
        printf "%s\\n" "${_NB_COLOR_THEMES[@]}"
      else
        if [[ ! "${1}" =~ [[:digit:]] ]]
        then
          _exit_1 printf "Usage: %s settings colors [<number> | themes]\\n" "${_ME}"
        fi

        _settings_colors_print "${1:-}"

        printf "\\n"
      fi
    else
      local i=
      for ((i=0; i < 256; i++))
      do
        if ((i)) && ! ((i % 16))
        then
          printf "\\n"
        fi

        _settings_colors_print "${i}"
      done

      printf "\\n"
    fi
  }

  # Usage: _settings_get_value (<number> | <name>)
  _settings_get_value() {
    local _setting_name=
    _setting_name="$(_settings_identify "${1:-}")"

    _env | grep "^${_setting_name}=" | cut -d= -f2
  }

  # Usage: _settings_identify [--id] (<number> | <name>)
  _settings_identify() {
    local _get_id=0
    local _id_or_name=

    case "${1:-}" in
      '')
        return 1
        ;;
      --id)
        _get_id=1

        if [[ -n "${2:-}" ]]
        then
          _id_or_name="${2:-}"
        else
          return 1
        fi
        ;;
      *)
        _id_or_name="${1}"
        ;;
    esac

    case "${_id_or_name}" in
      1|*auto*|*AUTO*|*sync*|*SYNC*)
        ((_get_id)) && printf "1"   || printf "NB_AUTO_SYNC"

        return 0
        ;;
      2|*primary*|*PRIMARY*)
        ((_get_id)) && printf "2"   || printf "NB_COLOR_PRIMARY"

        return 0
        ;;
      3|*secondary*|*SECONDARY*)
        ((_get_id)) && printf "3"   || printf "NB_COLOR_SECONDARY"

        return 0
        ;;
      4|*color*theme*|*COLOR*THEME*|*scheme*|theme*)
        ((_get_id)) && printf "4"   || printf "NB_COLOR_THEME"

        return 0
        ;;
      5|*ext*|*EXT*)
        ((_get_id)) && printf "5"   || printf "NB_DEFAULT_EXTENSION"

        return 0
        ;;
      6|*editor*|*EDITOR*)
        ((_get_id)) && printf "6"   || printf "EDITOR"

        return 0
        ;;
      7|*encrypt*|*ENCRYPT*)
        ((_get_id)) && printf "7"   || printf "NB_ENCRYPTION_TOOL"

        return 0
        ;;
      8|*footer*|*FOOTER*)
        ((_get_id)) && printf "8"   || printf "NB_FOOTER"

        return 0
        ;;
      9|*header*|*HEADER*)
        ((_get_id)) && printf "9"   || printf "NB_HEADER"

        return 0
        ;;
      10|*limit*|*LIMIT*)
        ((_get_id)) && printf "10"  || printf "NB_LIMIT"

        return 0
        ;;
      11|*dir*|*DIR*)
        ((_get_id)) && printf "11"  || printf "NB_DIR"

        return 0
        ;;
      12|*syntax*|*SYNTAX*)
        ((_get_id)) && printf "12"  || printf "NB_SYNTAX_THEME"

        return 0
        ;;
      *)
        _warn                                   \
          printf "Setting not found: %s\\n"     \
          "$(_color_primary "${_id_or_name}")"  &&
            return 1
        ;;
    esac
  }

  # Usage: _settings_prompt [<id> | <name>]
  _settings_prompt() {
    local _setting_name="${1:-}"

    local _padding=
    _padding="$(_print_padding "-----------" "${_COLUMNS}")"

    printf "%s%s Settings\\n" "${_padding}" "$(_color_primary "${_ME}")"
    _print_line "$(printf "%-${_COLUMNS}s" '.')"

    if [[ -n "${_setting_name}" ]]
    then
      _setting_name="$(_settings_identify "${_setting_name}")"
    else
      cat <<HEREDOC
$(_settings list)

Enter the number or name of the setting to change, or $(_color_primary 'q') to quit.
HEREDOC

      while true
      do
        local __setting=
        IFS='' read -r -e -d $'\n' -p \
"$(_color_primary "Number or Name: ")" __setting

        if [[ -n "${__setting}" ]]
        then
          case "${__setting}" in
            q|quit|exit)
              printf "Exiting%s\\n" "$(_color_muted "...")"

              return 0
              ;;
            *)
              _setting_name="$(
                _settings_identify "${__setting}"
              )" && break
              ;;
          esac
        fi
      done
    fi

    printf "\\n"

    if [[ "${_setting_name}" == "NB_COLOR_PRIMARY"    ]] ||
       [[ "${_setting_name}" == "NB_COLOR_SECONDARY"  ]]
    then
      printf "%s\\n\\n" "$(_settings_colors)"
    fi

    _settings show "${_setting_name}"

    local _hi_unset= && _hi_unset="$(_color_primary 'unset')"
    local _hi_q=     && _hi_q="$(_color_primary 'q')"

    cat <<HEREDOC

Enter a new value, ${_hi_unset} to set to the default value, or ${_hi_q} to quit.
HEREDOC

    while true
    do
      local __value=
      IFS='' read -r -e -d $'\n' -p "$(_color_primary "Value: ")" __value

      if [[ -n "${__value}" ]]
      then
        case "${__value}" in
          q|quit|exit)
            printf "Exiting%s\\n" "$(_color_muted "...")"

            return 0
            ;;
          unset|default|reset)
            _settings_unset "${_setting_name}"              || continue

            break
            ;;
          *)
            _settings_set   "${_setting_name}" "${__value}" || continue

            break
            ;;
        esac
      fi
    done
  }

  # Usage: _settings_set (<number> | <name>) <value>
  _settings_set() {
    local _entry=
    local _value="${2:-}"

    local _setting_name=
    _setting_name="$(_settings_identify "${1:-}")"

    if _contains "${2:-}" "unset" "default" "reset"
    then
      _settings_unset "${_setting_name}"

      return 0
    fi

    _settings_validate_value "${_setting_name}" "${2:-}"    || return 1

    if [[ "${_value:-}"       =~ ^~       ]]
    then
      # shellcheck disable=SC2016
      _value="$(printf "%s\\n" "${_value}" | LC_ALL=C sed "s|~|${HOME}|g")"
    fi

    local _attribution=
    _attribution="# Set by \`${_ME}\` • $(date)"

    if [[ "${_setting_name}"  == "EDITOR" ]]
    then
      _entry="export ${_setting_name}=\"${_value}\" ${_attribution}"
    else
      _entry="export ${_setting_name}=\"\${${_setting_name}:-${_value}}\" ${_attribution}"
    fi

    _settings_unset "${_setting_name}" > /dev/null 2>&1     || return 1

    printf "\\n%s\\n" "${_entry}" >> "${NBRC_PATH}"

    if [[   "${_setting_name}" == "NB_COLOR_PRIMARY"    ]]  ||
       [[   "${_setting_name}" == "NB_COLOR_SECONDARY"  ]]
    then
      _setting_name="$(_tput setaf "${_value}")${_setting_name}${_TPUT_SGR0}"
      _value="$(_tput setaf "${_value}")${_value}${_TPUT_SGR0}"
    elif [[ "${_setting_name}" == "NB_COLOR_THEME"      ]]
    then
      local _new_color=
      _new_color="$(
        NB_COLOR_THEME="${_value}" NB_COLOR_PRIMARY=''  \
          "${_MY_PATH}" settings get NB_COLOR_PRIMARY
      )"

      _setting_name="$(_tput setaf "${_new_color}")${_setting_name}${_TPUT_SGR0}"
      _value="$(_tput setaf "${_new_color}")${_value}${_TPUT_SGR0}"
    else
      _setting_name="$(_color_primary "${_setting_name}")"
      _value="$(_color_primary "${_value}")"
    fi

    printf "%s set to %s\\n" "${_setting_name}" "${_value}"
  }

  # Usage: _settings_unset (<number> | <name>)
  _settings_unset() {
    local _setting_name=
    _setting_name="$(_settings_identify "${1:-}")"

    _sed_i                                              \
      -e "/^export ${_setting_name}.*Added by.*$/d"     \
      -e "/^export ${_setting_name}.*Set by.*$/d"       \
      "${NBRC_PATH}"

    local _stripped=
    _stripped=$(<"${NBRC_PATH}")

    printf "%s\\n" "${_stripped}" > "${NBRC_PATH}"

    local _default_value=
    _default_value="$(
      eval "${_setting_name}='' \"${_MY_PATH}\" settings get ${_setting_name}"
    )"

    if [[   "${_setting_name}" == "NB_COLOR_SECONDARY"  ]]
    then
      _setting_name="$(_color_primary "${_setting_name}")"
      _default_value="$(_tput setaf "${_default_value}")${_default_value}${_TPUT_SGR0}"
    elif [[ "${_setting_name}" == "NB_COLOR_PRIMARY"    ]]
    then
      _setting_name="$(_tput setaf "${_default_value}")${_setting_name}${_TPUT_SGR0}"
      _default_value="$(_tput setaf "${_default_value}")${_default_value}${_TPUT_SGR0}"
    elif [[ "${_setting_name}" == "NB_COLOR_THEME"      ]]
    then
      _new_hi_color="$(
        NB_COLOR_THEME="${_ME}" NB_COLOR_PRIMARY=''     \
          "${_MY_PATH}" settings get NB_COLOR_PRIMARY
      )"

      _setting_name="$(_tput setaf "${_new_hi_color}")${_setting_name}${_TPUT_SGR0}"
      _default_value="$(_tput setaf "${_new_hi_color}")${_default_value}${_TPUT_SGR0}"
    else
      _setting_name="$(_color_primary "${_setting_name}")"
      _default_value="$(_color_primary "${_default_value}")"
    fi

    printf "%s restored to the default: %s\\n"          \
      "${_setting_name}"                                \
      "${_default_value}"
  }

  # Usage: _settings_validate_value (<number> | <name>) <value>
  _settings_validate_value() {
    if [[ "${1:-}" == 'EDITOR'                ]]  ||
       [[ "${1:-}" == 'NB_DEFAULT_EXTENSION'  ]]
    then
      if [[ -n "${2:-}"                       ]]
      then
        return 0
      else
        _warn printf                \
          "%s requires a value.\\n" \
          "${1:-}"

        return 1
      fi
    elif [[ "${1:-}" == 'NB_AUTO_SYNC'        ]]  ||
         [[ "${1:-}" == 'NB_FOOTER'           ]]
    then
      if [[ "${2:-}" =~ (^0$|^1$)             ]]
      then
        return 0
      else
        _warn printf                              \
          "%s must be either \"0\" or \"1\".\\n"  \
          "${1}"

        return 1
      fi
    elif [[ "${1:-}" == 'NB_HEADER'           ]]
    then
      if [[ "${2:-}" =~ (^0$|^1$|^2$|^3$)     ]]
      then
        return 0
      else
        _warn printf                                      \
          "%s must be \"0\", \"1\", \"2\", or \"3\".\\n"  \
          "${1}"

        return 1
      fi
    elif [[ "${1:-}" == 'NB_LIMIT'                ]]
    then
      if [[ "${2:-}" =~ ^[0-9]+$                  ]]  ||
         [[ "${2:-}" =~ ^auto$                    ]]  ||
         [[ "${2:-}" =~ ^auto[+|-][0-9]+$         ]]  ||
         [[ "${2:-}" =~ ^auto[+|-][0-9]+\^[0-9]+$ ]]  ||
         [[ "${2:-}" =~ ^auto\^[0-9]+$            ]]
      then
        return 0
      else
        _warn printf                                                                                \
"%s must be a number or valid \"auto\" value.\\n"  \
"${1}"

        return 1
      fi
    elif [[ "${1:-}" == 'NB_DIR'              ]]
    then
      if [[ -z  "${2:-}"                      ]]  ||
         [[ "${2}"   == "/"                   ]]  ||
         {
           [[   -e "${2}"                     ]]  &&
           [[ ! -w "${2}"                     ]]
         }
      then
        _warn printf                                      \
          "\"%s\" is not a valid location for NB_DIR.\\n" \
          "${2:-}"

        return 1
      fi
    elif [[ "${1:-}" == 'NB_ENCRYPTION_TOOL'  ]]
    then
      if [[ "${2:-}" =~ (^openssl$|^gpg$)     ]]
      then
        return 0
      else
        _warn printf \
          "NB_ENCRYPTION_TOOL must be either \"openssl\" or \"gpg\".\\n"

          return 1
      fi
    elif [[ "${1:-}" == 'NB_COLOR_PRIMARY'    ]]  ||
         [[ "${1:-}" == 'NB_COLOR_SECONDARY'  ]]
    then
      if [[ "${2:-}" =~ ^[0-9]                ]]
      then
        return 0
      else
        _warn printf                \
          "%s must be a number.\\n" \
          "${1}"

        return 1
      fi
    elif [[ "${1:-}" == 'NB_COLOR_THEME'      ]]
    then
      if _contains "${2:-}" "${_NB_COLOR_THEMES[@]}"
      then
        return 0
      else
        _warn printf                                    \
          "%s must be one of the available themes.\\n"  \
          "${1}"

        return 1
      fi
    elif [[ "${1:-}" == 'NB_SYNTAX_THEME'     ]]
    then
      if ! _bat --command-exists
      then
        printf "bat required: https://github.com/sharkdp/bat\\n"
      elif [[ -z "${2:-}"                     ]]
      then
        return 1
      else
        local _theme_list=
        _theme_list=($(_bat --list-themes --color never))

        local __theme=
        for   __theme in "${_theme_list[@]}"
        do
          if [[ "${2}" =~ \(                  ]]
          then
            if [[ "${2}" == "${__theme:-}"    ]]
            then
              return 0
            fi
          elif [[ "${2}" =~ ^${__theme%% (*}  ]]
          then
            return 0
          fi
        done

        _warn printf                                    \
          "%s must be one of the available themes.\\n"  \
          "${1}"

        return 1
      fi
    else
      return 0
    fi
  }

  local _settings_list_items=()
  local _settings_help_items=()

  _settings_list_items+=("$(_color_brackets '1')  auto_sync")
  _settings_help_items+=("\
    $(_color_secondary " ---------")
     By default, operations that trigger a git commit like \`add\`, \`edit\`,
     and \`delete\` will sync notebook changes to the remote repository, if
     the notebook's remote is set. To disable this behavior, set this to \"0\".

     • Default Value: $(_color_primary "1")")

  _settings_list_items+=("$(_color_brackets '2')  color_primary")
  _settings_help_items+=("\
    $(_color_secondary " -------------")
     The primary color used to highlight identifiers and messages.

     • Supported Values: xterm color numbers 0 through 255.
     • Default Value:    $(_color_primary "68") (blue) for 256 color terminals,
                         $(_color_primary "4")  (blue) for  8  color terminals.")

  _settings_list_items+=("$(_color_brackets '3')  color_secondary")
  _settings_help_items+=("\
    $(_color_secondary " ---------------")
     The color used for lines and footer elements.

     • Supported Values: xterm color numbers 0 through 255.
     • Default Value:    $(_color_primary "8")")

  _settings_list_items+=("$(_color_brackets '4')  color_theme")
  _settings_help_items+=("\
    $(_color_secondary " -----------")
     The color theme.

     To view screenshots of the built-in themes, visit:

         $(_color_primary "https://git.io/nb-docs-color-themes")

     \`${_ME}\` supports custom, user-defined themes. To learn more, run:

         $(_color_primary "${_ME} help --colors")

     To change the syntax highlighting theme, use:

         $(_color_primary "${_ME} set syntax_theme")

     • Available themes:

$(
  local __theme=
  for   __theme in "${_NB_COLOR_THEMES[@]}"
  do
    printf "         %s\\n" "$(_color_primary "${__theme}")"
  done
)

     • Default Value: $(_color_primary "${_ME}")")

  _settings_list_items+=("$(_color_brackets '5')  default_extension")
  _settings_help_items+=("\
    $(_color_secondary " -----------------")
     The default extension to use for note files. Change to \"org\" for Emacs
     Org mode files, \"rst\" for reStructuredText, \"txt\" for plain text, or
     whatever you prefer.

     • Default Value: $(_color_primary "md")")

  _settings_list_items+=("$(_color_brackets '6')  editor")
  _settings_help_items+=("\
    $(_color_secondary " ------")
     The command line text editor used by \`${_ME}\`.

     • Example Values:

$(
  local __editor=
  for   __editor in atom code emacs hx macdown mate micro nano pico subl vi vim
  do
    if _command_exists "${__editor}"
    then
      printf "         %s\\n" "$(_color_primary "${__editor}")"
    fi
  done
)")

  _settings_list_items+=("$(_color_brackets '7')  encryption_tool")
  _settings_help_items+=("\
    $(_color_secondary " ---------------")
     The tool used for encrypting notes.

     • Supported Values: $(_color_primary "openssl"), $(_color_primary "gpg")
     • Default Value:    $(_color_primary "openssl")")

  _settings_list_items+=("$(_color_brackets '8')  footer")
  _settings_help_items+=("\
    $(_color_secondary " ------")
     By default, \`${_ME}\` and \`${_ME} ls\` include a footer with example commands.
     To hide this footer, set this to \"0\".

     • Default Value: $(_color_primary "1")")

  _settings_list_items+=("$(_color_brackets '9')  header")
  _settings_help_items+=("\
    $(_color_secondary " ------")
     By default, \`${_ME}\` and \`${_ME} ls\` include a header listing available notebooks.
     Set the alignment, or hide the header with \"0\".

     • Supported Values:

       $(_color_primary "0")  Hide Header
       $(_color_primary "1")  Dynamic Alignment
            - Left justified when list is shorter than terminal width.
            - Center aligned when list is longer than terminal width.
       $(_color_primary "2")  Center Aligned (default)
       $(_color_primary "3")  Left Justified

     • Default Value: $(_color_primary "2")")

  _settings_list_items+=("$(_color_brackets '10') limit")
  _settings_help_items+=("\
    $(_color_secondary " -----")
     The maximum number of items included in the \`${_ME}\` and \`${_ME} ls\` lists.
     Set to \`auto\` to automatically limit output to the current terminal height.
     Set a maximum auto limit with \`auto^<max>\`, e.g., \`auto^15\`.
     Subtract an auto limit offset for multiline prompts with \`auto-<offset>\`.
     Add an auto limit offet with \`auto+<offset>\`.
     Combine both modifiers with \`auto-<offset>^<max>\` or \`auto+<offset>^<max>\`.

     • Example Values:

       15
       auto
       auto^15
       auto-2
       auto+2
       auto-2^15
       auto+2^15

     • Default Value: $(_color_primary "15")")

  _settings_list_items+=("$(_color_brackets '11') nb_dir")
  _settings_help_items+=("\
    $(_color_secondary " ------")
     The location of the directory that contains the notebooks.

     For example, to sync all notebooks with Dropbox, create a folder at
     \`~/Dropbox/Notes\` and run: \`${_ME} settings set nb_dir ~/Dropbox/Notes\`

     • Default Value: $(_color_primary "~/.${_ME}")")

  _settings_list_items+=("$(_color_brackets '12') syntax_theme")
  _settings_help_items+=("\
    $(_color_secondary " ------------")
     The syntax highlighting theme. View examples with:

         $(_color_primary "${_BAT_COMMAND} --list-themes")

$(
  if ! _bat --command-exists
  then
    printf "     Install \`bat\` to enable themes: https://github.com/sharkdp/bat\\n"
  else
    printf "     • Available themes:\\n"
    printf "\\n"

    local __theme=
    for   __theme in $(_bat --list-themes --color never)
    do
      printf "         %s\\n" "$(_color_primary "${__theme}")"
    done
  fi
)

     • Default Value: $(_color_primary 'base16')")

  while ((${#}))
  do
    case "${1:-}" in
      color|colors)
        _settings_colors "${2:-}"

        return 0
        ;;
      edit)
        _edit_file "${NBRC_PATH}" --no-wait

        return 0
        ;;
      get)
        if [[ -z  "${2:-}"              ]]
        then
          _exit_1 _help settings
        fi

        _settings_get_value "${2:-}"

        return 0
        ;;
      list)
        if [[     "${2:-}" == "--long"  ]]
        then
          local _counter=0

          local __setting=
          for   __setting in "${_settings_list_items[@]}"
          do
            ((_counter)) && printf "\\n"
            _counter="$((_counter+1))"

            _settings show "${_counter}"
          done
        else
          printf "%s\\n" "${_settings_list_items[@]}"
        fi

        return 0
        ;;
      set)
        if [[ -z "${2:-}" ]] || [[ -z "${3:-}" ]]
        then
          _exit_1 _help "settings"
        fi

        _settings_set "${2:-}" "${3:-}"

        return 0
        ;;
      show|help|about|info|more)
        if [[ -z "${2:-}" ]]
        then
          _exit_1 _help "settings"
        fi

        local _setting_id=
        _setting_id="$(_settings_identify --id "${2:-}")"

        local _setting_name=
        _setting_name="$(_settings_identify "${2:-}")"

        local _index=
        _index="$((_setting_id-1))"

        printf "%s\\n%s\\n"                       \
          "${_settings_list_items[${_index}]}"    \
          "${_settings_help_items[${_index}]}"

        printf "\\n%s is currently set to %s\\n"  \
          "$(_color_primary "${_setting_name}")"  \
          "$(_color_primary "$(_settings_get_value "${_setting_name}")")"

        return 0
        ;;
      reset|unset)
        if [[ -z "${2:-}" ]]
        then
          _exit_1 _help "settings"
        fi

        _settings_unset "${2:-}"

        return 0
        ;;
      *)
        local _setting_name=

        case "${1:-}" in
          '')       :                                             ;;
          remote)   shift; _remote set "${@}"; return 0           ;;
          *)        _setting_name="$(_settings_identify "${1}")"  ;;
        esac

        if [[   -n "${_setting_name:-}" ]]
        then
          if [[ -n "${2:-}"             ]]
          then
            _settings_set "${_setting_name}" "${2}"
          else
            _settings_prompt "${_setting_name}"
          fi
        else
          _settings_prompt
        fi

        return 0
        ;;
    esac

    shift
  done
}
_alias_subcommand "settings" "config"
_alias_subcommand "settings" "set"

# shell ################################################################# shell

_describe_shell() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} shell [<subcommand> [<options>...] | --clear-history]

$(_color_primary "Options"):
  --clear-history  Clear the \`${_ME}\` shell history.

$(_color_primary "Description"):
  Start the \`${_ME}\` interactive shell. Type "exit" to exit.

  \`${_ME} shell\` recognizes all \`${_ME}\` subcommands and options, providing
  a streamlined, distraction-free approach for working with \`${_ME}\`.

  When <subcommand> is present, the command will run as the shell is opened.

$(_color_primary "Read More"):
  ${_README_URL}#-interactive-shell

$(_color_primary "See Also"):
  ${_ME} help run

$(_color_primary "Example"):
  $ ${_ME} shell
  ${_ME}> ls 3
  [3] Example

  ${_ME}> edit 3 --content "New content."
  Updated [3] Example

  ${_ME}> notebook
  home

  ${_ME}> exit
  $
HEREDOC
}
_shell() {
  HISTFILE="${NB_HIST:-${HOME}/.${_ME}_history}"
  set -o history

  local _initial_command=
  local _prompt=
  _prompt="$(_color_primary "${_ME}")$(_color_secondary "${_CHEVRON_RIGHT}") "

  local __arg=
  for   __arg in "${@:-}"
  do
    case "${__arg}" in
      --clear-history)
        if [[ -e "${HISTFILE}"  ]]
        then
          rm "${HISTFILE:?}"

          printf "History cleared.\\n"

          return 0
        fi
        ;;
      *)
        if [[ -n "${__arg}"     ]]
        then
          _initial_command+=" ${__arg}"
        fi
        ;;
    esac
  done

  printf "%s" "${_TPUT_COLOR_PRIMARY}"
  cat <<HEREDOC
__          _
\ \   _ __ | |__
 \ \ | '_ \| '_ \\
 / / | | | | |_) |
/_/  |_| |_|_.__/
$(_color_secondary "------------------")
$(_color_primary "${_ME} shell") started. Enter $(_color_primary "ls") to list notes and notebooks.
Enter $(_color_primary "help") for usage information. Enter $(_color_primary "exit") to exit.
HEREDOC

  if [[ -n "${_initial_command:-}"            ]]
  then
    eval "\"${_MY_PATH}\" ${_initial_command}"
  fi

  local __input=
  while IFS='' read -r -e -d $'\n' -p "${_prompt}" __input
  do
    history -s "${__input}"

    if [[ "${__input}" =~ (^exit$|^quit$|^q$) ]]
    then
      return 0
    elif [[ "${__input}" =~ ^clear$           ]]
    then
      clear
    else
      # Strip leading 'n', 'nb', or 'notes'.
      local _normalized_input=
      _normalized_input="$(
        printf "%s\\n" "${__input}"           \
          | LC_ALL=C sed -e 's/^n$//'         \
          | LC_ALL=C sed -e 's/^n //'         \
          | LC_ALL=C sed -e 's/^nb$//'        \
          | LC_ALL=C sed -e 's/^nb //'        \
          | LC_ALL=C sed -e 's/^notes$//'     \
          | LC_ALL=C sed -e 's/^notes //'
      )"

      local _command_name=

      if [[ "${_normalized_input}" =~ ^help   ]] ||
         [[ "${_normalized_input}" =~ ^help\  ]] ||
         [[ "${_normalized_input}" =~ ^h$     ]] ||
         [[ "${_normalized_input}" =~ ^h\     ]]
      then
        eval "\"${_MY_PATH}\" ${_normalized_input}" --shell   || :
      elif [[ "${_normalized_input}" =~ ^use|^notebooks\ use  ]]
      then
        eval "_${_normalized_input}"
      elif [[ "${_normalized_input}" =~ ^echo\ .*   ]]        ||
           [[ "${_normalized_input}" =~ ^printf\ .* ]]
      then
        eval "${_normalized_input}"
      elif _command_name="$(
        printf "%s\\n" "${_normalized_input}" \
          | grep                              \
              --only-matching                 \
              -e '^code'                      \
              -e '^emacs'                     \
              -e '^gvim'                      \
              -e '^hx'                        \
              -e '^macdown'                   \
              -e '^mate'                      \
              -e '^mvim'                      \
              -e '^nano'                      \
              -e '^nvim'                      \
              -e '^subl'                      \
              -e '^vim'
      )"
      then
        _normalized_input="$(
          printf "%s\\n" "${_normalized_input}"     \
            | LC_ALL=C sed -e "s/^${_command_name} //"
        )"

        eval "\"${_MY_PATH}\" edit --editor \"${_command_name}\" ${_normalized_input}"
      else
        eval "\"${_MY_PATH}\" ${_normalized_input}" || :
      fi
    fi
  done
}

# status ############################################################### status

_describe_status() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} status [<notebook>]

$(_color_primary "Description"):
  Print archival, git, and remote status for the current notebook or <notebook>.

$(_color_primary "Read More"):
  ${_README_URL}#-git-sync
  ${_README_URL}#-revision-history

$(_color_primary "See Also"):
  ${_ME} help archive
  ${_ME} help history
  ${_ME} help notebooks
  ${_ME} help remote
  ${_ME} help sync
  ${_ME} help unarchive

$(_color_primary "Examples"):
  ${_ME} status
  ${_ME} status example

$(_color_primary "Shortcut Alias"):
  ${_ME} st
HEREDOC
}
_status() {
  local _notebook_name="${1%%:*}"
  local _notebook_path=

  if [[   -n "${_notebook_name:-}" ]]
  then
    _notebook_path="$(
      _notebooks show "${_notebook_name:-}" --path 2>/dev/null || :
    )"

    if [[ -z "${_notebook_path:-}" ]]
    then
      _warn printf "Notebook not found: %s\\n" \
        "$(_color_primary "${_notebook_name:-}")"

      return 1
    fi
  else
    _notebook_name="$(_notebooks current --name)"
    _notebook_path="$(_notebooks current --path)"
  fi

  _notebooks select "${_notebook_path}"

  printf "%s\\n" "$(_color_primary "${_notebook_name}")"
  _print_line "${_notebook_name}"

  printf "status: "

  if [[ "$(_notebooks status "${_notebook_name}")" =~ not\ archived ]]
  then
    printf "unarchived\\n"
  else
    printf "archived\\n"
  fi

  printf "remote: "

  _remote 2>/dev/null || printf "none\\n"

  printf "git:    "

  local _git_status_files=
  _git_status_files="$(git -C "${_notebook_path}" status --porcelain)"

  if [[ -n "${_git_status_files:-}" ]]
  then
    printf "dirty\\n\\nchanges\\n"

    _print_line "changes"

    git -C "${_notebook_path}" status --porcelain
  else
    printf "clean\\n"
  fi
}
_alias_subcommand "status" "st"
_alias_subcommand "status" "stat"

# sync ################################################################### sync

_describe_sync() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} sync [-a | --all]

$(_color_primary "Options"):
  -a, --all   Sync all unarchived notebooks.

$(_color_primary "Description"):
  Sync the current notebook with its remote.

$(_color_primary "Private Repositories and Git Credentials"):
  Syncing with private repositories requires configuring git to not prompt
  for credentials.

  For repositories cloned over HTTPS, credentials can be cached with git.
  For repositories cloned over SSH, keys can be added to the ssh-agent.

  More Information:
    ${_README_URL}#private-repositories-and-git-credentials

$(_color_primary "Sync Conflict Resolution"):
  When \`${_ME} sync\` encounters a conflict in a text file and can't merge
  overlapping local and remote changes, both versions are saved in the
  file, separated by git conflict markers. Use \`${_ME} edit\` to remove the
  conflict markers and delete any unwanted text.

  When \`${_ME} sync\` encounters a conflict in a binary file, such as an
  encrypted note or bookmark, both versions of the file are saved in the
  notebook as individual files, one with \`--conflicted-copy\` appended to
  the filename.

  More Information:
    ${_README_URL}#sync-conflict-resolution

$(_color_primary "Read More"):
  ${_README_URL}#-git-sync
  ${_README_URL}#-revision-history

$(_color_primary "See Also"):
  ${_ME} help history
  ${_ME} help notebooks
  ${_ME} help remote
  ${_ME} help status

$(_color_primary "Examples"):
  ${_ME} sync
  ${_ME} sync --all
HEREDOC
}
_sync() {
  local _notebooks=()
  local _sync_all=0

  if [[ "${1:-}" =~ (^-a$|^--all$) ]]
  then
    _sync_all=1

    local _notebook_names=()
    _notebooks=($(_notebooks --names --no-color --unarchived))
  else
    _notebooks=($(_notebooks current))
  fi

  local _sync_successful=0
  local _sync_started=0
  local _syncable_count=0

  local __notebook=
  for   __notebook in "${_notebooks[@]:-}"
  do
    if [[ "${__notebook}" == "local"      ]] &&
       [[ -n "${_LOCAL_NOTEBOOK_PATH:-}"  ]]
    then
      NB_NOTEBOOK_PATH="${_LOCAL_NOTEBOOK_PATH}"
    else
      NB_NOTEBOOK_PATH="${NB_DIR}/${__notebook}"
    fi

    if ((_sync_all))
    then
      _remote &>/dev/null || continue
    else
      _remote 1>/dev/null || {
        cat <<HEREDOC

Set the remote for the current notebook:

  $(_color_primary "${_ME} remote set <url>")

Set the remote for a notebook named "example":

  $(_color_primary "${_ME} example:remote set <url>")

HEREDOC

        return 1
      }
    fi

    if ! ((_sync_started))
    then
      printf "Syncing: "
      _sync_started=1
    fi

    printf "%s..." "$(_color_primary "${__notebook}")"

    local _notebook_sync_successful=0

    _syncable_count="$((_syncable_count+1))"

    if ((_sync_all))
    then # sync without prompt in background
      GIT_TERMINAL_PROMPT=0 NB_AUTO_SYNC=1 \
        _git checkpoint "${NB_NOTEBOOK_PATH}" "[${_ME}] Sync" --wait
    else # sync with prompt in foreground
      GIT_TERMINAL_PROMPT=1 NB_AUTO_SYNC=0 \
        _git checkpoint "${NB_NOTEBOOK_PATH}" "[${_ME}] Sync" --wait

      _git sync "${NB_NOTEBOOK_PATH}"

      if ! _index verify "${NB_NOTEBOOK_PATH}" &>/dev/null
      then
        _index reconcile "${NB_NOTEBOOK_PATH}" --commit

        while [[ -n "$(git -C "${NB_NOTEBOOK_PATH}" status --porcelain)" ]]
        do
          sleep 1
        done

        _git sync "${NB_NOTEBOOK_PATH}"
      fi
    fi && _notebook_sync_successful=1

    if ! ((_notebook_sync_successful))            ||
       _git dirty           "${NB_NOTEBOOK_PATH}" ||
       _git out_of_sync     "${NB_NOTEBOOK_PATH}"
    then
      _exit_1 cat <<HEREDOC
Sync failed.

Reason unknown, but likely one of the following:

- Authentication error or credentials not configured.
- Network unavailable.
- Misconfigured remote URL.

Configuring Git Credentials:
  ${_README_URL}#private-repositories-and-git-credentials
HEREDOC
    fi
  done && ((_syncable_count)) && _sync_successful=1

  if ((_sync_successful))
  then
    printf "Done!\\n"
  elif ! ((_syncable_count))
  then
    _exit_1 cat <<HEREDOC
No unarchived notebooks with remotes found.

Set the remote for the current notebook:

  $(_color_primary "${_ME} remote set <url>")

Set the remote for a notebook named "example":

  $(_color_primary "${_ME} example:remote set <url>")

HEREDOC
  else
    printf "\\n"

    _exit_1 printf "Sync failed.\\n"
  fi
}

# tasks ################################################################# tasks

_describe_tasks() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} tasks ([<notebook>:][<folder-path>/][<id> | <filename> | <description>])
           [open | closed] [--pager]

$(_color_primary "Options"):
  --pager  Display output in the pager.

$(_color_primary "Description"):
  List tasks in todos, notebooks, folders, and other items.

$(_color_primary "Read More"):
  ${_README_URL}#%EF%B8%8F-tasks
  ${_README_URL}#-todos

$(_color_primary "See Also"):
  ${_ME} help do
  ${_ME} help todo
  ${_ME} help undo

$(_color_primary "Examples"):
  ${_ME} tasks
  ${_ME} tasks open
  ${_ME} tasks closed
  ${_ME} tasks 123
  ${_ME} example:tasks open
  ${_ME} tasks closed sample/
  ${_ME} tasks closed demo:456

$(_color_primary "Shortcut Alias"):
  ${_ME} t
HEREDOC
}
_tasks() {
  _todo "tasks" "${@:-}"
}
_alias_subcommand "tasks" "task"

# todo ################################################################### todo

_describe_todo() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} todo add [<notebook>:][<folder-path>/][<filename>] <title>
              [--description <description>] [--due <date>]
              [-r (<url> | <selector>) | --related (<url> | <selector>)]
              [--tags <tag1>,<tag2>...] [--task <title>...]
  ${_ME} todo delete ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
  ${_ME} todo do   ([<notebook>:][<folder-path>/][<id> | <filename> | <description>])
               [<task-number>]
  ${_ME} todo undo ([<notebook>:][<folder-path>/][<id> | <filename> | <description>])
               [<task-number>]
  ${_ME} todos [<notebook>:][<folder-path>/] [open | closed] [--pager]
               [--tags <tag1>,<tag2>...]
  ${_ME} todos tasks ([<notebook>:][<folder-path>/][<id> | <filename> | <description>])
                 [open | closed] [--pager]

$(_color_primary "Options"):
  --description <description>         Description for the todo.
  --due <date>                        Due date and / or time for the todo.
  --pager                             Display output in the pager.
  -r, --related (<url> | <selector>)  Related URL or selector.
  --tags <tag1>,<tag2>...             Comma-separated list of tags.
  --task <title>                      Task to add to the tasklist.

$(_color_primary "Subcommands"):
  (default)   List todos.
  add         Add a new todo.
              Shortcut Aliases: \`${_ME} todo a\`, \`${_ME} todo +\`
  delete      Delete a todo.
              Shortcut Alias: \`${_ME} todo -\`
  do          Mark a todo or task as done.
  tasks       List tasks in todos, notebooks, folders, and other item.
  undo        Unmark a todo or task as done.

$(_color_primary "Description"):
  Manage todos and tasks.

$(_color_primary "Read More:"):
  ${_README_URL}#-todos

$(_color_primary "See Also"):
  ${_ME} help do
  ${_ME} help tasks
  ${_ME} help undo

$(_color_primary "Examples"):
  ${_ME} todo add "Example todo title."
  ${_ME} todo add Example todo title.
  ${_ME} todo add "Sample title." --tags tag1,tag2 --related demo:567
  ${_ME} todos
  ${_ME} todos open
  ${_ME} todos closed
  ${_ME} example:todos open
  ${_ME} todos closed sample/

$(_color_primary "Alias"):
  ${_ME} todos

$(_color_primary "Shortcut Alias"):
  ${_ME} to
HEREDOC
}
_todo() {
  # Usage: _todo_get_task <path> <task-number>
  _todo_get_task() {
    local _counter=0
    local _item_path="${1:?}"
    local _task_number="${2:?}"

    {
      cat "${_item_path:-}"
    } | {
      local         __line=
      while read -r __line
      do
        if [[ "${__line}" =~ (\-\ \[\]|\-\ \[\ \]|\-\ \[\x\]) ]]
        then
          _counter="$((_counter+1))"

          if [[ "${_counter:-}" == "${_task_number:-}" ]]
          then
            printf "%s\\n" "${__line}"

            return 0
          fi
        fi
      done

      return 1
    }
  }

  # Usage: _todo_update_task <path> <number> <action>
  _todo_update_task() {
    local _action="${3:?}"
    local _counter=0
    local _item_path="${1:?}"
    local _task_number="${2:?}"

    local _temp_file_path=
    _temp_file_path="$(_temp file)"

    case "${_action:-}" in
      do)   local _replacement_box="- [x]" ;;
      undo) local _replacement_box="- [ ]" ;;
    esac

    {
      cat "${_item_path:-}"
    } | {
      local         __line=
      while read -r __line
      do
        if [[ "${__line}" =~ (\-\ \[\]|\-\ \[\ \]|\-\ \[\x\]) ]]
        then
          _counter="$((_counter+1))"

          if [[ "${_counter:-}" ==  "${_task_number:-}"     ]]
          then
            printf "%s\\n" "${__line}"                      \
              | LC_ALL=C sed                                \
                  -e "s/- \[\]/${_replacement_box}/"        \
                  -e "s/- \[ \]/${_replacement_box}/"       \
                  -e "s/- \[x\]/${_replacement_box}/"
          else
            printf "%s\\n" "${__line}"
          fi
        else
          printf "%s\\n" "${__line}"
        fi
      done

      if [[ "${_task_number:-}" -gt "${_counter:-}"         ]]
      then
        _exit_1 printf "Task not found.\\n"
      fi
    } | {
      cat > "${_temp_file_path}"
    }

    cat "${_temp_file_path}"  > "${_item_path}"

    [[ -f "${_temp_file_path:?}" ]] && rm -rf "${_temp_file_path:?}"
  }

  local _action=
  local _arguments=()
  local _description=
  local _due_datetime=
  local _filter=
  local _maybe_title_arguments=()
  local _only_todos=0
  local _option_title=
  local _related_identifiers=()
  local _tag_list_with_commas=
  local _tag_list_with_spaces=
  local _tags=()
  local _task_list_options=()
  local _tasks=()
  local _use_pager=0

  while ((${#}))
  do
    case "${1:-}" in
      --description)
        _description="$(_option_get_value "${1:-}" "${2:-}")"

        shift
        ;;
      --due)
        _due_datetime="$(_option_get_value "${1:-}" "${2:-}")"

        shift
        ;;
      --pager|--less)
        _use_pager=1
        ;;
      --recursive|--tree)
        _task_list_options+=("--recursive")
        ;;
      -r|--via|--also|--related)
        _related_identifiers+=("$(_option_get_value "${1:-}" "${2:-}")")

        shift
        ;;
      --tag*|\#*)
        [[ -n "${_tag_list_with_commas:-}"  ]] && _tag_list_with_commas+=","
        [[ -n "${_tag_list_with_spaces:-}"  ]] && _tag_list_with_spaces+=" "

        if [[ "${1:-}" =~ ^-- ]]
        then
          _tag_list_with_commas+="$(_option_get_tags "${1}" "${2:-}")"
          _tag_list_with_spaces+="$(_option_get_tags "${1}" "${2:-}")"
          _tags+=("${2:-}")

          shift
        else
          _tag_list_with_commas+="${1:-}"
          _tag_list_with_spaces+="${1:-}"
          _tags+=("${1:-}")
        fi
        ;;
      --task)
        _tasks+=("$(_option_get_value "${1:-}" "${2:-}")")

        shift
        ;;
      --title)
        _option_title="$(_option_get_value "${1:-}" "${2:-}")"

        shift
        ;;
      *)
        if [[ "${_action:-}" == "add"       ]]
        then
          case "${1:-}" in
            --edit) _arguments+=("${1:-}")  ;;
            -*)
              _arguments+=("${1:-}")

              if _option_value_is_present "${2:-}"
              then
                _arguments+=("${2:-}")

                shift
              fi
              ;;
            *)
              _maybe_title_arguments+=("${1:-}")
              ;;
          esac
        fi

        case "${1:-}" in
          add|+|a)
            if [[ -z "${_action:-}"     ]]  ||  [[ "${_action:-}" == "tasks" ]]
            then
              _action="add"
            fi
            ;;
          c|closed|checked|completed|done|finished)
            _filter="closed"
            ;;
          delete|remove|rm|trash|-)
            if [[ -z "${2:-}" ]]
            then
              _help "todo"

              return 1
            fi

            _delete "${2:-}" "${3:-}"

            return 0
            ;;
          d|do|close|complete|finish|check)
            if [[ -z "${_action:-}"     ]]  ||  [[ "${_action:-}" == "tasks" ]]
            then
              _action="do"
            fi
            ;;
          l|list)
            if [[ -z "${_action:-}"     ]]
            then
              _action="list"
            fi
            ;;
          o|open|incomplete|unchecked|undone|unfinished)
            _filter="open"
            ;;
          tasks)
            if [[ -z "${_action:-}"     ]]
            then
              _action="tasks"
            fi
            ;;
          todos)
            _only_todos=1
            ;;
          u|undo|uncomplete|unfinish|uncheck)
            if [[ -z "${_action:-}"     ]]  ||  [[ "${_action:-}" == "tasks" ]]
            then
              _action="undo"
            fi
            ;;
          *)
            [[ "${_action:-}" != "add"  ]]  &&  _arguments+=("${1:-}")
            ;;
        esac
        ;;
    esac

    shift
  done

  if [[ -z "${_action:-}" ]]
  then
    _action="list"
  fi

  if [[ "${_SUBCOMMAND:-}"  == "t"      ]]  &&
     [[ "${_action:-}"      == "list"   ]]  &&
     ! ((_only_todos))
  then
    _action="tasks"
  fi

  case "${_action:-}" in
    add)
      local _first=1
      local _title=

      local __argument=
      for   __argument in "${_maybe_title_arguments[@]:-}"
      do
        if ((_first))
        then
          if [[ "${__argument:-}" =~ (:$|/$) ]]
          then
            _arguments+=("${__argument}")
          else
            _title+="${__argument}"
          fi

          _first=0
        else
          [[ -n "${_title:-}"       ]] && _title+=" "

          _title+="${__argument}"
        fi
      done

      if [[ -n "${_option_title:-}" ]]
      then
        if [[ -n "${_title:-}"      ]]
        then
          _title="${_option_title} ${_MD} ${_title}"
        else
          _title="${_option_title}"
        fi
      fi

      if [[ -z "${_title:-}"        ]]
      then
        _exit_1 _help "todo"
      fi

      local _todo_content="# [ ] ${_title:-}${_NEWLINE}"

      if [[ -n "${_due_datetime:-}" ]]
      then
        _todo_content+="${_NEWLINE}## Due${_NEWLINE}"
        _todo_content+="${_NEWLINE}${_due_datetime:-}${_NEWLINE}"
      fi

      if [[ -n "${_description:-}"  ]]
      then
        _todo_content+="${_NEWLINE}## Description${_NEWLINE}"
        _todo_content+="${_NEWLINE}${_description}${_NEWLINE}"
      fi

      if ((${#_tasks[@]}))
      then
        _todo_content+="${_NEWLINE}## Tasks${_NEWLINE}${_NEWLINE}"

        local __task=
        for   __task in "${_tasks[@]:-}"
        do
          _todo_content+="- [ ] ${__task}${_NEWLINE}"
        done
      fi

      if ((${#_related_identifiers[@]}))
      then
        _todo_content+="${_NEWLINE}## Related${_NEWLINE}${_NEWLINE}"
        _todo_content+="$(_build_related_list "${_related_identifiers[@]:-}")"
        _todo_content+="${_NEWLINE}"
      fi

      if [[ -n "${_tag_list_with_spaces:-}" ]]
      then
        _todo_content+="${_NEWLINE}## Tags${_NEWLINE}"
        _todo_content+="${_NEWLINE}${_tag_list_with_spaces}${_NEWLINE}"
      fi

      _add                                  \
        --content "${_todo_content:-}"      \
        --type    "todo.md"                 \
        --no-template                       \
        "${_arguments[@]:-}"
      ;;
    do|undo)
      local _selector="${_arguments[0]:-}"
      local _task_number="${_arguments[1]:-}"

      if [[ -z "${_selector:-}"         ]]
      then
        _exit_1 _help "todo"
      fi

      local _selector_path=
      _selector_path="$(_show "${_selector:-}" --path 2>/dev/null || :)"

      if [[ -z "${_selector_path:-}"    ]]
      then
        _exit_1 printf "Todo not found.\\n"
      fi

      local _notebook_path=
      _notebook_path="$(
        _notebooks show "${_selector:-}" --path 2>/dev/null ||
          _notebooks current --path 2>/dev/null
      )"

      if [[ !  "${_selector_path}" =~ todo\.md$   ]]        &&
         [[ -z "${_task_number:-}"                ]]
      then
        _exit_1 printf "Not a todo.\\n"
      fi

      case "${_action:-}" in
        do)
          if [[ -n "${_task_number:-}"  ]]
          then
            _todo_update_task "${_selector_path:-}" "${_task_number:-}" "do"

            local _updated_task=
            _updated_task="$(
              _todo_get_task "${_selector_path:-}" "${_task_number:-}"
            )"

            if [[ ! "${_updated_task:-}" =~ ^[[:space:]]*-\ \[x\] ]]
            then
              _warn cat "${_selector_path}"
              _exit_1 printf                      \
                "Unable to mark done: %s\\n"      \
                "$(_todos tasks "${_selector:-}" "${_task_number}")"
            else
              _todos tasks "${_selector:-}" "${_task_number}"     \
                | LC_ALL=C sed "3s/^/Done: /"

              _git checkpoint "${_notebook_path}" \
                "[${_ME}] Task Done: $(_show "${_selector:-}" --relative-path) ${_task_number}"
            fi
          else
            _sed_i -e "s/# \[ \]/# \[x\]/" "${_selector_path}"

            if ! grep -q "# \[x\]" "${_selector_path}"
            then
              _exit_1 printf                      \
                "Unable to mark done: %s\\n"      \
                "$(_color_primary "${_selector:-}")"
            else
              printf "Done: %s\\n" "$(_list "${_selector}")"

              _git checkpoint "${_notebook_path}" \
                "[${_ME}] Done: $(_show "${_selector:-}" --relative-path)"
            fi
          fi
          ;;
        undo)
          if [[ -n "${_task_number:-}"            ]]
          then
            _todo_update_task "${_selector_path}" "${_task_number:-}" "undo"

            local _updated_task=
            _updated_task="$(
              _todo_get_task "${_selector_path:-}" "${_task_number:-}"
            )"

            if [[ ! "${_updated_task:-}" =~ ^[[:space:]]*-\ \[\ \]  ]]
            then
              _exit_1 printf                      \
                "Unable to undo: %s\\n"           \
                "$(_todos tasks "${_selector:-}" "${_task_number}")"
            else
              _todos tasks "${_selector:-}" "${_task_number}"       \
                | LC_ALL=C sed "3s/^/Undone: /"

              _git checkpoint "${_notebook_path}" \
                "[${_ME}] Task Undone: $(_show "${_selector:-}" --relative-path) ${_task_number}"
            fi
          else
            _sed_i -e "s/# \[x\]/# \[ \]/" "${_selector_path}"

            if ! grep -q "# \[ \]" "${_selector_path}"
            then
              _exit_1 printf                      \
                "Unable to undo: %s\\n"           \
                "$(_color_primary "${_selector:-}")"
            else
              printf "Undone: %s\\n" "$(_list "${_selector}")"

              _git checkpoint "${_notebook_path}" \
                "[${_ME}] Undone: $(_show "${_selector:-}" --relative-path)"
            fi
          fi
          ;;
      esac
      ;;
    list)
      {
        if [[ -n "${_tag_list_with_commas:-}"   ]]
        then
          _search                               \
            "${_arguments[@]:-}"                \
            --tags "${_tag_list_with_commas:-}" \
            --type todo                         \
            --list 2>/dev/null
        else
          _list                   \
            "${_arguments[@]:-}"  \
            --error-on-empty      \
            --type todo           \
            2>/dev/null
        fi
      } | {
        case "${_filter:-}" in
          closed)
            LC_ALL=C sed -E -e "/${NB_INDICATOR_TODO:-} .*\[\ \].*/d"
            ;;
          open)
            LC_ALL=C sed -E -e "/${NB_INDICATOR_TODO_DONE:-} .*\[.*x.*\].*/d"
            ;;
          *)
            cat
            ;;
        esac
      } | {
        local _counter=0

        local         __line=
        while read -r __line
        do
          _counter=$((_counter+1))

          printf "%s\\n" "${__line:-}"
        done

        if ! ((_counter))
        then
          local _empty_message="No"

          if [[ -n "${_filter:-}"     ]]
          then
            _empty_message+=" ${_filter:-}"
          fi

          _exit_1 printf "%s todos found.\\n" "${_empty_message}"
        fi
      }
      ;;
    tasks)
      local _selector="${_arguments[0]:-}"
      local _task_number="${_arguments[1]:-}"

      local _maybe_padded_empty_qualifier=

      if [[ -n "${_filter:-}"         ]]
      then
        _maybe_padded_empty_qualifier="${_filter:-} "
      elif [[ -n "${_task_number:-}"  ]]
      then
        _maybe_padded_empty_qualifier="matching "
      fi

      local _notebook_path=
      local _selector_path=

      if [[ -n "${_selector:-}"       ]]
      then
        _notebook_path="$(
          _notebooks _show "${_selector:-}" --path 2>/dev/null ||
            _notebooks current --path
        )"

        _selector_path="$(
          _show "${_selector:-}" --path 2>/dev/null || :
        )"
      fi

      if [[ -z "${_selector_path:-}"  ]]
      then
        _selector_path="$(_notebooks current --path)"
      fi

      local _selector_is_item=1

      if [[ -d "${_selector_path:-}"  ]]
      then
        _selector_is_item=0
        _selector_path="${_selector_path:-}/"
      fi

      local _task_closed_patterns=(
        -e "- \[x\]"
      )
      local _task_open_patterns=(
        -e "- \[ \]"
        -e "^- \[\]"
        -e "[[:space:]]- \[\]"
      )

      local _todo_closed_patterns=(
        -e "# \[x\]"
      )
      local _todo_open_patterns=(
        -e "# \[ \]"
        -e "# \[\]"
      )

      {
        if [[ -n "${_tag_list_with_commas:-}"   ]]
        then
          _search                               \
            "${_selector_path:-}"               \
            "${_task_list_options[@]:-}"        \
            --tags "${_tag_list_with_commas:-}" \
            --type todo                         \
            --path
        else
          _list "${_selector_path:-}"     \
            --error-on-empty              \
            --no-id                       \
            --no-indicator                \
            --path                        \
            --type md                     \
            "${_task_list_options[@]:-}"  \
            2>/dev/null || printf ""
        fi
      } | {
        local _first=1
        local _in_task_list_item=0

        local         __item_path=
        while read -r __item_path
        do
          [[ -z "${__item_path:-}"    ]]    && continue
          [[ -d "${__item_path:-}"    ]]    && continue

          grep -q                           \
            "${_task_closed_patterns[@]:-}" \
            "${_task_open_patterns[@]:-}"   \
            "${_todo_closed_patterns[@]:-}" \
            "${_todo_open_patterns[@]:-}"   \
            "${__item_path}" || continue

          local _item_listing_no_color=
          _item_listing_no_color="$(
            _list "${__item_path:-}" --no-color --no-indicator
          )"

          local _item_selector="${_item_listing_no_color#[}"
          _item_selector="${_item_selector%%]*}"

          local _is_todo=0
          local _todo_done=0

          if _file_is_todo "${__item_path:-}"
          then
            _is_todo=1

            if [[ "${_item_listing_no_color:-}" =~ \[x\]  ]]
            then
              _todo_done=1
            fi
          fi

          local _filtered_task_patterns=()

          case "${_filter:-}" in
            closed) _filtered_task_patterns=("${_task_closed_patterns[@]:-}") ;;
            open)   _filtered_task_patterns=("${_task_open_patterns[@]:-}")   ;;
            *)
              _filtered_task_patterns=(
                "${_task_closed_patterns[@]:-}"
                "${_task_open_patterns[@]:-}"
              )
              ;;
          esac

          local _contains_filtered_tasks=0

          if grep -q                          \
            "${_filtered_task_patterns[@]:-}" \
            "${__item_path}"
          then
            _contains_filtered_tasks=1
          fi

          local _print_listing=1

          if ! ((_contains_filtered_tasks))
          then
            if ! ((_is_todo))
            then
              _print_listing=0
            fi

            case "${_filter:-}" in
              closed) ((_todo_done)) || _print_listing=0 ;;
              open)   ((_todo_done)) && _print_listing=0 ;;
            esac

            if ((_selector_is_item))
            then
              _print_listing=1
            fi
          fi

          if ! ((_print_listing))
          then
            continue
          fi

          if ((_contains_filtered_tasks))
          then
            _in_task_list_item=1

            ((_first)) || printf "\\n"
          elif ((_in_task_list_item))
          then
            _in_task_list_item=0

            ((_first)) || printf "\\n"
          fi

          _list "${__item_path:-}"

          _first=0

          if ! ((_contains_filtered_tasks)) && ! ((_selector_is_item))
          then
            continue
          fi

          local _info_line_no_color=
          _info_line_no_color="$(
            _list "${__item_path:-}" --no-color
          ) "

          local _extra_length=0

          case "${_info_line_no_color:-}" in
            *${_NB_INDICATOR_TODO_DONE}*) _extra_length="0"   ;;
            *${_NB_INDICATOR_TODO}*)      _extra_length="-3"  ;;
            *)                            _extra_length="-1"  ;;
          esac

          _print_line "${_info_line_no_color:-}"  \
            --no-wrap                             \
            --visible-length "${_extra_length:-0}"

          {
            grep                        \
              -e "- \[[[:space:]]*\] "  \
              -e "- \[x\] "             \
              "${__item_path:-}" || :
          } | {
            local _counter=0
            local _printed_task_counter=0

            local         __task=
            while read -r __task
            do
              _counter="$((_counter+1))"

              local _print_task=0

              case "${_filter:-}" in
                closed)
                  if [[ "${__task}" =~ \-\ \[x\]              ]]
                  then
                    _print_task=1
                  fi
                  ;;
                open)
                  if [[ "${__task}" =~ (\-\ \[\ \]|\-\ \[\])  ]]
                  then
                    _print_task=1
                  fi
                  ;;
                *)
                  _print_task=1
                  ;;
              esac

              if [[ "${_task_number:-${_counter:-}}" != "${_counter:-}" ]]
              then
                _print_task=0
              fi

              if ((_print_task))
              then
                local _formatted_task="${__task#- }"
                _formatted_task="${_formatted_task//\[x\]/$(_color_brackets "$(_color_primary "x")")}"
                _formatted_task="${_formatted_task//\[\]/$(_color_brackets " ")}"
                _formatted_task="${_formatted_task//\[ \]/$(_color_brackets " ")}"

                if [[ -z "${_task_number:-}" ]]
                then
                  _wrap off
                fi

                printf "%s %s"                                          \
                  "$(_color_brackets "${_item_selector} ${_counter}")"  \
                  "${_formatted_task}"

                if [[ -z "${_task_number:-}" ]]
                then
                  printf '\033[?7h'
                fi

                printf "\\n"

                _printed_task_counter="$((_printed_task_counter+1))"
              fi
            done

            if ! ((_printed_task_counter))
            then
              printf "0 %stasks.\\n" "${_maybe_padded_empty_qualifier:-}"
            fi
          }
        done
      } | {
        local _printed_line_counter=0

        local         __task_line=
        while read -r __task_line
        do
          printf "%s\\n" "${__task_line:-}"
          _printed_line_counter="$((_printed_line_counter+1))"
        done

        if ! ((_printed_line_counter))
        then
          _warn printf "0 %stasks.\\n" "${_maybe_padded_empty_qualifier:-}"

          return 1
        fi
      } | if ((_use_pager))
      then
        _pager
      else
        cat
      fi
      ;;
  esac
}
_alias_subcommand "todo" "t"
_alias_subcommand "todo" "to"
_alias_subcommand "todo" "todos"

# unarchive ######################################################### unarchive

_describe_unarchive() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} unarchive [<name>]

$(_color_primary "Description"):
  Remove "archived" status from the current notebook or notebook <name>.

  This is an alias for \`${_ME} notebooks unarchive\`.

$(_color_primary "Read More"):
  ${_README_URL}#archiving-notebooks

$(_color_primary "See Also"):
  ${_ME} help archive
  ${_ME} help notebooks
  ${_ME} help status

$(_color_primary "Examples"):
  ${_ME} unarchive
  ${_ME} unarchive example

$(_color_primary "Shortcut Alias"):
  ${_ME} unar
HEREDOC
}
_unarchive() {
  _notebooks unarchive "${@:-}"
}
_alias_subcommand "unarchive" "unar"

# undo ################################################################### undo

_describe_undo() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} undo ([<notebook>:][<folder-path>/][<id> | <filename> | <title>])
          [<task-number>]

$(_color_primary "Description"):
  Mark a todo or task as not done.

$(_color_primary "Read More"):
  ${_README_URL}#-todos

$(_color_primary "See Also"):
  ${_ME} help do
  ${_ME} help tasks
  ${_ME} help todo

$(_color_primary "Examples"):
  ${_ME} undo 123
  ${_ME} undo example:sample/321
  ${_ME} undo 543 7
HEREDOC
}
_undo() {
  _todo "undo" "${@:-}"
}
_alias_subcommand "undo" "undone"

# unset ################################################################# unset

_describe_unset() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} unset (<name> | <number>)

$(_color_primary "Description"):
  Unset a setting, returning it to the default value.

  This is an alias for \`${_ME} settings unset\`.

$(_color_primary "Read More"):
  ${_README_URL}#%EF%B8%8F-set--settings

$(_color_primary "See Also"):
  ${_ME} help settings

$(_color_primary "Examples"):
  ${_ME} unset color_primary
  ${_ME} unset 2

$(_color_primary "Alias"):
  ${_ME} reset
HEREDOC
}
_unset() {
  case "${1:-}" in
    '')     _exit_1   _help "unset" ; return 1 ;;
    remote) _remote   unset         ; return 0 ;;
    *)      _settings unset "${@:-}"; return 0 ;;
  esac
}
_alias_subcommand "unset" "reset"

# update ############################################################### update

_describe_update() {
  cat <<HEREDOC
$(_color_primary "Usage"):
  ${_ME} update

$(_color_primary "Description"):
  Update \`${_ME}\` to the latest version. You will be prompted for
  your password if administrator privileges are required.

  If \`${_ME}\` was installed using a package manager like npm or
  Homebrew, use the package manager's upgrade functionality instead
  of this command.

$(_color_primary "Read More"):
  ${_README_URL}#installation

$(_color_primary "See Also"):
  ${_ME} help env
  ${_ME} help version
HEREDOC
}
_update() {
  local _current_path=
  _current_path="${BASH_SOURCE[0]}"

  if [[ -n "${_current_path}" ]]  &&
     [[ -L "${_current_path}" ]]
  then
    _current_path="$(_resolve_symlink "${_current_path}")"
  fi

  if hash npm 2>/dev/null         &&
     npm list | grep -q notes.sh  &&
     [[ "${_current_path}"    =~ (\/node\/|\/node_modules\/)  ]]
  then # installed with npm
    cat <<HEREDOC
Installed with npm. To update, run:
  npm update -g notes.sh
HEREDOC
  elif hash npm 2>/dev/null       &&
       npm list | grep -q nb.sh   &&
       [[ "${_current_path}"  =~ (\/node\/|\/node_modules\/)  ]]
  then # installed with npm
    cat <<HEREDOC
Installed with npm. To update, run:
  npm update -g nb.sh
HEREDOC
  elif [[ "${OSTYPE}"         =~ ^darwin  ]] &&
       [[ "${_current_path}"  =~ Cellar   ]]
  then
    cat <<HEREDOC
Installed with Homebrew. To update, run:
  brew upgrade nb
HEREDOC
  else
    local _nb_url="${_REPO_RAW_URL}/nb"

    local _temp_file=
    _temp_file="$(_temp file)"

    if ! _download_from "${_nb_url}" "${_temp_file}" --no-chrome
    then
      _exit_1 printf "Unable to download update.\\n"
    fi

    if [[ "$(_get_hash "${_temp_file}")" != "$(_get_hash "${_current_path}")" ]]
    then
      while true
      do
        printf "Updating %s in place. " "$(_color_primary "${_ME}")"

        local __yn=
        IFS='' read -r -e -d $'\n' -p \
"$(_color_primary "Proceed?") $(_color_brackets "y/N") " __yn

        case "${__yn}" in
          [Yy]*)
            break
            ;;
          *)
            printf "Exiting%s\\n" "$(_color_muted "...")"

            exit 0
            ;;
        esac
      done

      if [[ -w "${_current_path}" ]]
      then
        cat "${_temp_file}" > "${_current_path}"
      else
        cat "${_temp_file}" | sudo tee "${_current_path}" > /dev/null
      fi

      printf "%s updated to the latest version.\\n" "$(_color_primary "${_ME}")"

      exit 0
    else
      printf "Already at the latest version.\\n"
    fi

    if [[ -n "${_temp_file:-}" ]] && [[ -f "${_temp_file}" ]]
    then
      rm "${_temp_file:?}"
    fi
  fi
}
_alias_subcommand "update" "upgrade"

###############################################################################
# Call Deferred Command: Group 3                 Call Deferred Command: Group 3
###############################################################################
# --------------------------------------------------------------------------- #

_call_deferred_command --group 3

exit 0
