grmenu 4.0.1 → 4.0.2

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 (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/data/help.txt +1 -1
  4. data/grmenu.rb +104 -84
  5. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15a2bac2ca8d2fcd19044ec0e07c589799400b840a302751a0b787f58095e548
4
- data.tar.gz: b73e42131614a574a3f85313dd611f294814e97da90ceb681714e33ffab51cae
3
+ metadata.gz: c028e16af097dddc8e61b7cc766cc6a7f1870616e3c5169c832fe6edcf79fb55
4
+ data.tar.gz: 1c0070cb22cebd71fa4b235c0cea7bd51c1af58c7b662fbe5bd2d9976709e774
5
5
  SHA512:
6
- metadata.gz: 3598fafb53860c943e0752730c8720424436f01035122f094c4d17938786a5dee451d41b388ef4032083f132752ea6cdef15bae2f56d01eea6871d323bbb1164
7
- data.tar.gz: 0f4dd3d3da4f1f65f6c4e926815ebe294e82dca8195c2362bd3fd614da399b7f8be3ca620e05b7a158bef49bb57347469b451675490930161192fa689f8caa9f
6
+ metadata.gz: ba425e3a5e0a2d4692f9bc79e249a8303a245e0aeca137bd343fee489020d6b3f1b4c37147751ca4d5c05ab119b97848f6f7470803984550c69b93c0ae77a8cc
7
+ data.tar.gz: 90959c3c3c4ae76ec8bca759faea2ecdb801ee8fbc977bfae15618ad3af603202c95b2192e0296193cee5a933a0aa93e2ac559db84e0a967380c3e4737839c50
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # GRmenu (Ruby) v4.0.1
1
+ # GRmenu (Ruby) v4.0.2
2
2
 
3
3
  **Suite TUI Profesional y Ligera para la Creación de Interfaces de Línea de Comandos en Terminales TTY.**
4
4
 
@@ -95,7 +95,7 @@ require 'grmenu'
95
95
  GRmenu.theme(:neon_red)
96
96
 
97
97
  def saludar
98
- GRmenu.alert(:success, "Bienvenido a GRmenu v4.0.1!")
98
+ GRmenu.alert(:success, "Bienvenido a GRmenu v4.0.2!")
99
99
  end
100
100
 
101
101
  def ver_tabla
data/data/help.txt CHANGED
@@ -8,7 +8,7 @@
8
8
  {bright_cyan}╚═══════════════════════════════════════════════════════════════════════════════════╝{reset}
9
9
 
10
10
  {bright_cyan}╔═══════════════════════════════════════════════════════════════════════════════════╗{reset}
11
- {bright_cyan}║{bright_yellow} DOCUMENTACION Y GUIA COMPLETA DE PARAMETROS (v4.0.1) {bright_cyan}║{reset}
11
+ {bright_cyan}║{bright_yellow} DOCUMENTACION Y GUIA COMPLETA DE PARAMETROS (v4.0.2) {bright_cyan}║{reset}
12
12
  {bright_cyan}║{gray} Soporte Raton SGR 1006, Submenus en Cascada 3 Niveles, Pestanas y CSS .gr {bright_cyan}║{reset}
13
13
  {bright_cyan}╚═══════════════════════════════════════════════════════════════════════════════════╝{reset}
14
14
 
data/grmenu.rb CHANGED
@@ -6,15 +6,15 @@ require 'zlib'
6
6
  require 'open3'
7
7
 
8
8
  class GRmenu
9
- VERSION = "4.0.1"
9
+ VERSION = "4.0.2"
10
10
  CLEAR_SCREEN_SEQUENCE = "\e[H\e[2J\e[3J"
11
11
  HIDE_CURSOR = "\e[?25l"
12
12
  SHOW_CURSOR = "\e[?25h"
13
13
  CURSOR_HOME = "\e[H"
14
14
  CLEAR_TO_EOL = "\e[K"
15
15
  CLEAR_TO_EOS = "\e[J"
16
- ENABLE_MOUSE = "\e[?1000h\e[?1006h"
17
- DISABLE_MOUSE = "\e[?1000l\e[?1006l"
16
+ ENABLE_MOUSE = "\e[?1000h\e[?1002h\e[?1006h"
17
+ DISABLE_MOUSE = "\e[?1006l\e[?1002l\e[?1000l"
18
18
 
19
19
  def self.find_data_file(filename)
20
20
  local_path = File.expand_path("data/#{filename}", __dir__)
@@ -24,6 +24,30 @@ class GRmenu
24
24
  nil
25
25
  end
26
26
 
27
+ def self.enable_windows_vt
28
+ return unless Gem.win_platform? || RUBY_PLATFORM =~ /mswin|mingw|cygwin/
29
+ require 'fiddle'
30
+ kernel32 = Fiddle.dlopen('kernel32')
31
+ get_std_handle = Fiddle::Function.new(kernel32['GetStdHandle'], [Fiddle::TYPE_INT], Fiddle::TYPE_VOIDP)
32
+ get_console_mode = Fiddle::Function.new(kernel32['GetConsoleMode'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
33
+ set_console_mode = Fiddle::Function.new(kernel32['SetConsoleMode'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_INT], Fiddle::TYPE_INT)
34
+
35
+ h_out = get_std_handle.call(-11)
36
+ out_mode = ' ' * 4
37
+ if get_console_mode.call(h_out, out_mode) != 0
38
+ m = out_mode.unpack1('L')
39
+ set_console_mode.call(h_out, m | 0x0004)
40
+ end
41
+
42
+ h_in = get_std_handle.call(-10)
43
+ in_mode = ' ' * 4
44
+ if get_console_mode.call(h_in, in_mode) != 0
45
+ m = in_mode.unpack1('L')
46
+ set_console_mode.call(h_in, m | 0x0200)
47
+ end
48
+ rescue StandardError
49
+ end
50
+
27
51
  def self.load_json_data(filename)
28
52
  path = find_data_file(filename)
29
53
  return {} unless path && File.exist?(path)
@@ -1448,27 +1472,37 @@ class GRmenu
1448
1472
  return nil if first_char.nil?
1449
1473
 
1450
1474
  if first_char == "\e"
1451
- begin
1452
- second = is_tty ? input_stream.read_nonblock(1) : input_stream.read(1)
1453
- if second
1454
- first_char << second
1455
- if second == "[" || second == "O"
1456
- while true
1457
- ch = is_tty ? input_stream.read_nonblock(1) : input_stream.read(1)
1458
- break if ch.nil?
1459
- first_char << ch
1460
- break if ch =~ /[a-zA-Z~]/
1461
- end
1462
- end
1475
+ seq = first_char.dup
1476
+ if is_tty
1477
+ while (ch = (input_stream.getch(min: 0, time: 0.1) rescue nil))
1478
+ seq << ch
1479
+ break if seq =~ /[a-zA-Z~]\z/
1480
+ end
1481
+ else
1482
+ while (IO.select([input_stream], nil, nil, 0.05) rescue nil)
1483
+ ch = (input_stream.read(1) rescue nil)
1484
+ break if ch.nil?
1485
+ seq << ch
1486
+ break if seq =~ /[a-zA-Z~]\z/
1463
1487
  end
1464
- rescue IO::WaitReadable, IO::EAGAINWaitReadable, EOFError
1465
1488
  end
1466
- elsif first_char == "\x00" || first_char == "\xe0"
1467
- begin
1468
- second_char = is_tty ? input_stream.read_nonblock(1) : input_stream.read(1)
1469
- first_char << second_char if second_char
1470
- rescue IO::WaitReadable, IO::EAGAINWaitReadable, EOFError
1489
+
1490
+ if seq == "\e[M"
1491
+ cb = is_tty ? (input_stream.getch(min: 0, time: 0.1) rescue nil) : (input_stream.read(1) rescue nil)
1492
+ cx = is_tty ? (input_stream.getch(min: 0, time: 0.1) rescue nil) : (input_stream.read(1) rescue nil)
1493
+ cy = is_tty ? (input_stream.getch(min: 0, time: 0.1) rescue nil) : (input_stream.read(1) rescue nil)
1494
+ if cb && cx && cy
1495
+ btn_c = cb.ord - 32
1496
+ col_c = cx.ord - 32
1497
+ row_c = cy.ord - 32
1498
+ return "\e[<#{btn_c};#{col_c};#{row_c}M"
1499
+ end
1471
1500
  end
1501
+
1502
+ return seq
1503
+ elsif first_char == "\x00" || first_char == "\xe0"
1504
+ second_char = is_tty ? (input_stream.getch(min: 0, time: 0.1) rescue nil) : (input_stream.read(1) rescue nil)
1505
+ return first_char + second_char if second_char
1472
1506
  end
1473
1507
 
1474
1508
  first_char
@@ -2587,8 +2621,12 @@ class GRmenu
2587
2621
  @image = image || keyword_arguments[:image]
2588
2622
  @image_width = (image_width || keyword_arguments[:image_width])&.to_i
2589
2623
  @animate = (keyword_arguments[:animate] || (@@global_theme.is_a?(Hash) && @@global_theme.dig(:sections, 'menu', 'animate')) || false).to_s
2590
- @desc_prefix = keyword_arguments[:desc_prefix] || keyword_arguments[:description_prefix]
2591
- @mouse = (mouse == true || keyword_arguments[:mouse] == true || mouse.to_s == 'true' || keyword_arguments[:mouse].to_s == 'true' || (theme_menu_sec['mouse'].to_s == 'true'))
2624
+ m_val = mouse.nil? ? keyword_arguments[:mouse] : mouse
2625
+ if m_val.nil?
2626
+ @mouse = theme_menu_sec.key?('mouse') ? (theme_menu_sec['mouse'].to_s != 'false') : true
2627
+ else
2628
+ @mouse = (m_val == true || m_val.to_s == 'true')
2629
+ end
2592
2630
 
2593
2631
  t_sec = (@@global_theme.is_a?(Hash) && @@global_theme.dig(:sections, "tabs")) || {}
2594
2632
  @active_tab_color = (active_tab_color || keyword_arguments[:active_tab_color] || t_sec["active_tab"] || t_sec["active_tab_color"] || "yellow").to_s
@@ -3736,11 +3774,15 @@ class GRmenu
3736
3774
  target_width = min_width || size_max || 20
3737
3775
  action_to_execute = nil
3738
3776
 
3777
+ self.class.enable_windows_vt
3778
+ $stdout.sync = true
3779
+
3739
3780
  is_tty = $stdin.respond_to?(:tty?) && $stdin.tty?
3740
3781
 
3741
3782
  begin
3742
3783
  Kernel.print("#{HIDE_CURSOR}#{CLEAR_SCREEN_SEQUENCE}")
3743
3784
  Kernel.print(ENABLE_MOUSE) if @mouse
3785
+ $stdout.flush
3744
3786
 
3745
3787
  if @animate && !["false", "rgb", "", "nil"].include?(@animate.downcase)
3746
3788
  intro_lines = render_lines(target_width)
@@ -3757,17 +3799,21 @@ class GRmenu
3757
3799
  ensure
3758
3800
  Kernel.print(DISABLE_MOUSE) if @mouse
3759
3801
  Kernel.print(SHOW_CURSOR)
3802
+ $stdout.flush
3760
3803
  end
3761
3804
 
3762
3805
  if action_to_execute
3763
3806
  Kernel.print(CLEAR_SCREEN_SEQUENCE)
3807
+ $stdout.flush
3764
3808
  execute_action(action_to_execute)
3765
3809
  else
3766
3810
  Kernel.print(CLEAR_SCREEN_SEQUENCE)
3811
+ $stdout.flush
3767
3812
  end
3768
3813
  rescue Interrupt
3769
3814
  Kernel.print(DISABLE_MOUSE) if @mouse
3770
3815
  Kernel.print("#{SHOW_CURSOR}#{CLEAR_SCREEN_SEQUENCE}")
3816
+ $stdout.flush
3771
3817
  nil
3772
3818
  end
3773
3819
 
@@ -3782,6 +3828,7 @@ class GRmenu
3782
3828
  end
3783
3829
  buffer << CLEAR_TO_EOS
3784
3830
  Kernel.print(buffer)
3831
+ $stdout.flush
3785
3832
  end
3786
3833
 
3787
3834
  def run_interactive_loop(input_stream, target_width)
@@ -3823,34 +3870,40 @@ class GRmenu
3823
3870
  act = $4
3824
3871
 
3825
3872
  if btn == 64
3826
- if @level == 2 && @open_level >= 2 && is_submenu_item?(@functions[@index])
3873
+ if @open_level >= 2 && @sub_2_col_rng && @sub_2_col_rng.cover?(col) && is_submenu_item?(@functions[@index])
3827
3874
  s1_acts = get_submenu_actions(@functions[@index])
3828
3875
  s2_acts = get_submenu_actions(s1_acts[@sub_index_1]) if s1_acts
3829
3876
  @sub_index_2 = (@sub_index_2 - 1) % s2_acts.length if s2_acts && !s2_acts.empty?
3830
- elsif @level == 1 && @open_level >= 1 && is_submenu_item?(@functions[@index])
3877
+ @level = 2
3878
+ elsif @open_level >= 1 && @sub_1_col_rng && @sub_1_col_rng.cover?(col) && is_submenu_item?(@functions[@index])
3831
3879
  s1_acts = get_submenu_actions(@functions[@index])
3832
3880
  @sub_index_1 = (@sub_index_1 - 1) % s1_acts.length if s1_acts && !s1_acts.empty?
3833
3881
  @sub_index_2 = 0
3882
+ @level = 1
3834
3883
  else
3835
3884
  move_up
3836
3885
  @sub_index_1 = 0
3837
3886
  @sub_index_2 = 0
3887
+ @level = 0
3838
3888
  end
3839
3889
  draw_frame(target_width)
3840
3890
  next
3841
3891
  elsif btn == 65
3842
- if @level == 2 && @open_level >= 2 && is_submenu_item?(@functions[@index])
3892
+ if @open_level >= 2 && @sub_2_col_rng && @sub_2_col_rng.cover?(col) && is_submenu_item?(@functions[@index])
3843
3893
  s1_acts = get_submenu_actions(@functions[@index])
3844
3894
  s2_acts = get_submenu_actions(s1_acts[@sub_index_1]) if s1_acts
3845
3895
  @sub_index_2 = (@sub_index_2 + 1) % s2_acts.length if s2_acts && !s2_acts.empty?
3846
- elsif @level == 1 && @open_level >= 1 && is_submenu_item?(@functions[@index])
3896
+ @level = 2
3897
+ elsif @open_level >= 1 && @sub_1_col_rng && @sub_1_col_rng.cover?(col) && is_submenu_item?(@functions[@index])
3847
3898
  s1_acts = get_submenu_actions(@functions[@index])
3848
3899
  @sub_index_1 = (@sub_index_1 + 1) % s1_acts.length if s1_acts && !s1_acts.empty?
3849
3900
  @sub_index_2 = 0
3901
+ @level = 1
3850
3902
  else
3851
3903
  move_down
3852
3904
  @sub_index_1 = 0
3853
3905
  @sub_index_2 = 0
3906
+ @level = 0
3854
3907
  end
3855
3908
  draw_frame(target_width)
3856
3909
  next
@@ -3889,14 +3942,9 @@ class GRmenu
3889
3942
  s1_acts = get_submenu_actions(@functions[@index])
3890
3943
  s2_acts = get_submenu_actions(s1_acts[@sub_index_1]) if s1_acts
3891
3944
  if s2_acts && s2_clicked < s2_acts.length
3892
- if @level == 2 && @sub_index_2 == s2_clicked
3893
- return s2_acts[s2_clicked]
3894
- else
3895
- @level = 2
3896
- @sub_index_2 = s2_clicked
3897
- draw_frame(target_width)
3898
- next
3899
- end
3945
+ @level = 2
3946
+ @sub_index_2 = s2_clicked
3947
+ return s2_acts[s2_clicked]
3900
3948
  end
3901
3949
  end
3902
3950
 
@@ -3905,67 +3953,39 @@ class GRmenu
3905
3953
  s1_acts = get_submenu_actions(@functions[@index])
3906
3954
  if s1_acts && s1_clicked < s1_acts.length
3907
3955
  t_act = s1_acts[s1_clicked]
3908
- if @level == 1 && @sub_index_1 == s1_clicked
3909
- if is_submenu_item?(t_act)
3910
- @open_level = 2
3911
- @level = 2
3912
- @sub_index_2 = 0
3913
- draw_frame(target_width)
3914
- next
3915
- else
3916
- return t_act
3917
- end
3918
- else
3919
- @level = 1
3920
- @sub_index_1 = s1_clicked
3921
- if is_submenu_item?(t_act)
3922
- @open_level = 2
3923
- @sub_index_2 = 0
3924
- else
3925
- @open_level = 1
3926
- end
3956
+ @level = 1
3957
+ @sub_index_1 = s1_clicked
3958
+ if is_submenu_item?(t_act)
3959
+ @open_level = 2
3960
+ @level = 2
3961
+ @sub_index_2 = 0
3927
3962
  draw_frame(target_width)
3928
3963
  next
3964
+ else
3965
+ return t_act
3929
3966
  end
3930
3967
  end
3931
3968
  end
3932
3969
 
3933
3970
  if @row_hit_map && @row_hit_map[row]
3934
3971
  hit = @row_hit_map[row]
3935
- inner_x = col - hit[:margin_left] - 3
3936
- if inner_x >= 0
3937
- c_idx = (inner_x / (hit[:col_w] + 2)).to_i
3938
- c_idx = [[c_idx, 0].max, hit[:cols] - 1].min
3972
+ x_in_box = col - hit[:margin_left]
3973
+ if x_in_box > 0 && (hit[:total_w].nil? || x_in_box <= hit[:total_w])
3974
+ c_idx = [[((x_in_box - 2) / ([hit[:col_w], 1].max + 2)).to_i, 0].max, hit[:cols] - 1].min
3939
3975
  clicked_item = hit[:row_indices][c_idx]
3940
3976
  if clicked_item
3941
- if @index == clicked_item
3942
- if is_submenu_item?(@functions[clicked_item])
3943
- @open_level = 1
3944
- @level = 1
3945
- @sub_index_1 = 0
3946
- @sub_index_2 = 0
3947
- @active_panel = :sub
3948
- @submenu_open = true
3949
- draw_frame(target_width)
3950
- next
3951
- else
3952
- return @functions[clicked_item]
3953
- end
3954
- else
3955
- @index = clicked_item
3956
- @level = 0
3957
- @active_panel = :main
3958
- if is_submenu_item?(@functions[clicked_item])
3959
- @open_level = 1
3960
- @sub_index_1 = 0
3961
- @sub_index_2 = 0
3962
- @submenu_open = true
3963
- else
3964
- @open_level = 0
3965
- @submenu_open = false
3966
- end
3977
+ @index = clicked_item
3978
+ if is_submenu_item?(@functions[clicked_item])
3979
+ @open_level = 1
3980
+ @level = 1
3981
+ @sub_index_1 = 0
3982
+ @sub_index_2 = 0
3983
+ @active_panel = :sub
3984
+ @submenu_open = true
3967
3985
  draw_frame(target_width)
3968
3986
  next
3987
+ else
3988
+ return @functions[clicked_item]
3969
3989
  end
3970
3990
  end
3971
3991
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grmenu
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - grcode