hyperlist 1.1.4 → 1.1.6

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: ceec87c634faff3f44aea9faab6b7e2c5fbb6299827371c148b01ac833a6653e
4
- data.tar.gz: d2aee8287a2af42238f8d55ac47e5ac4f38738d55c4672f5f7835c561653246a
3
+ metadata.gz: c3394f0a19dc7d9641036a62d294be9dcb4d07627e8f28abbf52be6db409b0ce
4
+ data.tar.gz: 226af1d1c88dc25128f9fb881e6195bb57f4ee9ec8248320d9c12834b1275aff
5
5
  SHA512:
6
- metadata.gz: a6bb97db751579efeb55724dd0280edf506a9c547c6809ae61e4fe2ed7ae8b505fb1fc85f138a6ae0c5aea47abc74ed391b6e35f347bbb0dc8e09c562eb2ea77
7
- data.tar.gz: efdac57b3bff33a8cefa53f26782ff99dfee21536d54bd185497d89bd010669cc543b2e5c167bdb2d0fe250de73a82a4922dc6c927af33d6f07dbb74429cc2f4
6
+ metadata.gz: e636855dff0f0179dcb0f7eb56dc67c577f3775cd1fbf93d9c49b1812ce896e34160331146c4a6e8cea5e7fa92cafba197244210bb48b24f5abfa86e1e7c266b
7
+ data.tar.gz: b5793788afef9b63fe54471687ed3f03f6f100616f2aa89eb13a5fa5e36201cbfaabac24b7683f612084bfacf3ffb827bac1bf7e363958ece2de0f32fecedc7a
data/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  All notable changes to the HyperList Ruby TUI will be documented in this file.
4
4
 
5
+ ## [1.1.6] - 2025-08-14
6
+
7
+ ### Fixed
8
+ - **Ruby 3.4+ Compatibility**
9
+ - Added explicit rcurses initialization for Ruby 3.4.0 and later
10
+ - Improved error handling during terminal initialization
11
+ - Added proper cleanup on exit for newer Ruby versions
12
+ - Fixed silent crashes on Arch Linux with Ruby 3.4.5
13
+
5
14
  ## [1.1.0] - 2025-08-13
6
15
 
7
16
  ### Added
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env ruby
2
+ # Diagnostic script for Ruby 3.4.5 compatibility issues
3
+
4
+ puts "Ruby Compatibility Diagnostic for HyperList"
5
+ puts "=" * 50
6
+ puts "Ruby version: #{RUBY_VERSION}"
7
+ puts "Ruby platform: #{RUBY_PLATFORM}"
8
+ puts
9
+
10
+ # Test 1: Basic rcurses functionality
11
+ puts "Test 1: Basic rcurses require and init..."
12
+ begin
13
+ require 'rcurses'
14
+ puts " ✓ rcurses loaded successfully"
15
+ puts " Rcurses version: #{Rcurses::VERSION}" if defined?(Rcurses::VERSION)
16
+ rescue LoadError => e
17
+ puts " ✗ Failed to load rcurses: #{e.message}"
18
+ exit 1
19
+ end
20
+
21
+ # Test 2: Rcurses initialization with error capture
22
+ puts "\nTest 2: Rcurses initialization..."
23
+ begin
24
+ # Capture any output during init
25
+ original_stdout = $stdout
26
+ original_stderr = $stderr
27
+
28
+ # Create StringIO to capture output
29
+ require 'stringio'
30
+ captured_out = StringIO.new
31
+ captured_err = StringIO.new
32
+
33
+ $stdout = captured_out
34
+ $stderr = captured_err
35
+
36
+ # Try to initialize
37
+ Rcurses.init!
38
+
39
+ # Restore output
40
+ $stdout = original_stdout
41
+ $stderr = original_stderr
42
+
43
+ # Check if anything was captured
44
+ out_content = captured_out.string
45
+ err_content = captured_err.string
46
+
47
+ if !out_content.empty?
48
+ puts " Captured stdout during init: #{out_content.inspect}"
49
+ end
50
+ if !err_content.empty?
51
+ puts " Captured stderr during init: #{err_content.inspect}"
52
+ end
53
+
54
+ puts " ✓ Rcurses initialized"
55
+
56
+ # Test basic functionality
57
+ puts " Testing basic screen operations..."
58
+ print "\e[2J\e[H" # Clear screen
59
+ print "Test"
60
+ sleep 0.1
61
+ print "\e[2J\e[H" # Clear again
62
+
63
+ puts " ✓ Basic operations work"
64
+
65
+ rescue => e
66
+ puts " ✗ Failed during initialization: #{e.message}"
67
+ puts " Backtrace:"
68
+ e.backtrace.first(5).each { |line| puts " #{line}" }
69
+ ensure
70
+ # Try to restore terminal
71
+ begin
72
+ Rcurses.done! if defined?(Rcurses.done!)
73
+ rescue
74
+ # Fallback terminal restore
75
+ print "\e[?25h" # Show cursor
76
+ system("stty sane 2>/dev/null")
77
+ end
78
+ end
79
+
80
+ # Test 3: Check for method availability issues in Ruby 3.4
81
+ puts "\nTest 3: Ruby 3.4 specific checks..."
82
+
83
+ # Check IO methods that might have changed
84
+ if IO.respond_to?(:console)
85
+ puts " ✓ IO.console available"
86
+ else
87
+ puts " ✗ IO.console not available"
88
+ end
89
+
90
+ begin
91
+ require 'io/console'
92
+ $stdin.raw { }
93
+ puts " ✓ IO#raw method works"
94
+ rescue => e
95
+ puts " ✗ IO#raw failed: #{e.message}"
96
+ end
97
+
98
+ # Test 4: Check encoding
99
+ puts "\nTest 4: Encoding checks..."
100
+ puts " Default external: #{Encoding.default_external}"
101
+ puts " Default internal: #{Encoding.default_internal}"
102
+ puts " Console encoding: #{$stdout.external_encoding}" if $stdout.respond_to?(:external_encoding)
103
+
104
+ # Test 5: Simple hyperlist initialization test
105
+ puts "\nTest 5: HyperList class initialization..."
106
+ begin
107
+ # Load just the class definition part
108
+ hyperlist_code = File.read(File.join(File.dirname(__FILE__), 'hyperlist'))
109
+
110
+ # Extract just the class without running main
111
+ class_only = hyperlist_code.split(/^if __FILE__ == \$0/)[0]
112
+
113
+ # Try to evaluate it
114
+ eval(class_only)
115
+
116
+ puts " ✓ HyperList class loaded"
117
+
118
+ # Try to create instance (without running)
119
+ app = HyperListApp.new
120
+ puts " ✓ HyperListApp instance created"
121
+
122
+ rescue => e
123
+ puts " ✗ Failed to load HyperList: #{e.message}"
124
+ puts " Error at: #{e.backtrace.first}"
125
+ end
126
+
127
+ # Test 6: Terminal capability check
128
+ puts "\nTest 6: Terminal capabilities..."
129
+ puts " TERM: #{ENV['TERM']}"
130
+ puts " Columns: #{`tput cols`.strip}" rescue nil
131
+ puts " Lines: #{`tput lines`.strip}" rescue nil
132
+
133
+ # Test 7: Check for signal handling changes
134
+ puts "\nTest 7: Signal handling..."
135
+ begin
136
+ old_handler = Signal.trap("WINCH") { }
137
+ Signal.trap("WINCH", old_handler)
138
+ puts " ✓ SIGWINCH trap works"
139
+ rescue => e
140
+ puts " ✗ SIGWINCH trap failed: #{e.message}"
141
+ end
142
+
143
+ puts "\n" + "=" * 50
144
+ puts "Diagnostic complete!"
145
+ puts "\nPlease share this output to help identify the Ruby 3.4.5 compatibility issue."
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.4 - Terminal User Interface for HyperList files
10
+ HyperList v1.1.6 - 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.4"
55
+ puts "HyperList v1.1.6"
56
56
  exit 0
57
57
  end
58
58
 
@@ -70,7 +70,7 @@ class HyperListApp
70
70
  include Rcurses::Input
71
71
  include Rcurses::Cursor
72
72
 
73
- VERSION = "1.1.4"
73
+ VERSION = "1.1.6"
74
74
 
75
75
  def initialize(filename = nil)
76
76
  @filename = filename ? File.expand_path(filename) : nil
@@ -706,7 +706,7 @@ class HyperListApp
706
706
  line = " " * item["level"] # 4 spaces per level
707
707
 
708
708
  # Add fold indicator
709
- real_idx = @items.index(item)
709
+ real_idx = get_real_index(item)
710
710
  if real_idx && has_children?(real_idx, @items) && item["fold"]
711
711
  color = (@presentation_mode && !is_item_in_presentation_focus?(item)) ? "240" : "245"
712
712
  line += "▶".fg(color) + " "
@@ -1111,7 +1111,10 @@ class HyperListApp
1111
1111
  next
1112
1112
  end
1113
1113
 
1114
- visible << item
1114
+ # Store the item with its real index to avoid lookup issues
1115
+ item_with_index = item.dup
1116
+ item_with_index["_real_index"] = idx
1117
+ visible << item_with_index
1115
1118
 
1116
1119
  if item["fold"] && has_children?(idx, @items)
1117
1120
  # Skip children if folded
@@ -1129,6 +1132,12 @@ class HyperListApp
1129
1132
  visible
1130
1133
  end
1131
1134
 
1135
+ # Helper method to get the real index from a visible item
1136
+ def get_real_index(visible_item)
1137
+ return nil unless visible_item
1138
+ visible_item["_real_index"] || @items.index(visible_item)
1139
+ end
1140
+
1132
1141
  def has_children?(idx, items)
1133
1142
  return false if idx >= items.length - 1
1134
1143
  return false if idx < 0
@@ -1219,7 +1228,7 @@ class HyperListApp
1219
1228
  return if @current >= visible.length
1220
1229
 
1221
1230
  item = visible[@current]
1222
- real_idx = @items.index(item)
1231
+ real_idx = get_real_index(item)
1223
1232
 
1224
1233
  if real_idx && has_children?(real_idx, @items)
1225
1234
  @items[real_idx]["fold"] = !@items[real_idx]["fold"]
@@ -1385,7 +1394,7 @@ class HyperListApp
1385
1394
  # Remember which item we're focused on
1386
1395
  current_item = visible_items[@current]
1387
1396
  current_level = current_item["level"]
1388
- current_real_idx = @items.index(current_item)
1397
+ current_real_idx = get_real_index(current_item)
1389
1398
 
1390
1399
  # First, fold everything
1391
1400
  @items.each_with_index do |item, idx|
@@ -1602,7 +1611,7 @@ class HyperListApp
1602
1611
  visible = get_visible_items
1603
1612
  if @current < visible.length
1604
1613
  level = visible[@current]["level"]
1605
- real_idx = @items.index(visible[@current])
1614
+ real_idx = get_real_index(visible[@current])
1606
1615
  @items.insert(real_idx + 1, {"text" => text, "level" => level, "fold" => false})
1607
1616
  else
1608
1617
  @items << {"text" => text, "level" => 0, "fold" => false}
@@ -1633,7 +1642,7 @@ class HyperListApp
1633
1642
  visible = get_visible_items
1634
1643
  if @current < visible.length
1635
1644
  level = visible[@current]["level"] + 1
1636
- real_idx = @items.index(visible[@current])
1645
+ real_idx = get_real_index(visible[@current])
1637
1646
 
1638
1647
  # Unfold parent if needed
1639
1648
  @items[real_idx]["fold"] = false
@@ -1651,7 +1660,7 @@ class HyperListApp
1651
1660
  return if @current >= visible.length
1652
1661
 
1653
1662
  item = visible[@current]
1654
- real_idx = @items.index(item)
1663
+ real_idx = get_real_index(item)
1655
1664
 
1656
1665
  @mode = :insert
1657
1666
 
@@ -1672,7 +1681,7 @@ class HyperListApp
1672
1681
  return if @current >= visible.length
1673
1682
 
1674
1683
  item = visible[@current]
1675
- real_idx = @items.index(item)
1684
+ real_idx = get_real_index(item)
1676
1685
 
1677
1686
  save_undo_state # Save state before modification
1678
1687
  @items[real_idx]["text"] = text
@@ -1688,7 +1697,7 @@ class HyperListApp
1688
1697
  save_undo_state # Save state before modification
1689
1698
 
1690
1699
  item = visible[@current]
1691
- real_idx = @items.index(item)
1700
+ real_idx = get_real_index(item)
1692
1701
 
1693
1702
  # First, yank the item(s) to clipboard
1694
1703
  @clipboard = []
@@ -1742,7 +1751,7 @@ class HyperListApp
1742
1751
  return if @current >= visible.length
1743
1752
 
1744
1753
  item = visible[@current]
1745
- real_idx = @items.index(item)
1754
+ real_idx = get_real_index(item)
1746
1755
 
1747
1756
  @clipboard = []
1748
1757
  @clipboard << item.dup
@@ -1771,7 +1780,7 @@ class HyperListApp
1771
1780
 
1772
1781
  visible = get_visible_items
1773
1782
  if @current < visible.length
1774
- real_idx = @items.index(visible[@current])
1783
+ real_idx = get_real_index(visible[@current])
1775
1784
 
1776
1785
  if @clipboard_is_tree
1777
1786
  # For tree paste (C-D or Y), maintain original indentation structure
@@ -1810,7 +1819,7 @@ class HyperListApp
1810
1819
  save_undo_state # Save state before modification
1811
1820
 
1812
1821
  item = visible[@current]
1813
- real_idx = @items.index(item)
1822
+ real_idx = get_real_index(item)
1814
1823
 
1815
1824
  # Can't move if already at the beginning
1816
1825
  return if real_idx == 0
@@ -1852,7 +1861,7 @@ class HyperListApp
1852
1861
  save_undo_state # Save state before modification
1853
1862
 
1854
1863
  item = visible[@current]
1855
- real_idx = @items.index(item)
1864
+ real_idx = get_real_index(item)
1856
1865
 
1857
1866
  # Collect item(s) to move
1858
1867
  items_to_move = [item]
@@ -1896,7 +1905,7 @@ class HyperListApp
1896
1905
  return if @current >= visible.length
1897
1906
 
1898
1907
  item = visible[@current]
1899
- real_idx = @items.index(item)
1908
+ real_idx = get_real_index(item)
1900
1909
 
1901
1910
  # Can only indent if there's a previous item at same or higher level
1902
1911
  if real_idx > 0
@@ -1925,7 +1934,7 @@ class HyperListApp
1925
1934
  return if @current >= visible.length
1926
1935
 
1927
1936
  item = visible[@current]
1928
- real_idx = @items.index(item)
1937
+ real_idx = get_real_index(item)
1929
1938
 
1930
1939
  if @items[real_idx]["level"] > 0
1931
1940
  save_undo_state # Save state before modification
@@ -1955,7 +1964,7 @@ class HyperListApp
1955
1964
  save_undo_state # Save state before modification
1956
1965
 
1957
1966
  item = visible[@current]
1958
- real_idx = @items.index(item)
1967
+ real_idx = get_real_index(item)
1959
1968
  text = @items[real_idx]["text"]
1960
1969
 
1961
1970
  if text =~ /^\[.\]/
@@ -1984,7 +1993,7 @@ class HyperListApp
1984
1993
  save_undo_state # Save state before modification
1985
1994
 
1986
1995
  item = visible[@current]
1987
- real_idx = @items.index(item)
1996
+ real_idx = get_real_index(item)
1988
1997
  text = @items[real_idx]["text"]
1989
1998
 
1990
1999
  # First, handle existing timestamp in the hyperlist.vim format
@@ -4197,7 +4206,7 @@ class HyperListApp
4197
4206
  @marks ||= {}
4198
4207
  visible = get_visible_items
4199
4208
  if @current < visible.length
4200
- real_idx = @items.index(visible[@current])
4209
+ real_idx = get_real_index(visible[@current])
4201
4210
  @marks[mark] = real_idx
4202
4211
  @message = "Mark '#{mark}' set"
4203
4212
  end
@@ -4212,7 +4221,7 @@ class HyperListApp
4212
4221
  # Find the marked item in visible items
4213
4222
  target_idx = @marks[mark]
4214
4223
  visible = get_visible_items
4215
- visible_idx = visible.find_index { |item| @items.index(item) == target_idx }
4224
+ visible_idx = visible.find_index { |item| get_real_index(item) == target_idx }
4216
4225
 
4217
4226
  if visible_idx
4218
4227
  @current = visible_idx
@@ -4348,13 +4357,13 @@ class HyperListApp
4348
4357
  when "o"
4349
4358
  visible = get_visible_items
4350
4359
  if @current < visible.length
4351
- real_idx = @items.index(visible[@current])
4360
+ real_idx = get_real_index(visible[@current])
4352
4361
  @items[real_idx]["fold"] = false if real_idx
4353
4362
  end
4354
4363
  when "c"
4355
4364
  visible = get_visible_items
4356
4365
  if @current < visible.length
4357
- real_idx = @items.index(visible[@current])
4366
+ real_idx = get_real_index(visible[@current])
4358
4367
  if real_idx && has_children?(real_idx, @items)
4359
4368
  @items[real_idx]["fold"] = true
4360
4369
  end
@@ -4546,8 +4555,35 @@ class HyperListApp
4546
4555
  end
4547
4556
 
4548
4557
  # Main
4549
- if __FILE__ == $0
4558
+ if __FILE__ == $0 && !defined?($hyperlist_wrapper_mode)
4550
4559
  # Normal operation - help/version already handled at top of file
4560
+
4561
+ # For Ruby 3.4+, explicitly initialize rcurses if needed
4562
+ if RUBY_VERSION >= "3.4.0"
4563
+ begin
4564
+ Rcurses.init! unless Rcurses.respond_to?(:initialized?) && Rcurses.initialized?
4565
+ rescue => e
4566
+ # If initialization fails, try to provide helpful error
4567
+ puts "Failed to initialize terminal interface: #{e.message}"
4568
+ puts "Try running with: ruby #{__FILE__} #{ARGV.join(' ')}"
4569
+ exit 1
4570
+ end
4571
+ end
4572
+
4551
4573
  app = HyperListApp.new(ARGV[0])
4552
- app.run
4574
+
4575
+ begin
4576
+ app.run
4577
+ ensure
4578
+ # Ensure proper cleanup for Ruby 3.4+
4579
+ if RUBY_VERSION >= "3.4.0"
4580
+ begin
4581
+ Rcurses.done! if defined?(Rcurses.done!)
4582
+ rescue
4583
+ # Fallback cleanup
4584
+ print "\e[?25h" # Show cursor
4585
+ system("stty sane 2>/dev/null")
4586
+ end
4587
+ end
4588
+ end
4553
4589
  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.4"
3
+ spec.version = "1.1.6"
4
4
  spec.authors = ["Geir Isene"]
5
5
  spec.email = ["g@isene.com"]
6
6
 
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ # Wrapper for Ruby 3.4+ compatibility
5
+ # This ensures proper initialization of rcurses
6
+
7
+ # Handle help/version before loading libraries
8
+ if ARGV[0] == '-h' || ARGV[0] == '--help' || ARGV[0] == '-v' || ARGV[0] == '--version'
9
+ # Pass through to main hyperlist
10
+ load File.join(File.dirname(__FILE__), 'hyperlist')
11
+ exit 0
12
+ end
13
+
14
+ # Explicitly initialize rcurses before loading the main app
15
+ require 'rcurses'
16
+
17
+ begin
18
+ # Initialize rcurses with proper error handling
19
+ Rcurses.init!
20
+
21
+ # Now load and run the main hyperlist app
22
+ # We need to prevent the main file from running automatically
23
+ $hyperlist_wrapper_mode = true
24
+
25
+ # Load the hyperlist file
26
+ load File.join(File.dirname(__FILE__), 'hyperlist')
27
+
28
+ # Create and run the app
29
+ app = HyperListApp.new(ARGV[0])
30
+ app.run
31
+
32
+ rescue Interrupt
33
+ # Handle Ctrl+C gracefully
34
+ Rcurses.done! if defined?(Rcurses.done!)
35
+ puts "\nInterrupted"
36
+ exit 0
37
+ rescue => e
38
+ # Ensure terminal is restored on error
39
+ Rcurses.done! if defined?(Rcurses.done!)
40
+
41
+ # Fallback terminal restoration
42
+ print "\e[?25h" # Show cursor
43
+ system("stty sane 2>/dev/null")
44
+
45
+ puts "Error: #{e.message}"
46
+ puts "Backtrace:" if ENV['DEBUG']
47
+ e.backtrace.first(10).each { |line| puts " #{line}" } if ENV['DEBUG']
48
+ exit 1
49
+ ensure
50
+ # Always try to restore terminal
51
+ begin
52
+ Rcurses.done! if defined?(Rcurses.done!)
53
+ rescue
54
+ print "\e[?25h"
55
+ system("stty sane 2>/dev/null")
56
+ end
57
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hyperlist
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
@@ -75,11 +75,13 @@ files:
75
75
  - README.md
76
76
  - debug_instructions.md
77
77
  - diagnose.rb
78
+ - diagnose_ruby34.rb
78
79
  - diagnose_safe.rb
79
80
  - fix_terminal.sh
80
81
  - hyperlist
81
82
  - hyperlist.gemspec
82
83
  - hyperlist_logo.svg
84
+ - hyperlist_ruby34_wrapper.rb
83
85
  - sample.hl
84
86
  - screenshot_help.png
85
87
  - screenshot_sample.png