hyperlist 1.1.7 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7963687b87c7d271d9e45e5574e7af4edb900e49cc60a567774e4be54a386f51
4
- data.tar.gz: '055148f7bc87ab9af632b5ad52eae9a367bdc8b4c84c8bbff28ed5686502e30a'
3
+ metadata.gz: aef5338683dfa697e59042f093e0db9a748ef53515952a295b1c9eb972519ac5
4
+ data.tar.gz: fbad5a0f6022d40cfd147846d3de81b317b41fff39036c9085a0230fc0a144c4
5
5
  SHA512:
6
- metadata.gz: 17a562ee3ccdbcd2434c7a6fc5b08f3bccb696fb0a0100e735ea7e5f5e267021de31c0b9c8007dd4990818e236d9d0f7a87cebeed4384b69161202e0f1f6f8c9
7
- data.tar.gz: 27a237a412326e4f45fa17cd7b622bfa5073f39a4b2f87ce1bc6af264eb0506d2f663b39338cd66738b54f95e7ccd48d85838c58eb6bad7c15ec84e007bd68dc
6
+ metadata.gz: fd23aaaaa0ffbb7b1d73fdc99a46d3fb08d265000e1e10651e747857a4ab5d78dbf523d967e87d4ca82a1f0f8ff46d3fc563cec4441c3a86de7a3651f0cb41e6
7
+ data.tar.gz: 98ae50b53b8a9b4578ed50c81b8dcd763af2273f44bca200f27627cdc808f61b620baa0d76c09a9a776107de3de637e50c1daf660c7c77903debb8ee1868909d
data/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  All notable changes to the HyperList Ruby TUI will be documented in this file.
4
4
 
5
+ ## [1.2.0] - 2025-08-20
6
+
7
+ ### Added
8
+ - **User-Defined Templates**
9
+ - Save any HyperList document as a reusable template (`:st` or `:save-template`)
10
+ - Template manager for listing and deleting custom templates (`:lt`, `:dt`)
11
+ - Enhanced template browser showing both built-in and user templates
12
+ - Template metadata including description and creation date
13
+ - Templates stored in `~/.hyperlist/templates/` for easy backup and sharing
14
+ - JSON format for template storage with full hierarchy preservation
15
+
16
+ ### Changed
17
+ - Template system now supports both built-in and user-created templates
18
+ - Template browser UI improved with separate sections for built-in vs user templates
19
+ - Help documentation updated with new template commands
20
+
5
21
  ## [1.1.7] - 2025-08-15
6
22
 
7
23
  ### Fixed
data/README.md CHANGED
@@ -6,7 +6,8 @@
6
6
  [![GitHub stars](https://img.shields.io/github/stars/isene/HyperList.svg)](https://github.com/isene/HyperList/stargazers)
7
7
  [![Stay Amazing](https://img.shields.io/badge/Stay-Amazing-blue.svg)](https://isene.org)
8
8
 
9
- <img src="hyperlist_logo.svg" align="left" width="150" height="150">
9
+ <img src="img/hyperlist_logo.svg" align="left" width="150" height="150">
10
+ <br clear="left"/>
10
11
 
11
12
  A powerful Terminal User Interface (TUI) application for creating, editing, and managing HyperLists - a methodology for describing anything in a hierarchical, structured format.
12
13
 
@@ -23,12 +24,21 @@ For historical context and the original VIM implementation, see: [hyperlist.vim]
23
24
  ## Screenshots
24
25
 
25
26
  ### Main Interface
26
- ![HyperList Main View](screenshot_sample.png)
27
+ ![HyperList Main View](img/screenshot_sample.png)
27
28
 
28
29
  ### Help Screen
29
- ![HyperList Help](screenshot_help.png)
30
+ ![HyperList Help](img/screenshot_help.png)
31
+
32
+ ## What's New in v1.2.0
30
33
 
31
- ## What's New in v1.1.0
34
+ ### 📝 User-Defined Templates
35
+ - **Save as Template**: Save any HyperList document as a reusable template (`:st`)
36
+ - **Template Manager**: List and delete your custom templates (`:lt`, `:dt`)
37
+ - **Enhanced Template Browser**: Shows both built-in and user templates
38
+ - **Template Metadata**: Includes description and creation date
39
+ - Templates stored in `~/.hyperlist/templates/` for easy backup and sharing
40
+
41
+ ## Previous Updates (v1.1.0)
32
42
 
33
43
  ### 🔐 Encryption Support
34
44
  - **File-level encryption** for sensitive files (dot files like `.passwords.hl`)
@@ -62,7 +72,7 @@ For historical context and the original VIM implementation, see: [hyperlist.vim]
62
72
  - **Powerful Navigation**: Jump between items, references, and markers
63
73
  - **Full Editing Capabilities**: Create, edit, delete, move, and reorganize items
64
74
  - **Checkbox Support**: Multiple checkbox types with completion tracking
65
- - **Template System**: Jump to and fill in template markers
75
+ - **Template System**: Built-in templates plus save/load custom templates
66
76
  - **Presentation Mode**: Focus on current item with auto-collapse
67
77
 
68
78
  ### Security Features
@@ -158,6 +168,7 @@ hyperlist file.txt # Open any text file
158
168
  - `R` - Go to reference
159
169
  - `F` - Open file reference
160
170
  - `P` - Presentation mode (with auto-collapse)
171
+ - `t` - Insert template (built-in or custom)
161
172
  - `?` - Help screen
162
173
 
163
174
  #### File Commands
@@ -169,6 +180,12 @@ hyperlist file.txt # Open any text file
169
180
  - `:export md` - Export to Markdown
170
181
  - `:graph` - Export to PNG
171
182
 
183
+ #### Template Commands
184
+ - `:st` - Save current document as template
185
+ - `:dt` - Delete a user template
186
+ - `:lt` - List all user templates
187
+ - `t` - Browse and insert templates
188
+
172
189
  ## Examples
173
190
 
174
191
  ### Simple Todo List
data/hyperlist CHANGED
@@ -7,7 +7,7 @@
7
7
  # Check for help/version BEFORE loading any libraries
8
8
  if ARGV[0] == '-h' || ARGV[0] == '--help'
9
9
  puts <<~HELP
10
- HyperList v1.1.7 - Terminal User Interface for HyperList files
10
+ HyperList v1.2.0 - Terminal User Interface for HyperList files
11
11
 
12
12
  USAGE
13
13
  hyperlist [OPTIONS] [FILE]
@@ -52,7 +52,7 @@ if ARGV[0] == '-h' || ARGV[0] == '--help'
52
52
  HELP
53
53
  exit 0
54
54
  elsif ARGV[0] == '-v' || ARGV[0] == '--version'
55
- puts "HyperList v1.1.7"
55
+ puts "HyperList v1.2.0"
56
56
  exit 0
57
57
  end
58
58
 
@@ -64,13 +64,15 @@ require 'cgi'
64
64
  require 'openssl'
65
65
  require 'digest'
66
66
  require 'base64'
67
+ require 'fileutils'
68
+ require 'json'
67
69
 
68
70
  class HyperListApp
69
71
  include Rcurses
70
72
  include Rcurses::Input
71
73
  include Rcurses::Cursor
72
74
 
73
- VERSION = "1.1.7"
75
+ VERSION = "1.2.0"
74
76
 
75
77
  def initialize(filename = nil)
76
78
  @filename = filename ? File.expand_path(filename) : nil
@@ -98,6 +100,8 @@ class HyperListApp
98
100
  @auto_save_enabled = false
99
101
  @auto_save_interval = 60 # seconds
100
102
  @last_auto_save = Time.now
103
+ @templates_dir = File.expand_path("~/.hyperlist/templates")
104
+ ensure_templates_dir
101
105
  @templates = load_templates
102
106
  @macro_recording = false
103
107
  @macro_register = {} # Store macros by key
@@ -136,8 +140,11 @@ class HyperListApp
136
140
  end
137
141
 
138
142
  def setup_ui
139
- Rcurses.clear_screen
140
- Cursor.hide
143
+ # Only do rcurses operations if initialized
144
+ if defined?(Rcurses.instance_variable_get) && Rcurses.instance_variable_get(:@initialized)
145
+ Rcurses.clear_screen
146
+ Cursor.hide
147
+ end
141
148
 
142
149
  # Ensure we have the latest terminal size
143
150
  if IO.console
@@ -2169,7 +2176,7 @@ class HyperListApp
2169
2176
  help_lines << help_line("#{"C-E".fg("10")}", "Encrypt/decrypt line", "#{"C-U".fg("10")}", "Toggle State/Trans underline")
2170
2177
  help_lines << help_line("#{"R".fg("10")}", "Go to reference", "#{"F".fg("10")}", "Open file")
2171
2178
  help_lines << help_line("#{"N".fg("10")}", "Next = marker", "#{"P".fg("10")}", "Presentation mode")
2172
- help_lines << help_line("#{"t".fg("10")}", "Insert template", "#{":template".fg("10")}", "Show templates")
2179
+ help_lines << help_line("#{"t".fg("10")}", "Insert template", "#{":st".fg("10")}", "Save as template")
2173
2180
  help_lines << help_line("#{"Ma".fg("10")}", "Record macro 'a'", "#{"@a".fg("10")}", "Play macro 'a'")
2174
2181
  help_lines << help_line("#{":vsplit".fg("10")}", "Split view vertically", "#{"w".fg("10")}", "Switch panes")
2175
2182
  help_lines << ""
@@ -2180,6 +2187,11 @@ class HyperListApp
2180
2187
  help_lines << help_line("#{":graph :g".fg("10")}", "Export to PNG graph", "#{":vsplit :vs".fg("10")}", "Split view")
2181
2188
  help_lines << help_line("#{":as on".fg("10")}", "Enable autosave", "#{":as off".fg("10")}", "Disable autosave")
2182
2189
  help_lines << help_line("#{":as N".fg("10")}", "Set interval (secs)", "#{":as".fg("10")}", "Show autosave status")
2190
+ help_lines << ""
2191
+ help_lines << "#{"TEMPLATES".fg("14")}"
2192
+ help_lines << help_line("#{":st".fg("10")}", "Save as template", "#{":dt".fg("10")}", "Delete template")
2193
+ help_lines << help_line("#{":lt".fg("10")}", "List user templates", "#{"t".fg("10")}", "Insert template")
2194
+ help_lines << ""
2183
2195
  help_lines << help_line("#{"q".fg("10")}", "Quit (asks to save)", "#{"Q".fg("10")}", "Force quit")
2184
2196
  help_lines << ""
2185
2197
  help_lines << "#{"COLOR SCHEME".fg("14")}"
@@ -2853,8 +2865,18 @@ class HyperListApp
2853
2865
  when "autosave", "as"
2854
2866
  status = @auto_save_enabled ? "enabled" : "disabled"
2855
2867
  @message = "Auto-save is #{status} (interval: #{@auto_save_interval}s)"
2856
- when "t"
2868
+ when "t", "template", "templates"
2857
2869
  show_templates
2870
+ when "save-template", "savetemplate", "st"
2871
+ save_as_template
2872
+ when /^save-template\s+(.+)/, /^savetemplate\s+(.+)/, /^st\s+(.+)/
2873
+ save_as_template($1.strip)
2874
+ when "delete-template", "deletetemplate", "dt"
2875
+ delete_template
2876
+ when /^delete-template\s+(.+)/, /^deletetemplate\s+(.+)/, /^dt\s+(.+)/
2877
+ delete_template($1.strip)
2878
+ when "list-templates", "listtemplates", "lt"
2879
+ show_template_manager(:list)
2858
2880
  when "foldlevel"
2859
2881
  level = @footer.ask("Fold to level (0-9): ", "")
2860
2882
  if level =~ /^[0-9]$/
@@ -3202,8 +3224,13 @@ class HyperListApp
3202
3224
  end
3203
3225
  end
3204
3226
 
3227
+ def ensure_templates_dir
3228
+ FileUtils.mkdir_p(@templates_dir) unless File.exist?(@templates_dir)
3229
+ end
3230
+
3205
3231
  def load_templates
3206
- {
3232
+ # Start with built-in templates
3233
+ templates = {
3207
3234
  "project" => [
3208
3235
  {"text" => "Project: =Project Name=", "level" => 0},
3209
3236
  {"text" => "[_] Define project scope", "level" => 1},
@@ -3306,6 +3333,214 @@ class HyperListApp
3306
3333
  {"text" => "=Tips, variations, serving suggestions=", "level" => 2}
3307
3334
  ]
3308
3335
  }
3336
+
3337
+ # Load user templates from templates directory
3338
+ if File.directory?(@templates_dir)
3339
+ Dir.glob(File.join(@templates_dir, "*.hlt")).each do |template_file|
3340
+ template_name = File.basename(template_file, ".hlt")
3341
+ begin
3342
+ template_data = JSON.parse(File.read(template_file))
3343
+ # Convert template data to the expected format
3344
+ if template_data.is_a?(Hash) && template_data["items"]
3345
+ templates[template_name] = template_data["items"].map do |item|
3346
+ {"text" => item["text"], "level" => item["level"]}
3347
+ end
3348
+ end
3349
+ rescue => e
3350
+ # Skip invalid template files
3351
+ end
3352
+ end
3353
+ end
3354
+
3355
+ templates
3356
+ end
3357
+
3358
+ def save_as_template(name = nil)
3359
+ # Ask for template name if not provided
3360
+ if name.nil? || name.empty?
3361
+ name = @footer.ask("Template name: ", "")
3362
+ return if name.nil? || name.empty?
3363
+ end
3364
+
3365
+ # Sanitize template name
3366
+ name = name.gsub(/[^a-zA-Z0-9_-]/, '_')
3367
+
3368
+ # Ask for description
3369
+ description = @footer.ask("Template description (optional): ", "")
3370
+
3371
+ # Prepare template data
3372
+ template_data = {
3373
+ "name" => name,
3374
+ "description" => description,
3375
+ "created" => Time.now.strftime("%Y-%m-%dT%H:%M:%S"),
3376
+ "items" => @items.map do |item|
3377
+ {
3378
+ "text" => item["text"],
3379
+ "level" => item["level"]
3380
+ }
3381
+ end
3382
+ }
3383
+
3384
+ # Save template file
3385
+ template_path = File.join(@templates_dir, "#{name}.hlt")
3386
+
3387
+ # Check if template already exists
3388
+ if File.exist?(template_path)
3389
+ response = @footer.ask("Template '#{name}' already exists. Overwrite? (y/n): ", "")
3390
+ return unless response.downcase == 'y'
3391
+ end
3392
+
3393
+ File.write(template_path, JSON.pretty_generate(template_data))
3394
+ @message = "Template '#{name}' saved successfully"
3395
+ end
3396
+
3397
+ def delete_template(name = nil)
3398
+ # Get list of user templates
3399
+ user_templates = get_user_templates
3400
+
3401
+ if user_templates.empty?
3402
+ @message = "No user templates found"
3403
+ return
3404
+ end
3405
+
3406
+ # Show template list if name not provided
3407
+ if name.nil? || name.empty?
3408
+ show_template_manager(:delete)
3409
+ return
3410
+ end
3411
+
3412
+ template_path = File.join(@templates_dir, "#{name}.hlt")
3413
+
3414
+ if File.exist?(template_path)
3415
+ response = @footer.ask("Delete template '#{name}'? (y/n): ", "")
3416
+ if response.downcase == 'y'
3417
+ File.delete(template_path)
3418
+ @message = "Template '#{name}' deleted"
3419
+ # Reload templates
3420
+ @templates = load_templates
3421
+ end
3422
+ else
3423
+ @message = "Template '#{name}' not found"
3424
+ end
3425
+ end
3426
+
3427
+ def get_user_templates
3428
+ templates = []
3429
+ if File.directory?(@templates_dir)
3430
+ Dir.glob(File.join(@templates_dir, "*.hlt")).each do |template_file|
3431
+ template_name = File.basename(template_file, ".hlt")
3432
+ begin
3433
+ template_data = JSON.parse(File.read(template_file))
3434
+ templates << {
3435
+ "name" => template_name,
3436
+ "description" => template_data["description"] || "",
3437
+ "created" => template_data["created"] || "",
3438
+ "path" => template_file
3439
+ }
3440
+ rescue => e
3441
+ # Skip invalid template files
3442
+ end
3443
+ end
3444
+ end
3445
+ templates.sort_by { |t| t["name"] }
3446
+ end
3447
+
3448
+ def show_template_manager(action = :list)
3449
+ # Store original state
3450
+ original_state = {
3451
+ items: @items.dup,
3452
+ current: @current,
3453
+ offset: @offset,
3454
+ filename: @filename,
3455
+ modified: @modified
3456
+ }
3457
+
3458
+ user_templates = get_user_templates
3459
+
3460
+ # Build template manager view
3461
+ @items = []
3462
+ case action
3463
+ when :delete
3464
+ @items << {"text" => "DELETE TEMPLATE (press Enter to delete, q to cancel)", "level" => 0, "fold" => false, "raw" => true}
3465
+ else
3466
+ @items << {"text" => "USER TEMPLATES (press Enter to select, q to cancel)", "level" => 0, "fold" => false, "raw" => true}
3467
+ end
3468
+ @items << {"text" => "="*50, "level" => 0, "fold" => false, "raw" => true}
3469
+
3470
+ if user_templates.empty?
3471
+ @items << {"text" => "No user templates found", "level" => 0, "fold" => false, "raw" => true}
3472
+ else
3473
+ user_templates.each_with_index do |template, idx|
3474
+ desc = template["description"].empty? ? "No description" : template["description"]
3475
+ created = template["created"].empty? ? "" : " (#{Time.parse(template["created"]).strftime('%Y-%m-%d')})"
3476
+ @items << {
3477
+ "text" => "#{idx+1}. #{template["name"]}: #{desc}#{created}",
3478
+ "level" => 0,
3479
+ "fold" => false,
3480
+ "raw" => true,
3481
+ "template_name" => template["name"],
3482
+ "template_action" => action
3483
+ }
3484
+ end
3485
+ end
3486
+
3487
+ @current = 2 # Start at first template
3488
+ @offset = 0
3489
+
3490
+ selected_template = nil
3491
+ exit_loop = false
3492
+
3493
+ # Template manager loop
3494
+ while !exit_loop
3495
+ begin
3496
+ render_main
3497
+ footer_text = case action
3498
+ when :delete
3499
+ "Delete Template | Enter: delete | q: cancel | j/k: navigate"
3500
+ else
3501
+ "User Templates | Enter: select | q: cancel | j/k: navigate"
3502
+ end
3503
+ @footer.text = footer_text
3504
+ @footer.refresh
3505
+
3506
+ c = getchr
3507
+ next if c.nil?
3508
+
3509
+ case c
3510
+ when "q", "ESC", "C-c", "Q"
3511
+ exit_loop = true
3512
+ when "j", "DOWN"
3513
+ @current = [@current + 1, @items.length - 1].min
3514
+ when "k", "UP"
3515
+ @current = [@current - 1, 2].max
3516
+ when "ENTER", "RETURN", "\n", "\r"
3517
+ if @current >= 2 && @current < @items.length
3518
+ item = @items[@current]
3519
+ if item && item.is_a?(Hash) && item["template_name"]
3520
+ selected_template = item["template_name"]
3521
+ exit_loop = true
3522
+ end
3523
+ end
3524
+ end
3525
+ rescue => e
3526
+ @message = "Error in template manager: #{e.message}"
3527
+ exit_loop = true
3528
+ end
3529
+ end
3530
+
3531
+ # Restore original state
3532
+ @items = original_state[:items]
3533
+ @current = original_state[:current]
3534
+ @offset = original_state[:offset]
3535
+ @filename = original_state[:filename]
3536
+ @modified = original_state[:modified]
3537
+
3538
+ # Process selected template
3539
+ if selected_template && action == :delete
3540
+ delete_template(selected_template)
3541
+ end
3542
+
3543
+ selected_template
3309
3544
  end
3310
3545
 
3311
3546
  def show_templates
@@ -3318,24 +3553,33 @@ class HyperListApp
3318
3553
  modified: @modified
3319
3554
  }
3320
3555
 
3321
- # Create template selection view
3556
+ # Create template selection view combining built-in and user templates
3322
3557
  template_list = [
3323
- ["project", "Project Plan - Complete project management template"],
3324
- ["meeting", "Meeting Agenda - Structure for meeting notes"],
3325
- ["daily", "Daily Planner - Daily task and schedule template"],
3326
- ["checklist", "Simple Checklist - Basic checkbox list"],
3327
- ["brainstorm", "Brainstorming Session - Idea generation template"],
3328
- ["recipe", "Recipe - Cooking recipe structure"]
3558
+ ["project", "Project Plan - Complete project management template", "built-in"],
3559
+ ["meeting", "Meeting Agenda - Structure for meeting notes", "built-in"],
3560
+ ["daily", "Daily Planner - Daily task and schedule template", "built-in"],
3561
+ ["checklist", "Simple Checklist - Basic checkbox list", "built-in"],
3562
+ ["brainstorm", "Brainstorming Session - Idea generation template", "built-in"],
3563
+ ["recipe", "Recipe - Cooking recipe structure", "built-in"]
3329
3564
  ]
3330
3565
 
3566
+ # Add user templates to the list
3567
+ user_templates = get_user_templates
3568
+ user_templates.each do |template|
3569
+ desc = template["description"].empty? ? "User template" : template["description"]
3570
+ template_list << [template["name"], desc, "user"]
3571
+ end
3572
+
3331
3573
  # Build template selection items
3332
3574
  @items = []
3333
3575
  @items << {"text" => "TEMPLATES (press Enter to insert, q to cancel)", "level" => 0, "fold" => false, "raw" => true}
3334
3576
  @items << {"text" => "="*50, "level" => 0, "fold" => false, "raw" => true}
3335
3577
 
3336
- template_list.each_with_index do |(key, desc), idx|
3578
+ # Add built-in templates section
3579
+ @items << {"text" => "BUILT-IN TEMPLATES:", "level" => 0, "fold" => false, "raw" => true}
3580
+ template_list.select { |t| t[2] == "built-in" }.each_with_index do |(key, desc, type), idx|
3337
3581
  @items << {
3338
- "text" => "#{idx+1}. #{key.capitalize}: #{desc}",
3582
+ "text" => " #{idx+1}. #{key.capitalize}: #{desc}",
3339
3583
  "level" => 0,
3340
3584
  "fold" => false,
3341
3585
  "raw" => true,
@@ -3343,6 +3587,21 @@ class HyperListApp
3343
3587
  }
3344
3588
  end
3345
3589
 
3590
+ # Add user templates section if any exist
3591
+ if user_templates.any?
3592
+ @items << {"text" => "", "level" => 0, "fold" => false, "raw" => true}
3593
+ @items << {"text" => "USER TEMPLATES:", "level" => 0, "fold" => false, "raw" => true}
3594
+ template_list.select { |t| t[2] == "user" }.each_with_index do |(key, desc, type), idx|
3595
+ @items << {
3596
+ "text" => " #{key}: #{desc}",
3597
+ "level" => 0,
3598
+ "fold" => false,
3599
+ "raw" => true,
3600
+ "template_key" => key
3601
+ }
3602
+ end
3603
+ end
3604
+
3346
3605
  @current = 2 # Start at first template
3347
3606
  @offset = 0
3348
3607
 
@@ -4252,6 +4511,19 @@ class HyperListApp
4252
4511
  end
4253
4512
 
4254
4513
  def run
4514
+ # Initialize rcurses explicitly (no longer auto-initialized)
4515
+ Rcurses.init!
4516
+
4517
+ # Flush any buffered input (like the Enter key from running the command)
4518
+ while IO.select([$stdin], nil, nil, 0)
4519
+ $stdin.read_nonblock(1024) rescue break
4520
+ end
4521
+
4522
+ # Now that rcurses is initialized, set up the UI properly
4523
+ Rcurses.clear_screen
4524
+ Cursor.hide
4525
+ setup_ui
4526
+
4255
4527
  render
4256
4528
 
4257
4529
  loop do
@@ -4260,6 +4532,14 @@ class HyperListApp
4260
4532
 
4261
4533
  c = getchr
4262
4534
 
4535
+ # Skip nil input (shouldn't happen normally)
4536
+ next if c.nil?
4537
+
4538
+ # Skip newline at the very start (buffered from command execution)
4539
+ if c == "\n" && @last_key.nil?
4540
+ next
4541
+ end
4542
+
4263
4543
  # Track last key for double-key combinations
4264
4544
  prev_key = @last_key
4265
4545
  @last_key = c
@@ -4550,13 +4830,15 @@ class HyperListApp
4550
4830
  quit
4551
4831
  ensure
4552
4832
  Cursor.show
4553
- Rcurses.clear_screen
4833
+ # Screen clearing disabled for debugging
4834
+ # Rcurses.clear_screen
4554
4835
  end
4555
4836
  end
4556
4837
 
4557
4838
  # Main
4558
- if __FILE__ == $0
4559
- # Normal operation - help/version already handled at top of file
4839
+ # When installed as a gem executable, this file is loaded (not executed directly)
4840
+ # so we can't use __FILE__ == $0. Just run unless we already handled help/version.
4841
+ unless ARGV[0] == '-h' || ARGV[0] == '--help' || ARGV[0] == '-v' || ARGV[0] == '--version'
4560
4842
  app = HyperListApp.new(ARGV[0])
4561
4843
  app.run
4562
4844
  end
data/hyperlist.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "hyperlist"
3
- spec.version = "1.1.7"
3
+ spec.version = "1.2.0"
4
4
  spec.authors = ["Geir Isene"]
5
5
  spec.email = ["g@isene.com"]
6
6
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hyperlist
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.7
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
8
8
  autorequire:
9
9
  bindir: "."
10
10
  cert_chain: []
11
- date: 2025-08-14 00:00:00.000000000 Z
11
+ date: 2025-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rcurses
@@ -73,20 +73,12 @@ files:
73
73
  - CHANGELOG.md
74
74
  - LICENSE
75
75
  - README.md
76
- - debug_instructions.md
77
- - diagnose.rb
78
- - diagnose_ruby34.rb
79
- - diagnose_ruby34_detailed.rb
80
- - diagnose_safe.rb
81
- - fix_terminal.sh
82
76
  - hyperlist
83
77
  - hyperlist.gemspec
84
- - hyperlist_logo.svg
85
- - hyperlist_ruby34_wrapper.rb
86
- - rcurses_ruby34_patch.rb
78
+ - img/hyperlist_logo.svg
79
+ - img/screenshot_help.png
80
+ - img/screenshot_sample.png
87
81
  - sample.hl
88
- - screenshot_help.png
89
- - screenshot_sample.png
90
82
  - test.hl
91
83
  homepage: https://github.com/isene/HyperList
92
84
  licenses: