Index ¦ All posts

My dead simple note system

Estimated read time: 4 minutes

I'm a fan of the terminal and a thoughtfully chosen $EDITOR variable. But enough with the intro. Here is my system, in action. Around 100 lines of bash and a directory with sets of plain text files.

A new document

torvald@gauda ~ $ note
[0] /home/torvald/notes/private
[1] /home/torvald/notes/work
[2] /home/torvald/notes/woodworking

Choose: [0]: 
Title: bathroom inspiration 
# Opens vim - edit and exit
/home/torvald/notes/private/2019-10-10_bathroom_inspiration.txt
torvald@gauda ~ $

Search for documents

torvald@gauda ~ $ note bathroom
Title serach:
[0] notes/private/./2019-10-10_bathroom_inspiration.txt
Content serach:
[1] notes/private/2019-04-02_home_improvments.txt (..the old bathroom light mus..)
[2] notes/private/2019-03-11_ideas_from_trip.txt (..- A bathroom closet..)
--
Enter number [0]:

The script

#!/bin/bash

ROOT=/home/torvald/notes
CATEGORIES="private work woodworking"

for folder in $CATEGORIES; do
    mkdir -p "$ROOT/$folder"
done

function search() {

    search=$1
    hits=()

    ####################
    # Seach by file name
    ####################

    echo "Title serach:"

    i=0
    for folder in $CATEGORIES; do
        cd "$ROOT/$folder" || continue
        for line in $(find . -maxdepth 1 | grep \.txt$ | grep "$search"); do
            hits[$i]=$folder/$line
            echo "[$i] $folder/$line"
            i=$((i + 1))
        done
    done

    ##################
    # Seach by content
    ##################

    echo "Content serach:"

    for folder in $CATEGORIES; do
        cd "$ROOT/$folder" || continue
        # TODO make --name
        for line in $(ag --depth 0 --files-with-matches "$search" | grep \.txt$); do
            context=$(grep -E -o ".{0,10}$search.{0,10}" "$line" | head -n 1)
            hits[$i]=$folder/$line
            echo "[$i] $folder/$line (..$context..)"
            i=$((i + 1))
        done
    done

    #################
    # Choose document
    #################

    # Only one hit, auto open
    if [[ "$i" == "1" ]]; then
        echo "Only one hit, opening $ROOT/${hits[1]}"
        sleep 1
        $EDITOR "$ROOT/${hits[1]}"
        exit 0

    # No hits
    elif [[ "$i" == "0" ]]; then
        echo "No hits."
        exit 1
    fi

    # Multiple hits
    echo "--"
    echo -n "Enter number [0]: "

    read -r index
    if [[ $index == "" ]]; then
        index="0"
    fi
    echo "$ROOT/${hits[$index]}"

    $EDITOR "$ROOT/${hits[$index]}"

    exit 0
}

function new_note() {

    ############################
    # List and choose categories
    ############################

    i=0
    for folder in $CATEGORIES; do
        echo "[$i] $ROOT/$folder"
        i=$((i + 1))
    done

    echo ""
    echo -n "Choose: [0]: "

    read -r foldernumber

    if [[ $foldernumber == "" ]]; then
        foldernumber="1"
    fi

    choosen=$(echo "$CATEGORIES" | cut -d' ' -f$foldernumber)
    folder=$ROOT/$choosen

    if ! [ -d "$folder" ]; then
        echo "Folder $folder does not exists"
        exit 1
    fi

    #######################
    # Choose title and open
    #######################

    echo -n "Title: "
    read -r filename

    filename=$(echo "$filename" | sed 's/ /_/g' | tr '[:upper:]' '[:lower:]')

    DATE=$(date +%Y-%m-%d)

    $EDITOR "$folder"/"$DATE"_"$filename".txt

    echo "$folder"/"$DATE"_"$filename".txt
}

if [[ $1 != "" ]]; then
    search "$1"
else
    new_note
fi

Future thoughts

  • Maybe I'll add a small daemon that runs grip, to render Markdown through a simple http server (apt-get install grip).
  • Maybe I'll add an interface to this somehow for my phone, but I'm not no fan of mobile typing, so I guess not.
  • Maybe I'll add an option to move a file to my web server which in turn returns a public and random link for sharing.
  • Maybe you have ideas?

© Torvald Tåke. Built using Pelican. Theme by Giulio Fidente on github.