i'm looking forward to reading your thoughts
This commit is contained in:
commit
94b41d8d9b
8 changed files with 500 additions and 0 deletions
6
.foot.html
Normal file
6
.foot.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
<hr>
|
||||
<p style="text-align:center">
|
||||
thank you for reading my thoughts
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
93
.head.html
Normal file
93
.head.html
Normal file
|
@ -0,0 +1,93 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Thoughts</title>
|
||||
<style>
|
||||
|
||||
html {
|
||||
background: white;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
color: black;
|
||||
padding: 1em;
|
||||
max-width: 50em;
|
||||
margin: 0 auto;
|
||||
word-wrap: break-word;
|
||||
line-height: 1.50;
|
||||
}
|
||||
|
||||
/*
|
||||
This only styles the main title at the top of the page
|
||||
which by default is just the word 'thoughts'
|
||||
*/
|
||||
h1 {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/*
|
||||
This styles code blocks
|
||||
*/
|
||||
pre {
|
||||
overflow-x: auto;
|
||||
word-wrap: normal;
|
||||
border: 1px solid lightgray;
|
||||
padding: 1em
|
||||
}
|
||||
|
||||
/*
|
||||
This styles inline <code>
|
||||
*/
|
||||
code:not(.block) {
|
||||
font-family: monospace;
|
||||
padding: .1em;
|
||||
border: 1px solid lightgray;
|
||||
}
|
||||
|
||||
/*
|
||||
This also styles code blocks
|
||||
Each code block <pre><code class="block">looks like this</code></pre>
|
||||
*/
|
||||
code {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
/*
|
||||
This styles the div that the date/link for each post is in
|
||||
The <a> tag itself is also a member of class "though-date"
|
||||
so you can style that too if that's helpful
|
||||
*/
|
||||
div.thought-date {
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/*
|
||||
This is the outermost block element for a given
|
||||
thought post. You can style it if you like, but this
|
||||
is probably only useful for spacing your posts from each other
|
||||
in the way you'd like
|
||||
*/
|
||||
section.thought {
|
||||
margin: 1em 0em;
|
||||
}
|
||||
|
||||
/*
|
||||
This styles the element that contains the actual
|
||||
text of an individual post.
|
||||
*/
|
||||
div.thought {
|
||||
border: 2px solid lightgray;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>thoughts</h1>
|
||||
|
||||
<!-- Your thoughts start here -->
|
47
install.sh
Executable file
47
install.sh
Executable file
|
@ -0,0 +1,47 @@
|
|||
#!/bin/sh
|
||||
set -euf
|
||||
|
||||
if [ -z ${1+x} ]; then
|
||||
cmd='default'
|
||||
else
|
||||
cmd="$1"
|
||||
fi
|
||||
|
||||
binDir=$HOME/.local/bin
|
||||
stuffDir=$HOME/.local/share/thoughts
|
||||
|
||||
if [ -d "$stuffDir" ]; then
|
||||
printf "Thoughts is already installed. Reinstall? [y/n]: "
|
||||
read -r reply
|
||||
if [ ! "$reply" = "y" ]; then
|
||||
echo
|
||||
echo "OK, nothing's been installed."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p "$stuffDir"/bin
|
||||
cp parse.awk "$stuffDir"/bin
|
||||
cp readme.md "$stuffDir"
|
||||
cp .head.html "$stuffDir"
|
||||
cp .foot.html "$stuffDir"
|
||||
cp thoughts-gitignore "$stuffDir"/.gitignore
|
||||
touch "$stuffDir"/.rawthoughts.html
|
||||
|
||||
mkdir -p "$binDir"
|
||||
cp thoughts "$binDir"
|
||||
chmod +x "$binDir"/thoughts
|
||||
|
||||
if [ "$cmd" = "another" ]; then
|
||||
printf "What's the git clone URL for your existing thoughts repository?: "
|
||||
read -r reply
|
||||
git clone "$reply" "$stuffDir"/thoughts-temp
|
||||
cp -r "$stuffDir"/thoughts-temp/. "$stuffDir"
|
||||
rm -rf "$stuffDir"/thoughts-temp
|
||||
echo
|
||||
echo 'Done! Add $HOME/.local/bin to your PATH'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo
|
||||
echo 'Done! Add $HOME/.local/bin to your PATH, and create a git repo: https://git.bunk.computer/maren/thoughts#first-install'
|
1
license.txt
Normal file
1
license.txt
Normal file
|
@ -0,0 +1 @@
|
|||
CC0 1.0
|
75
parse.awk
Normal file
75
parse.awk
Normal file
|
@ -0,0 +1,75 @@
|
|||
# This awk program adds <br> to the end of each line
|
||||
# unless it's inside a codeblock.
|
||||
# It also converts the custom <block> tag into
|
||||
# the actual HTML we want, and linkifies links
|
||||
BEGIN {isCode=0}
|
||||
{
|
||||
if ($0 == "<block>") {
|
||||
isCode = 1;
|
||||
printf("<pre><code class=\"block\">");
|
||||
# set the field separator before we read the next line
|
||||
# so we can read char by char
|
||||
FS = "";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($0 == "</block>") {
|
||||
isCode = 0;
|
||||
print "</code></pre>";
|
||||
# reset field separator to default before reading next line
|
||||
FS = " ";
|
||||
next;
|
||||
}
|
||||
|
||||
#if the thing we're in is a code block
|
||||
if (isCode == 1) {
|
||||
if ($0 == "") {
|
||||
print "";
|
||||
next;
|
||||
}
|
||||
# convert special html chars to web safe versions
|
||||
field = 1;
|
||||
while (field <= NF) {
|
||||
if ($field == "&") {
|
||||
printf "&";
|
||||
} else if ($field == "<") {
|
||||
printf "<";
|
||||
} else if ($field == ">") {
|
||||
printf ">";
|
||||
} else if ($field == "\"") {
|
||||
printf """;
|
||||
} else if ($field == "'") {
|
||||
printf "'";
|
||||
} else {
|
||||
printf $field;
|
||||
}
|
||||
field++;
|
||||
if (field > NF) {
|
||||
print "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isCode == 0) {
|
||||
# if the line is empty, make it a <br> and move on
|
||||
# TODO make this write <br> even if the line has just spaces/tabs/etc.
|
||||
if ($0 == "") {
|
||||
print "<br>";
|
||||
next;
|
||||
}
|
||||
field = 1;
|
||||
while (field <= NF) {
|
||||
if ($field ~ /^http:\/\/*/ || $field ~ /^https:\/\/*/ || $field ~ /^gopher:\/\/*/ || $field ~ /^gemini:\/\/*/) {
|
||||
printf "<a href=\""$field"\">"$field"</a> ";
|
||||
} else {
|
||||
printf $field" ";
|
||||
}
|
||||
field++;
|
||||
# print <br> if end of the line
|
||||
if (field > NF) {
|
||||
print "<br>";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
END {}
|
97
readme.md
Normal file
97
readme.md
Normal file
|
@ -0,0 +1,97 @@
|
|||
> i made this program during the height of the 2020 covid lockdowns. it was years before i joined or believed in the promise of mastodon and i and everyone else was in an intense and particular place emotionally. i loved this project, and i used it so so much. it spawned a sweet small internet posting platform and was my first sort of participation in the diy internet. in any case, it's done now and it's frozen in time. it still works well, and i think there's an interesting utility to frozen programs. this is one, please use it for anything you'd like, attribution not even necessary
|
||||
|
||||
---
|
||||
|
||||
# Thoughts 💭
|
||||
|
||||
Thoughts is a POSIX-compliant shell program for making short text posts and putting them on the internet. Thoughts has a terminal interface and runs on UNIX-based systems like MacOS, Linux, the BSDs, and WSL.
|
||||
|
||||
Thoughts keeps your thoughts in a single HTML file, and it syncs that file in a remote git repository. That HTML file is your thoughts page. It's up to you to serve the file from somewhere, but Thoughts handles everything else.
|
||||
|
||||
Thoughts can be installed on any number of computers, all updating the same remote HTML file.
|
||||
|
||||
Thoughts supports deployment on Codeberg Pages or GitHub Pages out of the box. Simply enable pages on your personal Thoughts repository.
|
||||
|
||||
If you want a thoughts page but don't want to host it yourself, you can do that at https://thoughts.page. *Note: I don't run thoughts.page but I do endorse it*
|
||||
|
||||
Thoughts' only dependency is Git, and it should run without modification on any UNIX-based system.
|
||||
|
||||
## How it works
|
||||
|
||||
1. Install Thoughts
|
||||
1. Type `thoughts` in a terminal and press ENTER
|
||||
1. Your preferred text editor opens. Type your thought, then save and exit
|
||||
1. Thoughts adds your thought to `index.html`
|
||||
1. Thoughts pushes your updated `index.html` to a remote git repository
|
||||
|
||||
## Installing
|
||||
|
||||
Install thoughts with the `install.sh` script described below
|
||||
|
||||
### First install:
|
||||
(*Do this if you're making a new thoughts page*)
|
||||
|
||||
1. Install and [configure](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup) git
|
||||
1. `git clone https://git.bunk.computer/maren/thoughts.git ~/thoughts-source && cd ~/thoughts-source`
|
||||
1. Install with `./install.sh`
|
||||
1. Add `$HOME/.local/bin` to your PATH
|
||||
1. Use `git init` to create a git repository in `$HOME/.local/share/thoughts`, then [point it at an empty remote origin](https://docs.codeberg.org/getting-started/first-repository/#option-b%3A-connect-an-existing-local-source-tree)
|
||||
1. Be sure the repo is set up properly:
|
||||
```
|
||||
$ cd ~/.local/share/thoughts
|
||||
$ git add .
|
||||
$ git commit -m "init"
|
||||
$ git push
|
||||
```
|
||||
1. From anywhere in your home directory, type `thoughts`
|
||||
|
||||
### Installing on another computer:
|
||||
|
||||
*(Do this if you already have a thoughts page)*
|
||||
|
||||
1. Clone `https://git.bunk.computer/maren/thoughts.git` and `cd` into the cloned directory
|
||||
1. Install with `./install.sh another`
|
||||
1. Follow the prompts
|
||||
|
||||
## Commands
|
||||
|
||||
* `$ thoughts edit`
|
||||
* Edit your previously posted thoughts
|
||||
* `$ thoughts style`
|
||||
* Customize the default CSS
|
||||
* `$ thoughts preview`
|
||||
* Preview a thought in a browser while working on it
|
||||
|
||||
## "Markdown"
|
||||
|
||||
Thoughts supports non-standard markdown that's mostly just HTML.
|
||||
|
||||
* Italics
|
||||
* `You can write <em>italics</em>`
|
||||
* Bold
|
||||
* `You can write in <strong>bold</strong>`
|
||||
* Inline code
|
||||
* `You can write <code>inline code</code>`
|
||||
* Code blocks
|
||||
* ```
|
||||
<block>
|
||||
You can write code blocks with this fake tag I invented.
|
||||
Each <block> tag must be on its own line or it won't parse correctly.
|
||||
Exactly like this.
|
||||
</block>
|
||||
```
|
||||
* Links
|
||||
* Links are automatically linkified if they start with `http://` or `https://`, and the "h" has a space in front of it
|
||||
* Thoughts will also linkify gemini and gopher links
|
||||
* HTML
|
||||
* Arbitrary HTML is theoretically supported outside of code blocks, but there are likely to be some inexplicable side-effects.
|
||||
|
||||
## Notes
|
||||
|
||||
* When typing a thought, newlines are converted to `<br>` in all cases.
|
||||
* Thoughts' goal is to make what you typed in vim appear on the internet, and to make it look roughly the way it did in vim. So, there will only be space between lines if you put it there -- space things how you want!
|
||||
* Thoughts is wrapping lots of git behavior.
|
||||
* The `edit` and `style` commands don't only open HTML and CSS files for you; they also wrap git things so that your changes stay synced across all your computers.
|
||||
* If a git thing is breaking, manually inspect the situation in `$HOME/.local/share/thoughts`.
|
||||
* If you post a thought that contains HTML outside of a `<block>` tag, that HTML will definitely render in the browser. It might work, or it might break. Experiment!
|
||||
* You can modify the footer by editing the file at `~/.local/share/thoughts/.foot.html`
|
175
thoughts
Executable file
175
thoughts
Executable file
|
@ -0,0 +1,175 @@
|
|||
#!/bin/sh
|
||||
set -euf
|
||||
|
||||
if [ -z ${1+x} ]; then
|
||||
cmd='default'
|
||||
else
|
||||
cmd="$1"
|
||||
fi
|
||||
|
||||
stuffDir=$HOME/.local/share/thoughts
|
||||
binDir=$HOME/.local/bin
|
||||
|
||||
# "edit" command
|
||||
edit () {
|
||||
cd "$stuffDir"
|
||||
git pull
|
||||
"${EDITOR:-vi}" .rawthoughts.html
|
||||
cat .head.html .rawthoughts.html .foot.html > index.html
|
||||
git add .
|
||||
git commit -m "update thoughts"
|
||||
git push
|
||||
echo
|
||||
echo "your thoughts have been updated"
|
||||
}
|
||||
|
||||
# "help" command
|
||||
help () {
|
||||
echo '$ thoughts'
|
||||
echo ' * Share your thoughts'
|
||||
echo
|
||||
echo '$ thoughts edit'
|
||||
echo ' * Edit your previously posted thoughts'
|
||||
echo
|
||||
echo '$ thoughts style'
|
||||
echo ' * Customize the CSS'
|
||||
echo
|
||||
echo '$ thoughts preview'
|
||||
echo ' * Preview a thought in a browser while working on it'
|
||||
echo
|
||||
echo "If you need to do some manual intervention,"
|
||||
echo "thoughts data lives in $HOME/.local/share/thoughts"
|
||||
echo "and the program is installed in $HOME/.local/bin"
|
||||
}
|
||||
|
||||
# "style" command
|
||||
style () {
|
||||
cd "$stuffDir"
|
||||
git pull
|
||||
"${EDITOR:-vi}" .head.html
|
||||
cat .head.html .rawthoughts.html .foot.html > index.html
|
||||
git add .
|
||||
git commit -m "update css"
|
||||
git push
|
||||
echo
|
||||
echo "Done! CSS updated."
|
||||
}
|
||||
|
||||
|
||||
default () {
|
||||
cd "$stuffDir"
|
||||
# get an editor so we can type our thought.
|
||||
# generate a random temp filename to avoid collisions.
|
||||
# who knows what's in there!
|
||||
rand=$(date | cksum | tr -d ' ')
|
||||
|
||||
"${EDITOR:-vi}" "$rand".txt
|
||||
if [ ! -f "$rand".txt ]; then
|
||||
echo
|
||||
echo "you don't always have to share your thoughts"
|
||||
exit 0
|
||||
fi
|
||||
# If this thought doesn't have a trailing newline, add one
|
||||
tail -c 1 "$rand".txt | read -r _ || echo >> "$rand".txt
|
||||
|
||||
# replace some newlines with <br>
|
||||
# and convert codeblock tag into real one
|
||||
# and linkify things outside of codeblocks
|
||||
awk -f "$stuffDir"/bin/parse.awk "$rand".txt > temp.txt && mv temp.txt "$rand".txt
|
||||
# get the last 4 characters from the file
|
||||
# if they are "<br>", delete them.
|
||||
br=$(tail -c 5 "$rand".txt)
|
||||
if [ "$br" = '<br>' ]; then
|
||||
sed '$ s/.\{4\}$//' "$rand".txt > temp.txt && mv temp.txt "$rand".txt
|
||||
fi
|
||||
thought=$(cat "$rand".txt)
|
||||
|
||||
now=$(date +"%I:%M %p | %Y-%m-%d")
|
||||
dateHash=$(date | cksum | tr -d ' ')
|
||||
blob="<section class=\"thought\"><div class=\"thought-date\"><a class=\"thought-date\" id=\"$dateHash\" href=\"#$dateHash\">\n$now</a></div><div class=\"thought\">\n$thought\n</div></section>\n"
|
||||
|
||||
git pull
|
||||
echo "$blob" | cat - .rawthoughts.html > "$dateHash".html && mv "$dateHash".html .rawthoughts.html
|
||||
cat .head.html .rawthoughts.html .foot.html > index.html
|
||||
git add .
|
||||
git commit -m "update thoughts"
|
||||
git push
|
||||
rm "$rand".txt
|
||||
echo
|
||||
echo "your thoughts have been shared"
|
||||
}
|
||||
|
||||
preview () {
|
||||
cd "$stuffDir"
|
||||
isDone="false"
|
||||
# get an editor so we can type our thought.
|
||||
# generate a random temp filename to avoid collisions.
|
||||
# who knows what's in there!
|
||||
rand=$(date | cksum | tr -d ' ')
|
||||
|
||||
# type the thought
|
||||
while [ "$isDone" = "false" ]
|
||||
do
|
||||
"${EDITOR:-vi}" "$rand".txt
|
||||
if [ ! -f "$rand".txt ]; then
|
||||
echo
|
||||
echo "you don't always have to share your thoughts"
|
||||
exit 0
|
||||
fi
|
||||
cp "$rand.txt" thought.txt
|
||||
|
||||
# turn the thought into HTML
|
||||
tail -c 1 thought.txt | read -r _ || echo >> thought.txt
|
||||
awk -f "$stuffDir"/bin/parse.awk thought.txt > temp.txt && mv temp.txt thought.txt
|
||||
br=$(tail -c 5 thought.txt)
|
||||
if [ "$br" = '<br>' ]; then
|
||||
sed '$ s/.\{4\}$//' thought.txt > temp.txt && mv temp.txt thought.txt
|
||||
fi
|
||||
thought=$(cat thought.txt)
|
||||
now=$(date +"%I:%M %p | %Y-%m-%d")
|
||||
dateHash=$(date | cksum | tr -d ' ')
|
||||
blob="<section class=\"thought\"><div class=\"thought-date\"><a class=\"thought-date\" id=\"$dateHash\" href=\"#$dateHash\">\n$now</a></div><div class=\"thought\">\n$thought\n</div></section>\n"
|
||||
echo "$blob" > thought.txt
|
||||
|
||||
# make the preview page
|
||||
git pull # in case of CSS changes in remote
|
||||
cat .head.html thought.txt .foot.html > preview.html
|
||||
echo
|
||||
echo "Open file:///$HOME/.local/share/thoughts/preview.html in a browser,"
|
||||
echo "or refresh the page if it's already open."
|
||||
echo
|
||||
printf "Do you want to post your thought in its current state? [y/n]: "
|
||||
read -r reply
|
||||
if [ "$reply" = "y" ]; then isDone="true"; fi
|
||||
rm thought.txt preview.html
|
||||
done
|
||||
|
||||
# Commit it
|
||||
git pull
|
||||
echo "$blob" | cat - .rawthoughts.html > "$dateHash".html && mv "$dateHash".html .rawthoughts.html
|
||||
cat .head.html .rawthoughts.html .foot.html > index.html
|
||||
git add .
|
||||
git commit -m "update thoughts"
|
||||
git push
|
||||
rm "$rand".txt
|
||||
echo
|
||||
echo "your thoughts have been shared"
|
||||
}
|
||||
|
||||
case $cmd in
|
||||
"edit")
|
||||
edit
|
||||
;;
|
||||
"style")
|
||||
style
|
||||
;;
|
||||
"preview")
|
||||
preview
|
||||
;;
|
||||
"default")
|
||||
default
|
||||
;;
|
||||
*)
|
||||
help
|
||||
;;
|
||||
esac
|
6
thoughts-gitignore
Normal file
6
thoughts-gitignore
Normal file
|
@ -0,0 +1,6 @@
|
|||
*
|
||||
!index.html
|
||||
!.gitignore
|
||||
!.rawthoughts.html
|
||||
!.head.html
|
||||
!.foot.html
|
Reference in a new issue