Bem, eu estive na curva de aprendizado novamente ... (tarde da noite e muito café).
O resultado líquido é um script bash moderadamente utilizável (usando um sqlite db / table) que faz o que eu estava atrás ...
... ou seja. Cria um agrupamento de notas, com base nos títulos das janelas ...
Funciona ... mas é definitivamente "alfa" ...
Então, eu tenho meu aplicativo caseiro! ... Estou postando aqui para qualquer pessoa interessada em um "look-see" ...
Aqui está:
#!/bin/bash
clearAllDataAndStartAgain="false"
# Name: tinotes (Title Notes)
#
# What does it do? ... Aside from giving me a great opportunity to learn
# more about bash (and sqlite, which I had previously barely touched).. not much ;)
# Actually, it allows you to keep notes, grouped by window title.
# The notes are kept in an sqlite database.
# Each timestamped note-"event" is stored in a row of the main (only) table.
# You can consolidate notes in a semi ad-hoc manner...
# Notes are presented to you in a single editable text file (in Leafpad).
# You must keep at least one "tinotes" timestamp-line at the top of the text...
# All lines above this topmost timestamp-line are ignored,
# including the "title", which is presented upon each viewing.
# If you remove any/all other "timestamp line(s)", those particular rows are
# deleted from the sqlite table, and the text which remains is associated with
# the immediately preceding timestamp-line (and updated as such in the sqlite table)
#
# How do you drive it? .. Just associate 'tinotes.sh' with a shortcut-key.. That's' it!
# Just press the shortcut-key and you will be presented with Leafpad displaying
# a "title line" at the very top, and on line 2, is a "tinotes timestamp" line.
# Type your note below the timestamp-line, then Save and Exit Leafpad,..
# NB.. You MUST fully EXIT Leafpad.. the script cannot proceed until you EXIT Leafpad..
# Leafpad is effectively being used as a Dialog-box with "normal" editing capability.
# A warning Dialog appears if another instance of this script is currently running..
# (actually, if another ***tinotes** leafpad window is running).
#
# Caveat: This version is very much "demo-only"...
# It works, but has typical "alpha" bugs...
# I've presented it here, for anyone who is interested in the general idea.
#
# dependencies
# ============
# sqlite3 ,, the notes are stored in a sqlite db.
# leafpad .. to edit/view the notes (no need to re-invent the wheel)
# wmctrl .. to detect if a ***tinotes*** leafpad window is currently open.
# xdotool .. to get the active window's' ID
# xwininfo .. to get a window's title via it's ID.
# md5sum .. to check for mods to the presented/added notes data
# zenity .. for warning dialog(s)
# sed .. versatile!
# wc .. word count? .. line count (here)
############################################################################
function FinalizeNote {
title=""; note=""; timeline=""; preList=""
# Remove trailing whitespace
note="${note%"${note##*[![:space:]]}"}"
# Does this timestamp exist in the PRE-LIST
timestamp=${timeline:0:19}
preCt=$(sed -n "s/^$timestamp.\(.*\)//p" "$preList" |wc -l)
if [ "$preCt" -eq "0" ] ; then
sqlite3 "$appdb" "INSERT INTO Tmain (time,title,note) VALUES('$timestamp','$title','$note');"
elif [ "$preCt" -gt "1" ] ; then
excod=3
zenity --error --text "$preCt duplicate timestamps found. \
\nThis is an 'alpha' problem! \
\n\n Exiting with code $excod"
exit $excod
else
# TODO: At it currently stands, it is only known that "something" has changed,
# but not which rows have been effected. (Just update them all, for now.)
id=$(sed -n "s/^$timestamp.\(.*\)//p" "$preList")
sqlite3 "$appdb" "UPDATE Tmain SET note='$note' WHERE id='$id';"
# Remove line from PRE-LIST
sed -i -e "/^$timestamp.*$/d" "$preList"
fi
}
############################################################################
sep="∘" # Field seperator
sepmulti="∘∘∘∘∘∘∘∘∘∘∘∘∘∘∘∘∘∘∘∘∘∘∘∘"
sepfirst="∘∘(write∘new∘notes∘below∘this∘line)∘∘"
appnam="tinotes"
appdir="$HOME/.$appnam"
appdb="$appdir/$appnam.db"
appsql="$appdir/$appnam.sql"
apptxt="$appdir/$sep$sep$sep$appnam$sep$sep$sep"
preList="$appdir/$appnam.pre"; echo -n>"$preList"
tiwid=0 # Check for a currently running Instance of the "Leafpad" window...
tiwid=$(wmctrl -l |sed -n "s/\([^ ]\+\) \+[^ ]\+ \+[^ ]\+ \*\?$(basename $apptxt)$//p")
if [ "${tiwid:0:2}" == "0x" ] ; then
# Warn of the need to finalize an already-running instance of this script
zenity --warning --text "You must first finalize a previously opened \n\t 'tinotes' window.\
\n\n To activate the window, select 'OK'"
# 'wmctrl' can only activate via a title
# ..and it is case-insensitive and wildcarded!!
# so use 'xdotool'
xdotool windowactivate --sync $(($tiwid))
exit
fi
#################################################################################################################################################
[ "$clearAllDataAndStartAgain" = "true" ] && [ -d "$appdir" ] && rm -rf "$appdir" # Typically for TESTING ONLY; Remove all data,and start afresh!
#################################################################################################################################################
# First-time create app's main directory
[ ! -d "$appdir" ] && mkdir "$appdir"
# First-time Create the Tmain table
[ ! -f "$appdb" ] && sqlite3 "$appdb" "create table Tmain (id INTEGER PRIMARY KEY,time DATE,title TEXT,note TEXT);"
# Get the active-window's title
# =============================
activeT=$(xwininfo -id "$(xdotool getactivewindow)" |sed -n \
"2s/^xwininfo: Window id: \(0x[[:xdigit:]]\+\) \x22\(.*\)\x22$//p")
# Does a previous row of the same title already exist?
# ====================================================
# First, prepare a new/"empty" note entry
echo "$activeT" >"$apptxt"
echo -e $(date '+%Y-%m-%d %H:%M:%S' |tr -d '\n')" $sep$appnam$sepfirst\n\n\n">>"$apptxt"
# Count existing rows for this title
if [ $(sqlite3 "$appdb" "SELECT COUNT(title) FROM Tmain WHERE title = '$activeT';") -gt 0 ] ; then
# Previous notes FOUND for this window title
# Make a list of timestamps to match-off against any user mods
sqlite3 "$appdb" "SELECT time,id FROM Tmain WHERE title='$activeT';" >"$preList"
# Build and Run the query to construct the "timeline"
echo -e ".separator "$sep"\n\
SELECT time||' $sep$appnam$sepmulti','\n\n'||note||'\n' FROM Tmain WHERE title='$activeT' order by time desc;">"$appsql"
sqlite3 "$appdb" <"$appsql">>"$apptxt"
fi
# Present the notes to the user (get the "before" md5sum, to compare with user's access/mods)
md5bef=$(md5sum "$apptxt" |sed "s/\([[:xdigit:]]\+\).*//")
leafpad "$apptxt" # The script waits for the user to close "leafpad"
md5aft=$(md5sum "$apptxt" |sed "s/\([[:xdigit:]]\+\).*//")
# Check for any modifications to the notes
if [ "$md5bef" == "$md5aft" ] ; then
# No changes have been made.
exit 0
fi
# The notes have been modified. Commit the changes!
# It's time to analyze the changes, and tidy up.
# Remove leading and trailing blank lines (per timestamp).
# Delete rows for which the timestamp has been removed.
# Update the table for all the remaining rows.
note=""
lnCt=0
while read line ; do
lnCt=$((lnCt+1))
[ "$lnCt" -eq "1" ] && continue # The first line is a throw-away copy of the "title"
# Find timeline. Any leading data is lost. (It shouldn't be there... common-sense!)
if [[ "$line" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}\ [0-9]{2}:[0-9]{2}:[0-9]{2}\ ∘.*∘$ ]] ; then
# FOUND timeline
if [ "$note" != "" ] ; then
FinalizeNote "$activeT" "$note" "$timeline" "$preList"
fi
note=""
timeline=$line
elif [ "$line" = "" ] ; then
if [ "$note" != "" ] ; then
note="$note$line"$'\n' # append this blank line
fi
else
note="$note$line"$'\n' # append this non-blank line
fi
done <"$apptxt"
#
if [ "$note" != "" ] ; then
FinalizeNote "$activeT" "$note" "$timeline" "$preList"
fi
# Delete rows for timestamps still in the PRE-LIST
while read line ; do
eval $(echo "$line" |sed -n "s/.*|\([0-9]\+\)$/id=/p")
sqlite3 "$appdb" "DELETE FROM Tmain WHERE id='$id';"
done <"$preList"
exit
############################################################################