ruby-shell 3.5.0 → 3.6.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 +4 -4
- data/bin/rsh +146 -87
- metadata +5 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c1a7a1c2414582ba14f71073684dc8046d52ba9bc45bf9dcc8e333ba4a99cdfe
|
|
4
|
+
data.tar.gz: 7a41cf6ed38b56e4e706e42712a59adfd0ac35fb4b60329a37bfa30d40b77abc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d6c26b7a0654f7f1dc37a55f42b6f5721ab7493838344e9bedbcb65fd023025b89b2448eae56a7dc5e907aa71ede64644b4636779d89f2ef991c1dfedf22728b
|
|
7
|
+
data.tar.gz: 03cd96dfeadcc4f6b3ee39db49ada250e1c4f301616269bb99f5940f672548c2d16f35631044fc137f483db57833c0111684443ac2aa39a1f7a4c4b1131934ba
|
data/bin/rsh
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
# Web_site: http://isene.com/
|
|
9
9
|
# Github: https://github.com/isene/rsh
|
|
10
10
|
# License: Public domain
|
|
11
|
-
@version = "3.
|
|
11
|
+
@version = "3.6.0" # Multi-line prompt support: Complete readline refactor with rcurses-inspired ANSI handling
|
|
12
12
|
|
|
13
13
|
# MODULES, CLASSES AND EXTENSIONS
|
|
14
14
|
class String # Add coloring to strings (with escaping for Readline)
|
|
@@ -185,67 +185,44 @@ end
|
|
|
185
185
|
# HELP TEXT
|
|
186
186
|
@info = <<~INFO
|
|
187
187
|
|
|
188
|
-
Hello #{@user}, welcome to rsh v3.
|
|
189
|
-
|
|
190
|
-
rsh
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
v3.2 Features:
|
|
228
|
-
* Plugin system - Extensible architecture for custom commands, completions, and hooks
|
|
229
|
-
* Auto-correct typos - :config auto_correct on (with confirmation prompt)
|
|
230
|
-
* Command timing alerts - :config slow_command_threshold 5 warns on slow commands
|
|
231
|
-
* Inline calculator - :calc 2 + 2, :calc "Math::PI", full Ruby Math library
|
|
232
|
-
* Enhanced history - !!, !-2, !5:7 for repeat last, nth-to-last, and chaining
|
|
233
|
-
* Stats visualization - :stats --graph for colorful ASCII bar charts
|
|
234
|
-
|
|
235
|
-
v3.1 Features:
|
|
236
|
-
* Multiple named sessions - :save_session "project" and :load_session "project"
|
|
237
|
-
* Stats export - :stats --csv or :stats --json for data analysis
|
|
238
|
-
* Session auto-save - Set @session_autosave = 300 in .rshrc for 5-min auto-save
|
|
239
|
-
* Bookmark import/export - :bm --export file.json and :bm --import file.json
|
|
240
|
-
* Bookmark statistics - :bm --stats shows usage patterns and tag distribution
|
|
241
|
-
* Color themes - :theme solarized|dracula|gruvbox|nord|monokai
|
|
242
|
-
* Config management - :config shows/sets history_dedup, session_autosave, etc.
|
|
243
|
-
* Environment management - :env for listing/setting/exporting environment variables
|
|
244
|
-
|
|
245
|
-
Config file (.rshrc) updates on exit (Ctrl-d) or not (Ctrl-e).
|
|
246
|
-
All colors are themeable in .rshrc (see github link for possibilities).
|
|
247
|
-
|
|
248
|
-
Use `:help` for complete command reference.
|
|
188
|
+
Hello #{@user}, welcome to rsh v3.6 - the Ruby SHell.
|
|
189
|
+
|
|
190
|
+
rsh is a feature-rich shell written in pure Ruby, designed for productivity and customization.
|
|
191
|
+
|
|
192
|
+
KEY FEATURES:
|
|
193
|
+
• Nicks (aliases) with {{parameters}} - :nick gp = git push origin {{branch}}
|
|
194
|
+
• Completion learning - Shell learns and adapts to your patterns
|
|
195
|
+
• Plugin system - Extend with custom commands and hooks
|
|
196
|
+
• Command recording/replay - Automate workflows
|
|
197
|
+
• Sessions & bookmarks - Save and restore your workspace
|
|
198
|
+
• Multi-line prompts - Full support for prompts with newlines
|
|
199
|
+
• Stats & analytics - :stats shows usage patterns and performance
|
|
200
|
+
• Validation rules - :validate rm -rf / = block for safety
|
|
201
|
+
• 6 color themes - :theme solarized|dracula|gruvbox|nord|monokai|default
|
|
202
|
+
• Auto-correct - Smart typo detection with suggestions
|
|
203
|
+
• Shell scripts - Full bash support (for, while, if loops)
|
|
204
|
+
• AI integration - @ for questions, @@ for command suggestions
|
|
205
|
+
• Ruby functions - :defun for custom shell commands
|
|
206
|
+
• 18 tool completions - git, docker, kubectl, terraform, aws, etc.
|
|
207
|
+
|
|
208
|
+
QUICK START:
|
|
209
|
+
• :help - Command reference
|
|
210
|
+
• :info --features - Feature list
|
|
211
|
+
• :nick - Create alias
|
|
212
|
+
• :bm - Bookmark directory
|
|
213
|
+
• :stats - View analytics
|
|
214
|
+
• :theme - Change colors
|
|
215
|
+
• :plugins - Extend functionality
|
|
216
|
+
|
|
217
|
+
CUSTOMIZATION:
|
|
218
|
+
• Config file: ~/.rshrc (edit with :config or manually)
|
|
219
|
+
• Colors: All themeable (see :help)
|
|
220
|
+
• Exit: Ctrl-D (save) or Ctrl-E (don't save)
|
|
221
|
+
|
|
222
|
+
MORE INFO:
|
|
223
|
+
• GitHub: https://github.com/isene/rsh
|
|
224
|
+
• Docs: Type :help for quick reference
|
|
225
|
+
• Version: Type :version for current/latest
|
|
249
226
|
|
|
250
227
|
INFO
|
|
251
228
|
|
|
@@ -356,19 +333,73 @@ def getstr # A custom Readline-like function
|
|
|
356
333
|
@pos = @ai_suggestion.length
|
|
357
334
|
@ai_suggestion = nil
|
|
358
335
|
end
|
|
336
|
+
|
|
337
|
+
# Print prompt ONCE at start (optimization + multi-line support)
|
|
359
338
|
@row0, p = @c.pos
|
|
339
|
+
|
|
340
|
+
# Clear any previous prompt
|
|
341
|
+
@c.row(@row0)
|
|
342
|
+
@c.clear_screen_down
|
|
343
|
+
|
|
344
|
+
print @display_prompt
|
|
345
|
+
|
|
346
|
+
# Calculate positions and save prompt parts
|
|
347
|
+
if @display_prompt.include?("\n")
|
|
348
|
+
# Multi-line prompt
|
|
349
|
+
newline_count = @display_prompt.count("\n")
|
|
350
|
+
@row0 += newline_count
|
|
351
|
+
|
|
352
|
+
# Extract last line and reapply color codes (rcurses pattern)
|
|
353
|
+
# Detect ANY color codes at start of full prompt
|
|
354
|
+
color_codes = ""
|
|
355
|
+
if @display_prompt =~ /^(\001\e\[[0-9;]+m\002)/
|
|
356
|
+
color_codes = $1
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
# Split and get last line
|
|
360
|
+
lines = @display_prompt.split("\n")
|
|
361
|
+
@prompt_last_line = lines.last
|
|
362
|
+
|
|
363
|
+
# If original had colors and last line doesn't, reapply them
|
|
364
|
+
if !color_codes.empty? && !@prompt_last_line.start_with?("\001")
|
|
365
|
+
@prompt_last_line = color_codes + @prompt_last_line + "\001\e[0m\002"
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
# Calculate visible length (strip ANSI for counting)
|
|
369
|
+
@pos0 = @prompt_last_line.gsub(/\001?\e\[[0-9;]*m\002?/, '').length
|
|
370
|
+
@cmd_row = @row0
|
|
371
|
+
@is_multiline = true
|
|
372
|
+
else
|
|
373
|
+
# Single-line prompt
|
|
374
|
+
row, @pos0 = @c.pos
|
|
375
|
+
@prompt_last_line = @display_prompt
|
|
376
|
+
@cmd_row = @row0
|
|
377
|
+
@is_multiline = false
|
|
378
|
+
end
|
|
379
|
+
|
|
360
380
|
while chr != "ENTER" # Keep going with readline until user presses ENTER
|
|
361
381
|
@ci = nil
|
|
362
382
|
lift = false
|
|
363
383
|
right = false
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
@c.
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
384
|
+
|
|
385
|
+
# Update command line display (not the prompt!)
|
|
386
|
+
@c.row(@cmd_row)
|
|
387
|
+
|
|
388
|
+
# Reprint the prompt line (preserves colors)
|
|
389
|
+
if @is_multiline
|
|
390
|
+
@c.col(1)
|
|
391
|
+
print @prompt_last_line
|
|
392
|
+
@c.clear_line_after
|
|
393
|
+
else
|
|
394
|
+
@c.col(1)
|
|
395
|
+
print @prompt_last_line
|
|
396
|
+
@c.clear_line_after
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
# Print command text with syntax highlighting
|
|
371
400
|
print cmd_check(@history[0])
|
|
401
|
+
|
|
402
|
+
# Print history suggestion if available
|
|
372
403
|
@ci = @history[1..].find_index {|e| e =~ /^#{Regexp.escape(@history[0].to_s)}./}
|
|
373
404
|
unless @ci == nil
|
|
374
405
|
@ci += 1
|
|
@@ -378,15 +409,17 @@ def getstr # A custom Readline-like function
|
|
|
378
409
|
print @ciprompt.c(@c_stamp)
|
|
379
410
|
right = true
|
|
380
411
|
end
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
@
|
|
386
|
-
@c.row(@c.rowget - 1)
|
|
412
|
+
|
|
413
|
+
# Position cursor (different logic for single vs multi-line)
|
|
414
|
+
if @is_multiline
|
|
415
|
+
# Multi-line: @pos0 is string length (0-indexed), need +1 for terminal
|
|
416
|
+
cursor_col = @pos0 + @pos + 1
|
|
387
417
|
else
|
|
388
|
-
@c.
|
|
418
|
+
# Single-line: @pos0 already from @c.pos (1-indexed)
|
|
419
|
+
cursor_col = @pos0 + @pos
|
|
389
420
|
end
|
|
421
|
+
@c.row(@cmd_row)
|
|
422
|
+
@c.col(cursor_col)
|
|
390
423
|
chr = getchr
|
|
391
424
|
puts "DEBUG: Got char: '#{chr}' (length: #{chr.length})" if ENV['RSH_DEBUG']
|
|
392
425
|
case chr
|
|
@@ -416,8 +449,21 @@ def getstr # A custom Readline-like function
|
|
|
416
449
|
exit
|
|
417
450
|
when 'C-L' # Clear screen and set position to top of the screen
|
|
418
451
|
@c.row(1)
|
|
419
|
-
@row0 = 1
|
|
420
452
|
@c.clear_screen_down
|
|
453
|
+
# Reprint prompt after clear
|
|
454
|
+
@row0 = 1
|
|
455
|
+
print @display_prompt
|
|
456
|
+
# Recalculate positions
|
|
457
|
+
if @display_prompt.include?("\n")
|
|
458
|
+
newline_count = @display_prompt.count("\n")
|
|
459
|
+
@row0 += newline_count
|
|
460
|
+
last_line = @display_prompt.split("\n").last
|
|
461
|
+
@pos0 = last_line.gsub(/\001?\e\[[0-9;]*m\002?/, '').length
|
|
462
|
+
@cmd_row = @row0
|
|
463
|
+
else
|
|
464
|
+
row, @pos0 = @c.pos
|
|
465
|
+
@cmd_row = @row0
|
|
466
|
+
end
|
|
421
467
|
when 'UP' # Go up in history
|
|
422
468
|
if @stk == 0 and @history[0].length > 0
|
|
423
469
|
@tabsearch = @history[0]
|
|
@@ -436,8 +482,6 @@ def getstr # A custom Readline-like function
|
|
|
436
482
|
end
|
|
437
483
|
lift = false
|
|
438
484
|
end
|
|
439
|
-
@c.row(@row0)
|
|
440
|
-
@c.clear_screen_down
|
|
441
485
|
when 'DOWN' # Go down in history
|
|
442
486
|
if lift
|
|
443
487
|
@history.unshift("")
|
|
@@ -457,8 +501,6 @@ def getstr # A custom Readline-like function
|
|
|
457
501
|
@pos = @history[0].length
|
|
458
502
|
end
|
|
459
503
|
lift = false
|
|
460
|
-
@c.row(@row0)
|
|
461
|
-
@c.clear_screen_down
|
|
462
504
|
when 'RIGHT' # Move right on the readline
|
|
463
505
|
if right
|
|
464
506
|
if lift
|
|
@@ -633,10 +675,17 @@ def tab(type)
|
|
|
633
675
|
completed = @tabstr + "/"
|
|
634
676
|
@history[0] = @pretab + completed + @postab
|
|
635
677
|
@pos = @pretab.length + completed.length
|
|
636
|
-
|
|
678
|
+
# Consistent cursor calc
|
|
679
|
+
if @is_multiline
|
|
680
|
+
@c_col = @pos0 + @pos + 1
|
|
681
|
+
else
|
|
682
|
+
@c_col = @pos0 + @pos
|
|
683
|
+
end
|
|
637
684
|
@c.clear_line
|
|
638
685
|
line_display = cmd_check(@history[0]).to_s
|
|
639
|
-
|
|
686
|
+
# Use last line only for multi-line prompts
|
|
687
|
+
prompt_display = @is_multiline ? @display_prompt.split("\n").last : @display_prompt
|
|
688
|
+
print prompt_display + line_display
|
|
640
689
|
@c.col(@c_col)
|
|
641
690
|
return
|
|
642
691
|
end
|
|
@@ -851,6 +900,9 @@ def tab(type)
|
|
|
851
900
|
@newhist0 = @pretab + tabchoice + @postab # Remember now the new value to be given to @history[0]
|
|
852
901
|
line1 = cmd_check(@pretab).to_s # Syntax highlight before @tabstr
|
|
853
902
|
line2 = cmd_check(@postab).to_s # Syntax highlight after @tabstr
|
|
903
|
+
|
|
904
|
+
# For multi-line prompts, only show last line during tab completion
|
|
905
|
+
prompt_for_tab = @display_prompt.include?("\n") ? @display_prompt.split("\n").last : @display_prompt
|
|
854
906
|
# Color and underline the current tabchoice on the commandline with file type color:
|
|
855
907
|
display_choice = tabchoice.dup
|
|
856
908
|
clean_choice = tabchoice.gsub(/['"]/, '').chomp('/')
|
|
@@ -861,9 +913,14 @@ def tab(type)
|
|
|
861
913
|
# Escape regex special characters in @tabstr for pattern matching
|
|
862
914
|
escaped_tabstr = Regexp.escape(@tabstr)
|
|
863
915
|
tabline = display_choice.sub(/(.*)#{escaped_tabstr}(.*)/, '\1'.c(choice_color) + @tabstr.u.c(choice_color) + '\2'.c(choice_color))
|
|
864
|
-
print
|
|
916
|
+
print prompt_for_tab + line1 + tabline + line2 # Print the commandline (use last line only for multi-line)
|
|
865
917
|
@pos = @pretab.length.to_i + tabchoice.length.to_i # Set the position on that commandline
|
|
866
|
-
|
|
918
|
+
# Consistent cursor positioning
|
|
919
|
+
if @is_multiline
|
|
920
|
+
@c_col = @pos0 + @pos + 1 # Multi-line: string length needs +1
|
|
921
|
+
else
|
|
922
|
+
@c_col = @pos0 + @pos # Single-line: already 1-indexed
|
|
923
|
+
end
|
|
867
924
|
@c.col(@c_col) # Set the cursor position
|
|
868
925
|
nextline # Then start showing the completion items
|
|
869
926
|
tabline = @tabarray[i] # Get the next matching tabline
|
|
@@ -3541,9 +3598,11 @@ loop do
|
|
|
3541
3598
|
@cmd = hi if hi
|
|
3542
3599
|
end
|
|
3543
3600
|
# Move cursor to end of line and print the full command before clearing
|
|
3544
|
-
@c.row(@row0)
|
|
3601
|
+
@c.row(@cmd_row || @row0) # Use cmd_row if set (multi-line)
|
|
3545
3602
|
@c.clear_line
|
|
3546
|
-
print
|
|
3603
|
+
# For multi-line, only print last line; for single-line, print full prompt
|
|
3604
|
+
prompt_to_print = (@display_prompt.include?("\n") && @prompt_last_line) ? @prompt_last_line : @display_prompt
|
|
3605
|
+
print prompt_to_print + cmd_check(@cmd)
|
|
3547
3606
|
print "\n"; @c.clear_screen_down
|
|
3548
3607
|
if @cmd == "r" # Integration with rtfm (https://github.com/isene/RTFM)
|
|
3549
3608
|
t = Time.now
|
metadata
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby-shell
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Geir Isene
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-10-
|
|
11
|
+
date: 2025-10-31 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: 'A shell written in Ruby with extensive tab completions, aliases/nicks,
|
|
14
14
|
history, syntax highlighting, theming, auto-cd, auto-opening files and more. UPDATE
|
|
15
|
-
v3.
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
v3.6.0: MULTI-LINE PROMPT SUPPORT - Complete readline refactor with rcurses-inspired
|
|
16
|
+
ANSI handling. Define prompts with newlines! Plus nick/history export, 9 new completions,
|
|
17
|
+
validation templates, startup tips, and critical performance fixes for huge PATHs!'
|
|
18
18
|
email: g@isene.com
|
|
19
19
|
executables:
|
|
20
20
|
- rsh
|