#!/usr/bin/env python3 # The Spartan Bookmark Launcher (sbl) with embedded bookmarks # This project is licensed under the Blue Oak Model License 1.0.0. # See: https://blueoakcouncil.org/license/1.0.0 # Ver 1.0 : initial release (09may2025) # ver 2.0 : Major changes.. (07jun2025) # . embedded the bookmarks directly into the script (portability) # . display only titles from the embedded bookmarks # . added support for comments in the bookmark section # . new '-edit' flag opens script in default editor (configurable) # Supported Help Flags: -h --help -? /? (more, see below) # Install: chmod +x sbl && sudo install sbl /usr/local/bin # Uninstall: sudo rm /usr/local/bin/sbl import sys import os import subprocess # ============================================================================= # CONFIGURATION - Edit these values if needed # ============================================================================= DEFAULT_EDITOR = "/usr/bin/xed" # Change this to your preferred editor # ============================================================================= # ============================================================================= # EMBEDDED BOOKMARKS - Edit this section to customize your bookmarks # Format: # "Title: spartan://url" # Comments start with # # ============================================================================= EMBEDDED_BOOKMARKS = """ # All sample URLs collected from the Spartan Home Page # Alignment below (ASCII Art) is not necessary. I did it for readability. Spartan Home Page: spartan://mozz.us Spartan Specifications: spartan://spartan.mozz.us Software for the Spartan Protocol: spartan://mozz.us/software.gmi # A great collection of ASCII Art begins Alt-ASCII-Art FAQ: spartan://ascii.mozz.us:7070/academy/faqs/faq_randall.txt Rowan Crawford ASCII Art: spartan://ascii.mozz.us:7070/mirrors/afn/artists/crawford.txt The Funny Bone (1998): spartan://ascii.mozz.us:7070/mirrors/funnybone/1998/funnybone_1998-09-13.txt Bob Allison's collection: spartan://ascii.mozz.us:7070/mirrors/incredibleart/files/scarecrow_sig_files.txt Six Line Ascii Art Challenge: spartan://ascii.mozz.us:7070/mirrors/vk/files/junkyard/pics/six_line_challenge.txt ASCII Artist Licenses: spartan://ascii.mozz.us:7070/academy/artists/license.txt # Add more bookmarks below this line... (or edit this section in any way) # ============================= End Bookmarks =============================== """ # ============================================================================= def show_help(): script_name = os.path.basename(sys.argv[0]) print(f""" SBL: Spartan Bookmark Launcher (with embedded bookmarks) Shows a numbered list of URL page titles. Selecting a number, displays that URL using 'sv' and 'less'. After exiting, the list redisplays. Usage: sbl - Show and launch embedded bookmarks sbl -edit - Edit this script (sudo if script installed) sbl -h - Show this help message Edit bookmarks: 1. Run: sbl -edit 2. Modify the EMBEDDED_BOOKMARKS section 3. Save the file (sudo if script installed) Bookmark format: Page Title: spartan://example.com Lines starting with '#' (comments) and blank lines are ignored. Requires: The Spartan Viewer (sv) https://640kb.neocities.org/apps/apps.html finger spartanviewer@happynetbox.com """) def parse_embedded_bookmarks(): """Parse bookmarks from the embedded string""" bookmarks = [] lines = EMBEDDED_BOOKMARKS.splitlines() for line in lines: # Strip whitespace and skip empty lines stripped = line.strip() if not stripped: continue # Skip comment lines (starting with #) if stripped.startswith('#'): continue if ':' in line: title, url = line.split(':', 1) title = title.strip() url = url.strip() if url.startswith("spartan://"): bookmarks.append((title, url)) return bookmarks def display_bookmarks(bookmarks): os.system('clear') # Clear the screen for a clean view if not bookmarks: print("No bookmarks available. Please edit the embedded bookmarks section.") return longest = max(len(title) for title, _ in bookmarks) header_width = max(longest + 10, 30) # Ensure minimum width of 30 print("=" * header_width) print("SPARTAN BOOKMARK MANAGER".center(header_width)) print("=" * header_width) for idx, (title, _) in enumerate(bookmarks, 1): print(f"[{idx:2}] {title}") print() print("List of bookmarks embedded in this script") print("=" * header_width) def edit_script(): """Open the script in the default editor with sudo""" script_path = os.path.abspath(__file__) try: subprocess.run(["sudo", DEFAULT_EDITOR, script_path], check=True) except subprocess.CalledProcessError: print(f"Failed to open editor. You may need to:") print(f"1. Change DEFAULT_EDITOR in the script") print(f"2. Ensure {DEFAULT_EDITOR} is installed") sys.exit(1) def main(): help_flags = {'-h', '--h', '-help', '--help', '-?', '/?'} if len(sys.argv) > 1: if sys.argv[1].lower() in help_flags: show_help() sys.exit(0) elif sys.argv[1].lower() == "-edit": edit_script() sys.exit(0) else: show_help() sys.exit(1) bookmarks = parse_embedded_bookmarks() if not bookmarks: print("No valid bookmarks found in embedded section.") sys.exit(1) while True: display_bookmarks(bookmarks) try: choice = input("Enter number to open (0 to quit): ").strip() if choice == '0': break index = int(choice) - 1 if 0 <= index < len(bookmarks): url = bookmarks[index][1] subprocess.run(f"sv {url} | less -R", shell=True) else: print("Invalid choice.") input("Press Enter to continue...") except ValueError: print("Invalid input.") input("Press Enter to continue...") except KeyboardInterrupt: print("\nCanceled.") break if __name__ == "__main__": main()