Skip to content

Instantly share code, notes, and snippets.

@zrzka
Forked from chockenberry/tot.sh
Last active March 2, 2020 07:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save zrzka/5948256ac72c3f3820aebff1fb4b1b70 to your computer and use it in GitHub Desktop.
Save zrzka/5948256ac72c3f3820aebff1fb4b1b70 to your computer and use it in GitHub Desktop.
A shell script for Tot
#!/usr/bin/env bash
# Fork of gruber's tot.sh https://gist.github.com/gruber/b18d8b53385fa612713754799ed4d0a2
# which is a fork of chockenberry's tot.sh https://gist.github.com/chockenberry/d33ef5b6e6da4a3e4aa9b07b093d3c23
# Exit immediately if a pipeline returns a non-zero status.
set -e
# If set, the return value of a pipeline is the value of the last (rightmost) command
# to exit with a non-zero status, or zero if all commands in the pipeline exit successfully.
set -o pipefail
basename=$(basename "$0")
#
# Helpers
#
# All functions expect that the global `dot` variable is set & validated.
#
function print_usage() {
cat << END
Usage: ${basename} <dot> [ <command> ] [ <file> | - ]
Options:
<dot> dot number (1 to 7) or 0 as a first empty dot
<command> see Commands
<file> file path to read contents from or just - (stdin)
Commands:
activate select dot & activate Tot.app (default command if not provided)
p|print print dot contents
a|append append file/stdin contents to dot
c|clear remove dot contents
r|replace replace dot contents with file/stdin
Examples:
$ ${basename} 2 # activate Tot.app and select second dot
$ ${basename} 2 print # print second dot contents to stdout
$ ${basename} 2 clear # clear contents of second dot
$ cal -h | ${basename} 1 append - # append a calendar to first dot
$ ${basename} 2 append MyApp.crash # append a crash report to second dot
$ ${basename} 2 replace MyApp.crash # replace second dot contents with a crash report
END
}
function get_url_encoded_content_of() {
local file=$1
# $(< "${file}" python3 ...) doesn't handle stdin (-) well, but cat does
# shellcheck disable=SC2002
cat "${file}" | python3 -c 'import urllib.parse; import sys; print(urllib.parse.quote(sys.stdin.read()))'
}
function tell_tot_to() {
local command=$1
osascript -e "tell application \"Tot\" to ${command}"
}
function tell_tot_to_append_content_of() {
local file=$1
local content
content=$(get_url_encoded_content_of "${file}")
tell_tot_to "open location \"tot://${dot}/append?text=${content}\""
}
function tell_tot_to_replace_content_with() {
local file=$1
local content
content=$(get_url_encoded_content_of "${file}")
tell_tot_to "open location \"tot://${dot}/replace?text=${content}\""
}
function replace_zero_dot_with_first_empty_dot() {
local testdot
local content
if ! [[ ${dot} = "0" ]]; then
return 0
fi
for testdot in {1..7}
do
content=$(tell_tot_to "open location \"tot://${testdot}/content\"")
# Matching whitespace-only strings in Bash: https://stackoverflow.com/questions/9767644/
if ! [[ $content =~ [^[:space:]] ]]; then
# clear contents of dot, in case there's whitespace:
tell_tot_to "open location \"tot://${testdot}/replace?text=\""
dot=$testdot
break
fi
done
if (( dot == 0 )); then
>&2 echo "error: no empty dots"
return 1
fi
}
#
# Main
#
if [ -z "$*" ]; then
print_usage
exit 1
fi
#
# Sort of input validation
#
dot="$1"
replace_zero_dot_with_first_empty_dot
if ! [[ $dot =~ ^[1-7]$ ]]; then
>&2 echo "error: invalid dot number ${dot}"
exit 1
fi
command="${2:-activate}"
input="$3"
#
# Commands
#
case "${command}" in
activate)
# Switch dot & activate Tot
tell_tot_to "open location \"tot://${dot}\""
tell_tot_to "activate"
;;
p|print)
# Print contents of dot
tell_tot_to "open location \"tot://${dot}/content\""
;;
c|clear)
# Clear contents of dot
tell_tot_to "open location \"tot://${dot}/replace?text=\""
;;
r|replace)
# Replace contents of dot
tell_tot_to_replace_content_with "${input}"
;;
a|append)
# Append contents to dot
tell_tot_to_append_content_of "${input}"
;;
*)
print_usage
exit 1
esac
@earthboundkid
Copy link

Great fork. I think this is an example of what good shell scripting looks like. Obviously, no one should use shell for "real" programming, but that doesn't mean you can't use things like functions to make things simpler.

@zrzka
Copy link
Author

zrzka commented Feb 28, 2020

Did update it & replaced options like -r with commands like replace (or just r).

Not sure if this is an example of what good shell scripting looks like, but thanks :)

@earthboundkid
Copy link

The script runs just python without specifying 2 or 3, but depends on 2. I changed the script to explicitly use 3 because I worry Apple will drop Python 2 someday and the script will break.

@zrzka
Copy link
Author

zrzka commented Feb 28, 2020

Good point, I'll update it tmw.

@toonetown
Copy link

I have made this into a homebrew formula (at https://github.com/toonetown/homebrew-extras) that can be easily installed using:

brew install toonetown/extras/tot

I'll try to keep it updated as you update this here (yours seems to be the most active and up-to-date fork, so I'm using it as the base).

@toonetown
Copy link

One helpful thing I found is to default to stdin when specifying r|replace and a|append...I updated a fork (revision 8 at https://gist.github.com/toonetown/5a73a279c905a56a14b1d2f535d62dea/revisions) with this change. Would love to have you consider putting it in your fork, and then I can update the homebrew formula version.

@toonetown
Copy link

Another helpful change is to allow not needing to put spaces in between your parameters...so so, for example, I like doing:

date | tot 0a

To append to the "0" dot. Another update which is at that same revision (revision 9).

@zrzka
Copy link
Author

zrzka commented Mar 2, 2020

To all

I moved this Gist to the https://github.com/zrzka/tot-addons repository (bash/tot) along with my LaunchBar action. This gist wont be updated.

@toonetown thanks for the feedback.

Re default to stdin - definitely good idea. I updated it zrzka/tot-addons@983649e.

Re second proposal - 0 a -> 0a. To be honest, I'm not a big fan of it. I think that saving one keystroke is not worth in this case. If you'd like to add/have it, feel free to fork it and use it in your homebrew formula.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment