#!/bin/sh # acmetodo: Main script to open and manage the todo list in Acme. PLAN9=${PLAN9:-"/Users/eli/plan9"} # Ensure this is your correct PLAN9 path TODO_FILE="$PLAN9/lib/todo" ACME_BIN="$PLAN9/bin/acme" STARTPLUMB_BIN="$PLAN9/bin/startplumb" ACME_FS_ROOT="/acme" # Standard Plan 9 /acme FUSE mount point # --- DEBUGGING START --- DEBUG_LOG="/tmp/acmetodo_debug.log" rm -f "$DEBUG_LOG" # Clear previous log on each run log_debug() { echo "$(date '+%Y-%m-%d %H:%M:%S') [DEBUG] $@" >> "$DEBUG_LOG" echo "$(date '+%H:%M:%S') [DEBUG] $@" >/dev/stderr } log_error() { echo "$(date '+%Y-%m-%d %H:%M:%S') [ERROR] $@" >> "$DEBUG_LOG" echo "$(date '+%H:%M:%S') [ERROR] $@" >/dev/stderr } log_debug "Script started." log_debug "PLAN9 is $PLAN9" log_debug "TODO_FILE is $TODO_FILE" log_debug "ACME_BIN is $ACME_BIN" log_debug "STARTPLUMB_BIN is $STARTPLUMB_BIN" log_debug "Current \$winid (from Acme environment) is '$winid'" # --- DEBUGGING END --- # --- PLUMBER CHECK AND LAUNCH --- log_debug "Checking if plumber is running..." if ! ps aux | grep -q "[p]lumber"; then log_debug "Plumber not found. Attempting to start plumber..." if [ -x "$STARTPLUMB_BIN" ]; then "$STARTPLUMB_BIN" & # Launch plumber in the background log_debug "Plumber launch command issued. Waiting for plumber to initialize..." sleep 1 # Give plumber a moment to fully start else log_error "startplumb executable not found at '$STARTPLUMB_BIN'. Cannot start plumber." exit 1 fi else log_debug "Plumber is already running." fi # --- END PLUMBER CHECK --- # Ensure the lib directory exists mkdir -p "$(dirname "$TODO_FILE")" # Ensure the todo file exists touch "$TODO_FILE" # Function to safely get window ID by name, suppressing stderr from acme -w get_existing_win_id() { # Pipe stderr of acme -w to /dev/null to suppress the "usage" message "$ACME_BIN" -w 2>/dev/null | grep "^$TODO_FILE " | cut -d' ' -f1 | head -n 1 } # Function to update a window's content, name, and tag update_todo_window() { local win_id="$1" log_debug "Function update_todo_window called for win_id: $win_id" # 1. Set the window's name log_debug "Attempting to set window $win_id name to '$TODO_FILE'" echo "name $TODO_FILE" | "$ACME_BIN" -a "$win_id" if [ $? -ne 0 ]; then log_error "Failed to send 'name' command to window $win_id." fi sleep 0.05 # Small delay to ensure command is processed # 2. Set the window's tag log_debug "Attempting to set window $win_id tag." echo 'tag Get Put | Add | Todo InProgress Done All | Quit' | "$ACME_BIN" -a "$win_id" if [ $? -ne 0 ]; then log_error "Failed to send 'tag' command to window $win_id." fi sleep 0.05 # Small delay # 3. Load content directly into the window's body log_debug "Attempting to write content to window $win_id body." if [ -f "$TODO_FILE" ]; then log_debug "Reading content from '$TODO_FILE' and piping to $win_id body." cat "$TODO_FILE" | "$ACME_BIN" -a "$win_id" body if [ $? -ne 0 ]; then log_error "Failed to write content to window $win_id body from $TODO_FILE." fi else log_debug "TODO_FILE '$TODO_FILE' does not exist or is not readable. Writing initial content." echo "## Acme To-Do List" | "$ACME_BIN" -a "$win_id" body if [ $? -ne 0 ]; then log_error "Failed to write initial content to window $win_id body." fi fi echo 'clean' | "$ACME_BIN" -a "$win_id" # Mark window as clean after setting content log_debug "Finished updating window $win_id." } # --- MAIN LOGIC --- if [ -n "$winid" ]; then log_debug "Running in Case 1: Script called from an existing Acme window." update_todo_window "$winid" else # Always try to find existing window first EXISTING_TODO_WINID=$(get_existing_win_id) log_debug "EXISTING_TODO_WINID (found by checking existing Acme windows) is '$EXISTING_TODO_WINID'" if [ -n "$EXISTING_TODO_WINID" ]; then log_debug "Running in Case 2: Script called from terminal, existing todo window found." update_todo_window "$EXISTING_TODO_WINID" else log_debug "Running in Case 3: Script called from terminal, new todo window needed." # Capture the highest window ID *before* opening a new one PRE_NEW_WIN_ID=$(ls -d "$ACME_FS_ROOT"/[0-9]* 2>/dev/null | sort -V | tail -n 1 | xargs basename) log_debug "Highest existing Acme window ID before new creation: '$PRE_NEW_WIN_ID'" # 1. Open a new, empty Acme window. Don't try to capture its ID directly, as it's unreliable. log_debug "Attempting to create a new Acme window with '$ACME_BIN -l /dev/null'." "$ACME_BIN" -l /dev/null 2>/dev/null & # Run in background and suppress stderr # Give Acme a moment to open the window sleep 0.5 # 2. Find the ID of the newly created window (should be the highest now) NEW_WIN_ID=$(ls -d "$ACME_FS_ROOT"/[0-9]* 2>/dev/null | sort -V | tail -n 1 | xargs basename) log_debug "Highest existing Acme window ID after new creation: '$NEW_WIN_ID'" if [ -z "$NEW_WIN_ID" ] || [ "$NEW_WIN_ID" = "$PRE_NEW_WIN_ID" ]; then log_error "Failed to create a new Acme window or get its ID correctly." log_error "Possible causes: Acme not running, or its communication with plumber failed, or the FUSE mount is inaccessible." exit 1 fi # 3. Call the update function for the new window log_debug "Calling update_todo_window for the newly created ID: $NEW_WIN_ID" update_todo_window "$NEW_WIN_ID" fi fi log_debug "Script finished."