hyperlist 1.4.5 → 1.5.1

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/hyperlist +65 -31
  3. data/hyperlist.gemspec +1 -1
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b5da858aef9693451d436d48156170ebebfffa6f9ff08bf6fb71848bca3970e
4
- data.tar.gz: f4f82de4e9d76bf55611628f9a9031d2e4eccf0625536964e6615423fc3a43cb
3
+ metadata.gz: d906cdf818500e49cb3911de90fec6dc30c2de1d8b184a6ea1f59f6055776263
4
+ data.tar.gz: d35bd7c1a80843e9167e9ff30321dec10b7f91269a888870dbf655961c3b1f58
5
5
  SHA512:
6
- metadata.gz: f828786e61e63348ace5b6684afc23a8b8b4630a05c8ba73381907d5b6f874b9b2438e5bdb393944503e01b4e07f336e74a4c385dd803569ced68bacd2a35192
7
- data.tar.gz: d7e22aa25b76906372edf1d80fa88dd73778fd25de5e4b0ae88b80ac77cd7b6a7a10e6eaf178c205805bd00608eecdfe89fa2833e80e410de01bb9461527a6d3
6
+ metadata.gz: 531069f6958c4056feab35ff0db6124801501741248ec773e8582134f289d42ed9c37fc77ae25c58e45c0aa06d5c80deb114b91bc3b89d8358c482219c0d497d
7
+ data.tar.gz: 67bb2e44b183907672c08a58971149ff59297f7d800e8d1ed9156b7e27f5a04d7ec0c1acf205656c6ce813e7047eec723a6db727f5ae0cdac908e3d28a4e25b5
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.4.3 - Terminal User Interface for HyperList files
10
+ HyperList v1.5.1 - 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.4.0"
55
+ puts "HyperList v1.5.1"
56
56
  exit 0
57
57
  end
58
58
 
@@ -72,7 +72,7 @@ class HyperListApp
72
72
  include Rcurses::Input
73
73
  include Rcurses::Cursor
74
74
 
75
- VERSION = "1.4.5"
75
+ VERSION = "1.5.1"
76
76
 
77
77
  def initialize(filename = nil)
78
78
  @filename = filename ? File.expand_path(filename) : nil
@@ -135,9 +135,6 @@ class HyperListApp
135
135
  @cols = ENV['COLUMNS']&.to_i || 80
136
136
  end
137
137
 
138
- # Debug: uncomment to see terminal size
139
- # puts "Terminal size: #{@rows}x#{@cols}"
140
-
141
138
  # Setup terminal resize handler
142
139
  setup_resize_handler
143
140
 
@@ -175,9 +172,8 @@ class HyperListApp
175
172
  # This is how RTFM works - it passes colored command output to panes with nil colors
176
173
  @main = Pane.new(1, 1, split_width - 1, @rows - 1, nil, nil)
177
174
  @split_pane = Pane.new(split_width + 1, 1, split_width - 1, @rows - 1, nil, nil)
178
- # Footer: Use @rows for y-position (this puts it at the actual bottom)
179
175
  @footer = Pane.new(1, @rows, @cols, 1, 15, 8)
180
-
176
+
181
177
  # Add separator with explicit background to overwrite emoji overflow
182
178
  @separator = Pane.new(split_width, 1, 1, @rows - 1, 15, 0)
183
179
  # Build separator with explicit clearing
@@ -192,7 +188,6 @@ class HyperListApp
192
188
  # Use nil colors like RTFM to avoid ANSI wrapping issues
193
189
  # This prevents the corruption that happens with narrow terminals
194
190
  @main = Pane.new(1, 1, @cols, @rows - 1, nil, nil)
195
- # Footer: Use @rows for y-position (this puts it at the actual bottom)
196
191
  @footer = Pane.new(1, @rows, @cols, 1, 15, 8)
197
192
  end
198
193
  end
@@ -661,7 +656,6 @@ class HyperListApp
661
656
  content += "\n" unless content.end_with?("\n")
662
657
  content += "\n" + @config_line
663
658
  else
664
- # Debug: Check why config line is missing
665
659
  if @fold_level != 99
666
660
  # Rebuild config line if we have config settings but no line
667
661
  update_config_line
@@ -1477,6 +1471,11 @@ class HyperListApp
1477
1471
  end
1478
1472
 
1479
1473
  def render_footer
1474
+ # Don't overwrite footer if showing password prompt
1475
+ if @footer && @footer.text && @footer.text.include?("password")
1476
+ return
1477
+ end
1478
+
1480
1479
  version_text = "v#{VERSION}"
1481
1480
 
1482
1481
  if @mode == :command
@@ -1599,17 +1598,33 @@ class HyperListApp
1599
1598
  def has_children?(idx, items)
1600
1599
  return false if idx >= items.length - 1
1601
1600
  return false if idx < 0
1602
-
1601
+
1603
1602
  current_item = items[idx]
1604
1603
  next_item = items[idx + 1]
1605
-
1604
+
1606
1605
  # For visible items array
1607
1606
  if current_item.is_a?(Hash) && next_item.is_a?(Hash)
1608
1607
  return next_item["level"] > current_item["level"]
1609
1608
  end
1610
-
1609
+
1611
1610
  false
1612
1611
  end
1612
+
1613
+ def get_last_descendant_index(idx, items)
1614
+ # Find the index after the last descendant of item at idx
1615
+ # Returns idx + 1 if no children
1616
+ return idx + 1 if idx >= items.length - 1
1617
+ return idx + 1 unless has_children?(idx, items)
1618
+
1619
+ current_level = items[idx]["level"]
1620
+ last_idx = idx + 1
1621
+
1622
+ while last_idx < items.length && items[last_idx]["level"] > current_level
1623
+ last_idx += 1
1624
+ end
1625
+
1626
+ last_idx
1627
+ end
1613
1628
 
1614
1629
  def indent_split_right(with_children = false)
1615
1630
  visible_items = get_visible_split_items
@@ -2246,13 +2261,21 @@ class HyperListApp
2246
2261
 
2247
2262
  def insert_line_with_text(text)
2248
2263
  return unless text && !text.strip.empty?
2249
-
2264
+
2250
2265
  save_undo_state # Save state before modification
2251
2266
  visible = get_visible_items
2252
2267
  if @current < visible.length
2253
2268
  level = visible[@current]["level"]
2254
2269
  real_idx = get_real_index(visible[@current])
2255
- @items.insert(real_idx + 1, {"text" => text, "level" => level, "fold" => false})
2270
+
2271
+ # If current item has collapsed children, insert after all descendants
2272
+ if @items[real_idx]["fold"] && has_children?(real_idx, @items)
2273
+ insert_idx = get_last_descendant_index(real_idx, @items)
2274
+ else
2275
+ insert_idx = real_idx + 1
2276
+ end
2277
+
2278
+ @items.insert(insert_idx, {"text" => text, "level" => level, "fold" => false})
2256
2279
  else
2257
2280
  @items << {"text" => text, "level" => 0, "fold" => false}
2258
2281
  end
@@ -2292,17 +2315,26 @@ class HyperListApp
2292
2315
 
2293
2316
  def insert_child_with_text(text)
2294
2317
  return unless text && !text.strip.empty?
2295
-
2318
+
2296
2319
  save_undo_state # Save state before modification
2297
2320
  visible = get_visible_items
2298
2321
  if @current < visible.length
2299
2322
  level = visible[@current]["level"] + 1
2300
2323
  real_idx = get_real_index(visible[@current])
2301
-
2324
+
2325
+ # If current item has collapsed children, insert as last child
2326
+ if @items[real_idx]["fold"] && has_children?(real_idx, @items)
2327
+ # Insert just before the next sibling (at the end of all descendants)
2328
+ insert_idx = get_last_descendant_index(real_idx, @items)
2329
+ else
2330
+ # No collapsed children, insert right after current item
2331
+ insert_idx = real_idx + 1
2332
+ end
2333
+
2302
2334
  # Unfold parent if needed
2303
2335
  @items[real_idx]["fold"] = false
2304
-
2305
- @items.insert(real_idx + 1, {"text" => text, "level" => level, "fold" => false})
2336
+
2337
+ @items.insert(insert_idx, {"text" => text, "level" => level, "fold" => false})
2306
2338
  else
2307
2339
  @items << {"text" => text, "level" => 1, "fold" => false}
2308
2340
  end
@@ -3979,18 +4011,25 @@ class HyperListApp
3979
4011
  @footer.text = prompt
3980
4012
  @footer.refresh
3981
4013
 
4014
+ # Force terminal to flush output - needed when launched from urxvt
4015
+ STDOUT.flush
4016
+
4017
+ # When launched through urxvt, force a complete redraw
4018
+ if ENV['TERM'] =~ /rxvt/
4019
+ sleep 0.1
4020
+ # Force complete screen refresh
4021
+ Rcurses.clear_screen
4022
+ setup_ui
4023
+ @footer.text = prompt
4024
+ @footer.refresh
4025
+ STDOUT.flush
4026
+ end
4027
+
3982
4028
  password = ""
3983
4029
  loop do
3984
4030
  begin
3985
4031
  c = getchr
3986
4032
 
3987
- # Debug logging
3988
- if ENV['DEBUG']
3989
- File.open('/tmp/hyperlist_debug.log', 'a') do |f|
3990
- f.puts "Password prompt key: #{c.inspect}"
3991
- end
3992
- end
3993
-
3994
4033
  case c
3995
4034
  when "ENTER", "\r", "\n"
3996
4035
  break
@@ -4657,11 +4696,6 @@ class HyperListApp
4657
4696
  # Skip truly nil input
4658
4697
  next if c.nil?
4659
4698
 
4660
- # Debug logging to file
4661
- File.open('/tmp/hyperlist_debug.log', 'a') do |f|
4662
- f.puts "Template key received: #{c.inspect} (length: #{c.length}, ord: #{c.bytes.inspect})"
4663
- end if ENV['DEBUG']
4664
-
4665
4699
  case c
4666
4700
  when "q", "ESC", "C-c", "Q"
4667
4701
  exit_loop = true
data/hyperlist.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "hyperlist"
3
- spec.version = "1.4.5"
3
+ spec.version = "1.5.1"
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.4.5
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
8
8
  autorequire:
9
9
  bindir: "."
10
10
  cert_chain: []
11
- date: 2025-09-02 00:00:00.000000000 Z
11
+ date: 2025-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rcurses