restructure: move backend/ and layout/ into src/; convert README to org syntax; fix demo package conflict and alien-sap ioctl; update ROADMAP with v0.15.0; remove stale files
- Move backend/ and layout/ directories into src/ - Update all path references in ASD, scripts, docs - Convert README.org from Markdown syntax to proper Org-mode - Fix demo.lisp use-package conflict (both backend and input export #:read-event) - Fix modern-backend TIOCGWINSZ ioctl alien type (alien-sap wrapper) - Add v0.15.0 section to ROADMAP, update line count to 5760 - Add known gaps (suspend/resume-backend, slot modes) to v1.0.0 checklist - Remove docs/plans/, debug-layout.lisp, system-index.txt, ci-watchdog.sh - Move tangle.py to Hermes skill (org-babel-tangle) - Add .gitignore for fasl files
This commit is contained in:
@@ -26,9 +26,9 @@
|
||||
*results*)))))
|
||||
|
||||
(let ((files
|
||||
'("backend/classes.lisp" "backend/package.lisp"
|
||||
"backend/detection.lisp" "backend/simple.lisp" "backend/modern.lisp"
|
||||
"layout/layout.lisp"
|
||||
'("src/backend/classes.lisp" "src/backend/package.lisp"
|
||||
"src/backend/detection.lisp" "src/backend/simple.lisp" "src/backend/modern.lisp"
|
||||
"src/layout/layout.lisp"
|
||||
"src/components/container-package.lisp"
|
||||
"src/components/dialog-package.lisp" "src/components/dialog.lisp"
|
||||
"src/components/dirty.lisp"
|
||||
@@ -45,8 +45,8 @@
|
||||
"src/components/box.lisp"
|
||||
"src/rendering/framebuffer.lisp"
|
||||
"demo.lisp"
|
||||
"backend/modern-tests.lisp" "backend/tests.lisp"
|
||||
"layout/tests.lisp"
|
||||
"src/backend/modern-tests.lisp" "src/backend/tests.lisp"
|
||||
"src/layout/tests.lisp"
|
||||
"src/components/box-tests.lisp" "src/components/dirty-tests.lisp"
|
||||
"src/components/render-tests.lisp" "src/components/theme-tests.lisp"
|
||||
"src/components/input-tests.lisp"
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Watchdog script: checks if the latest commit on the active branch is new,
|
||||
# runs the full test suite if so.
|
||||
# Designed to run every 15 minutes via Hermes cron.
|
||||
# Prints output only when tests are run (silent otherwise).
|
||||
|
||||
cd /mnt/hermes/projects/cl-tty || exit 1
|
||||
|
||||
STATE_FILE="/tmp/.cl-tty-ci-last-commit"
|
||||
BRANCH="feature/v0.11.0-slots"
|
||||
|
||||
# Fetch latest
|
||||
git fetch origin "$BRANCH" 2>/dev/null || exit 0
|
||||
LATEST=$(git rev-parse "origin/$BRANCH" 2>/dev/null) || exit 0
|
||||
|
||||
# Check against last seen
|
||||
if [ -f "$STATE_FILE" ]; then
|
||||
LAST_SEEN=$(cat "$STATE_FILE")
|
||||
[ "$LATEST" = "$LAST_SEEN" ] && exit 0 # No new commits, silent exit
|
||||
fi
|
||||
|
||||
# New commit found! Save it and run tests
|
||||
echo "$LATEST" > "$STATE_FILE"
|
||||
|
||||
COMMIT_MSG=$(git log --oneline "origin/$BRANCH" -1 2>/dev/null)
|
||||
echo "New commit on $BRANCH: $COMMIT_MSG"
|
||||
echo ""
|
||||
echo "=== Running Tier 1: Unit Tests ==="
|
||||
sbcl --noinform --eval '(load "~/quicklisp/setup.lisp")' \
|
||||
--eval '(push (truename ".") asdf:*central-registry*)' \
|
||||
--eval '(asdf:test-system :cl-tty)' --eval '(uiop:quit 0)' \
|
||||
2>&1 | grep -E "Fail:|Pass:|Did|Running test"
|
||||
echo ""
|
||||
|
||||
echo "=== Running Tier 2: API Verification ==="
|
||||
python3 scripts/verify-api.py 2>&1 | tail -3
|
||||
echo ""
|
||||
|
||||
echo "=== Running Tier 3: PTY Demo Test ==="
|
||||
python3 scripts/verify-demo-pty.py 2>&1 | tail -3
|
||||
echo ""
|
||||
|
||||
echo "Done."
|
||||
@@ -25,9 +25,9 @@
|
||||
|
||||
;; Load all source files directly to catch per-file warnings
|
||||
(let ((files
|
||||
'("backend/classes.lisp" "backend/package.lisp"
|
||||
"backend/detection.lisp" "backend/simple.lisp" "backend/modern.lisp"
|
||||
"layout/layout.lisp"
|
||||
'("src/backend/classes.lisp" "src/backend/package.lisp"
|
||||
"src/backend/detection.lisp" "src/backend/simple.lisp" "src/backend/modern.lisp"
|
||||
"src/layout/layout.lisp"
|
||||
"src/components/container-package.lisp"
|
||||
"src/components/dialog-package.lisp" "src/components/dialog.lisp"
|
||||
"src/components/dirty.lisp"
|
||||
@@ -49,8 +49,8 @@
|
||||
(load f))))
|
||||
|
||||
;; Also run the test files for good measure
|
||||
(dolist (f '("backend/tests.lisp" "backend/modern-tests.lisp"
|
||||
"layout/tests.lisp"
|
||||
(dolist (f '("src/backend/tests.lisp" "src/backend/modern-tests.lisp"
|
||||
"src/layout/tests.lisp"
|
||||
"src/components/box-tests.lisp"
|
||||
"src/components/dirty-tests.lisp"
|
||||
"src/components/render-tests.lisp"
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Simple org-babel tangle replacement.
|
||||
Extracts #+BEGIN_SRC blocks with :tangle headers and writes target files.
|
||||
"""
|
||||
import re, os, sys
|
||||
|
||||
ORG_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
def tangle_file(org_path):
|
||||
org_path = os.path.join(ORG_DIR, org_path)
|
||||
with open(org_path) as f:
|
||||
text = f.read()
|
||||
|
||||
# Find all #+BEGIN_SRC blocks with :tangle
|
||||
pattern = re.compile(
|
||||
r'#\+BEGIN_SRC\s+(\w+)\s+(.*?)\n(.*?)\n#\+END_SRC',
|
||||
re.DOTALL
|
||||
)
|
||||
|
||||
count = 0
|
||||
block_count = {}
|
||||
for match in pattern.finditer(text):
|
||||
lang = match.group(1)
|
||||
header = match.group(2)
|
||||
content = match.group(3)
|
||||
|
||||
# Extract :tangle path
|
||||
tangle_match = re.search(r':tangle\s+(\S+)', header)
|
||||
if not tangle_match:
|
||||
continue
|
||||
tangle_path = tangle_match.group(1)
|
||||
|
||||
# Resolve relative path
|
||||
if tangle_path.startswith('../'):
|
||||
target = os.path.normpath(os.path.join(os.path.dirname(org_path), tangle_path))
|
||||
else:
|
||||
target = os.path.join(ORG_DIR, tangle_path)
|
||||
|
||||
# Ensure directory exists
|
||||
os.makedirs(os.path.dirname(target), exist_ok=True)
|
||||
|
||||
# Don't write :tangle no blocks
|
||||
if tangle_path == 'no':
|
||||
continue
|
||||
|
||||
# Write the content (write mode — each run produces clean files)
|
||||
content = content.rstrip('\n') + '\n'
|
||||
if os.path.exists(target) and block_count.get(target, 0) == 0:
|
||||
with open(target, 'w') as f:
|
||||
f.write(content)
|
||||
elif os.path.exists(target):
|
||||
with open(target, 'a') as f:
|
||||
f.write('\n' + content)
|
||||
else:
|
||||
with open(target, 'w') as f:
|
||||
f.write(content)
|
||||
block_count[target] = block_count.get(target, 0) + 1
|
||||
print(f" {target} ({len(content)} bytes)")
|
||||
count += 1
|
||||
|
||||
return count
|
||||
|
||||
if __name__ == '__main__':
|
||||
for f in sys.argv[1:] or ['org/text-input.org']:
|
||||
print(f"Tangling {f}...")
|
||||
c = tangle_file(f)
|
||||
print(f" {c} code blocks")
|
||||
@@ -96,7 +96,7 @@ size = len(output)
|
||||
check("Output is non-empty", size > 100, f"got {size} bytes")
|
||||
check("Shows title 'cl-tty'", has_text(output, "cl-tty"))
|
||||
check("Shows component list", has_text(output, "TextInput"))
|
||||
check("Shows test count", has_text(output, "392"))
|
||||
check("Shows test count", has_text(output, "483"))
|
||||
check("Shows controls help", has_text(output, "Ctrl+C"))
|
||||
check("Shows tab bar items", has_text(output, "Home"))
|
||||
check("Shows Console tab", has_text(output, "Console"))
|
||||
|
||||
Reference in New Issue
Block a user