1 Commits

Author SHA1 Message Date
Alexander Whitestone
9dc47845cf feat: enhance aw-post CLI — --from-x, --file, --help flags (#219)
- --from-x "text": port X/Twitter posts (title from first 60 chars)
- --file path.md: post from markdown file (title from # header)
- --help: usage info
- Refactored into functions for reuse
- All modes auto-rebuild the blog after posting

Closes #219
2026-03-18 21:45:50 -04:00
2 changed files with 85 additions and 32 deletions

View File

@@ -4,7 +4,7 @@
<link href="https://alexanderwhitestone.com/blog/"/>
<link rel="self" href="https://alexanderwhitestone.com/blog/feed.xml"/>
<id>https://alexanderwhitestone.com/blog/</id>
<updated>2026-03-19T01:42:22Z</updated>
<updated>2026-03-19T01:45:33Z</updated>
<author>
<name>Alexander Whitestone</name>
</author>

View File

@@ -2,51 +2,104 @@
# aw-post — Quick-post a scroll from the command line
#
# Usage:
# aw-post "Title of the Post"
# aw-post "Title" < body.md
# echo "Post body here" | aw-post "Title"
# aw-post "Title" # Create empty post, open for editing
# aw-post "Title" < body.md # Pipe body from stdin
# echo "Post body" | aw-post "Title" # Pipe body from stdin
# aw-post --file thoughts.md # Post from a file (title from first line)
# aw-post --from-x "Tweet text here" # Port an X/Twitter post
#
# Creates a new markdown file in blog/posts/ with frontmatter,
# then rebuilds the blog index, post pages, and RSS feed.
# Creates a markdown file in blog/posts/, rebuilds the blog.
set -euo pipefail
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
BLOG_DIR="${REPO_DIR}/blog/posts"
if [ $# -lt 1 ]; then
echo "Usage: aw-post \"Title of the Post\""
echo " Pipe or redirect body content via stdin."
exit 1
fi
TITLE="$1"
DATE=$(date +%Y-%m-%d)
SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-')
FILENAME="${DATE}-${SLUG}.md"
FILEPATH="${BLOG_DIR}/${FILENAME}"
if [ -f "$FILEPATH" ]; then
echo "Error: $FILEPATH already exists"
exit 1
fi
slugify() {
echo "$1" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-' | head -c 60
}
# Read body from stdin if available
BODY=""
if [ ! -t 0 ]; then
BODY=$(cat)
fi
create_post() {
local title="$1"
local body="$2"
local slug
slug=$(slugify "$title")
local filename="${DATE}-${slug}.md"
local filepath="${BLOG_DIR}/${filename}"
cat > "$FILEPATH" << EOF
if [ -f "$filepath" ]; then
echo "Error: $filepath already exists"
exit 1
fi
cat > "$filepath" << EOF
---
title: "${TITLE}"
title: "${title}"
date: ${DATE}
---
${BODY}
${body}
EOF
echo "Created: ${FILEPATH}"
echo "Created: ${filepath}"
python3 "${REPO_DIR}/scripts/build.py"
}
# Rebuild the blog
python3 "${REPO_DIR}/scripts/build.py"
# Parse arguments
case "${1:-}" in
--file)
# Post from a file — title from first non-empty line
if [ -z "${2:-}" ] || [ ! -f "${2:-}" ]; then
echo "Usage: aw-post --file <path-to-markdown>"
exit 1
fi
BODY=$(cat "$2")
# Extract title: first line starting with # or first non-empty line
TITLE=$(echo "$BODY" | grep -m1 '^#' | sed 's/^#* *//' || echo "$BODY" | grep -m1 '.' || echo "Untitled")
if [ -z "$TITLE" ]; then
TITLE="Untitled"
fi
# Strip the title line from body if it was a markdown header
BODY=$(echo "$BODY" | sed '1{/^#/d;}')
create_post "$TITLE" "$BODY"
;;
--from-x)
# Port an X/Twitter post — the text becomes both title and body
if [ -z "${2:-}" ]; then
echo "Usage: aw-post --from-x \"Tweet text here\""
exit 1
fi
TEXT="$2"
# Title: first 60 chars, cleaned up
TITLE=$(echo "$TEXT" | head -1 | cut -c1-60 | sed 's/[[:space:]]*$//')
create_post "$TITLE" "$TEXT"
;;
--help|-h)
echo "aw-post — Quick-post a scroll to The Scrolls"
echo ""
echo "Usage:"
echo " aw-post \"Title\" Create a post (body from stdin)"
echo " aw-post --file thoughts.md Post from a markdown file"
echo " aw-post --from-x \"Tweet text\" Port an X/Twitter post"
echo " aw-post --help Show this help"
;;
"")
echo "Usage: aw-post \"Title of the Post\""
echo " See: aw-post --help"
exit 1
;;
*)
# Standard mode: title as arg, body from stdin
TITLE="$1"
BODY=""
if [ ! -t 0 ]; then
BODY=$(cat)
fi
create_post "$TITLE" "$BODY"
;;
esac