ruby-shell 0.4 → 0.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 +4 -4
- data/README.md +3 -1
- data/bin/rsh +88 -72
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a90c70f4301d27cd625341258f896e214b489b7bc7f94df209696970f00d44e9
|
|
4
|
+
data.tar.gz: 769a76676650f1bc307c22dcc4f6b2198196673b7c70acead191d6a08c802e30
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 78db98d6b5f0925ad5460985479480e95f03faa42ec8a4d136ad63962d956b41aab7df0077131a05546fd3d05329023242e848f138ffa87ccc0ba138f9a07d24
|
|
7
|
+
data.tar.gz: 306debaadf9e812c4cb6ee47e153964a2c00c866ec4208e8b5ea04b645b571004136c081e6529f54a3696515e6446bb206d9c0cfee653a24bce6e69bf3ae975a
|
data/README.md
CHANGED
|
@@ -29,7 +29,9 @@ Or simply `gem install ruby-shell`.
|
|
|
29
29
|
Add command nicks (aliases) with `:nick "some_nick = some_command"`, e.g. `:nick "ls = ls --color"`. Add general nicks that will substitute anything on a command line (not just commands) like this `:gnick "some_gnick = some_command"`, e.g. `:gnick "x = /home/user/somewhere"`. List (g)nicks with `:nick?`. Remove a nick with `:nick "-some_command"`, e.g. `:nick "-ls"` to remove an `ls` nick. Same for gnicks.
|
|
30
30
|
|
|
31
31
|
## Tab completion
|
|
32
|
-
You can tab complete almost anything. Hitting `TAB` will try to complete in this priority: nicks, gnicks, commands, dirs/files. Hitting `TAB`after a `-` will list the command switches for the preceding command with a short explanation (from the command's --help), like this `ls -`(`TAB`) will list all the switches/options for the `ls` command.
|
|
32
|
+
You can tab complete almost anything. Hitting `TAB` will try to complete in this priority: nicks, gnicks, commands, dirs/files. Hitting `TAB`after a `-` will list the command switches for the preceding command with a short explanation (from the command's --help), like this `ls -`(`TAB`) will list all the switches/options for the `ls` command. You can add to (or subtract from) the search criteria while selecting possible matches - hit any letter to specify the search, while backspace removes a letter from the search criteria.
|
|
33
|
+
|
|
34
|
+
Hitting Shift-TAB will do a similar search through the command history - but with a general match of the search criteria (not only matching at the start).
|
|
33
35
|
|
|
34
36
|
## Integrations
|
|
35
37
|
rsh is integrated with the [rtfm file manager](https://github.com/isene/RTFM) and with [fzf](https://github.com/junegunn/fzf). Just enter the command `r` and rtfm will be launched - and when you quit the file manager, you will drop back into rsh in the directory you where you exited rtfm. Enter the command `fzf` to launch the fuzzy finder - select the directory/file you want, press `ENTER` and you will find yourself in the directory where that item resides.
|
data/bin/rsh
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# for any damages resulting from its use. Further, I am under no
|
|
15
15
|
# obligation to maintain or extend this software. It is provided
|
|
16
16
|
# on an 'as is' basis without any expressed or implied warranty.
|
|
17
|
-
@version = "0.
|
|
17
|
+
@version = "0.6"
|
|
18
18
|
|
|
19
19
|
# MODULES, CLASSES AND EXTENSIONS
|
|
20
20
|
class String # Add coloring to strings (with escaping for Readline)
|
|
@@ -38,7 +38,7 @@ module Cursor # Terminal cursor movement ANSI codes (thanks to https://github.co
|
|
|
38
38
|
def pos # Query cursor current position
|
|
39
39
|
res = ''
|
|
40
40
|
$stdin.raw do |stdin|
|
|
41
|
-
$stdout <<
|
|
41
|
+
$stdout << CSI + '6n' # Tha actual ANSI get-position
|
|
42
42
|
$stdout.flush
|
|
43
43
|
while (c = stdin.getc) != 'R'
|
|
44
44
|
res << c if c
|
|
@@ -93,6 +93,7 @@ module Cursor # Terminal cursor movement ANSI codes (thanks to https://github.co
|
|
|
93
93
|
print(CSI + 'J')
|
|
94
94
|
end
|
|
95
95
|
end
|
|
96
|
+
|
|
96
97
|
# INITIALIZATION
|
|
97
98
|
begin # Requires
|
|
98
99
|
require 'etc'
|
|
@@ -127,6 +128,7 @@ begin # Initialization
|
|
|
127
128
|
# Variable initializations
|
|
128
129
|
@cmd = "" # Initiate variable @cmd
|
|
129
130
|
end
|
|
131
|
+
|
|
130
132
|
# GENERIC FUNCTIONS
|
|
131
133
|
def getchr # Process key presses
|
|
132
134
|
c = STDIN.getch
|
|
@@ -244,29 +246,9 @@ def getstr # A custom Readline-like function
|
|
|
244
246
|
@history_copy[@stk] = ""
|
|
245
247
|
@pos = 0
|
|
246
248
|
when 'TAB' # Tab completion of dirs and files
|
|
247
|
-
@
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if @tabstr.match(" $")
|
|
251
|
-
elements.append("")
|
|
252
|
-
@tabsearch = ""
|
|
253
|
-
else
|
|
254
|
-
@tabsearch = elements.last.to_s
|
|
255
|
-
@tabstr = @tabstr[0...-@tabsearch.length]
|
|
256
|
-
end
|
|
257
|
-
i = elements.length - 1
|
|
258
|
-
if @tabsearch =~ /^-/
|
|
259
|
-
until i == 0
|
|
260
|
-
i -= 1
|
|
261
|
-
if elements[i] !~ /^-/
|
|
262
|
-
tab_switch(elements[i])
|
|
263
|
-
break
|
|
264
|
-
end
|
|
265
|
-
end
|
|
266
|
-
else
|
|
267
|
-
tab_all(@tabsearch)
|
|
268
|
-
end
|
|
269
|
-
@history_copy[@stk] = @tabstr.to_s + @tabsearch.to_s + @tabend.to_s
|
|
249
|
+
@tabsearch =~ /^-/ ? tabbing("switch") : tabbing("all")
|
|
250
|
+
when 'S-TAB'
|
|
251
|
+
tabbing("hist")
|
|
270
252
|
when /^.$/
|
|
271
253
|
@history_copy[@stk].insert(@pos,chr)
|
|
272
254
|
@pos += 1
|
|
@@ -280,18 +262,32 @@ def getstr # A custom Readline-like function
|
|
|
280
262
|
@history.insert(0, @history_copy[@stk])
|
|
281
263
|
@history[0]
|
|
282
264
|
end
|
|
283
|
-
def
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
@tabsearch
|
|
292
|
-
@
|
|
293
|
-
rescue
|
|
265
|
+
def tabbing(type)
|
|
266
|
+
@tabstr = @history_copy[@stk][0...@pos]
|
|
267
|
+
@tabend = @history_copy[@stk][@pos..]
|
|
268
|
+
elements = @tabstr.split(" ")
|
|
269
|
+
if @tabstr.match(" $")
|
|
270
|
+
elements.append("")
|
|
271
|
+
@tabsearch = ""
|
|
272
|
+
else
|
|
273
|
+
@tabsearch = elements.last.to_s
|
|
274
|
+
@tabstr = @tabstr[0...-@tabsearch.length]
|
|
294
275
|
end
|
|
276
|
+
i = elements.length - 1
|
|
277
|
+
if @tabsearch =~ /^-/
|
|
278
|
+
until i == 0
|
|
279
|
+
i -= 1
|
|
280
|
+
if elements[i] !~ /^-/
|
|
281
|
+
tab_switch(elements[i])
|
|
282
|
+
break
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
elsif type == 'all'
|
|
286
|
+
tab_all(@tabsearch)
|
|
287
|
+
elsif type == 'hist'
|
|
288
|
+
tab_hist(@tabsearch)
|
|
289
|
+
end
|
|
290
|
+
@history_copy[@stk] = @tabstr.to_s + @tabsearch.to_s + @tabend.to_s
|
|
295
291
|
end
|
|
296
292
|
def tab_all(str) # TAB completion for Dirs/files, nicks and commands
|
|
297
293
|
exe = []
|
|
@@ -302,34 +298,56 @@ def tab_all(str) # TAB completion for Dirs/files, nicks and commands
|
|
|
302
298
|
end
|
|
303
299
|
exe.prepend(*@nick.keys)
|
|
304
300
|
exe.prepend(*@gnick.keys)
|
|
305
|
-
compl
|
|
306
|
-
fdir
|
|
307
|
-
fdir
|
|
308
|
-
fdir
|
|
301
|
+
compl = exe.select {|s| s =~ Regexp.new("^" + str)}
|
|
302
|
+
fdir = str
|
|
303
|
+
fdir += "/" if Dir.exist?(fdir)
|
|
304
|
+
fdir += "*"
|
|
309
305
|
compl.prepend(*Dir.glob(fdir))
|
|
310
|
-
match
|
|
311
|
-
@tabsearch
|
|
312
|
-
@pos
|
|
306
|
+
match = tabselect(compl) unless compl.empty?
|
|
307
|
+
@tabsearch = match if match
|
|
308
|
+
@pos = @tabstr.length + @tabsearch.length if match
|
|
313
309
|
end
|
|
314
|
-
def
|
|
310
|
+
def tab_switch(str) # TAB completion for command switches (TAB after "-")
|
|
311
|
+
begin
|
|
312
|
+
hlp = `#{str} --help`
|
|
313
|
+
hlp = hlp.split("\n").grep(/^\s*-{1,2}[^-]/)
|
|
314
|
+
hlp = hlp.map {|h| h.sub(/^\s*/, '')}
|
|
315
|
+
switch = tabselect(hlp)
|
|
316
|
+
switch = switch.sub(/ .*/, '').sub(/,/, '')
|
|
317
|
+
@tabsearch = switch if switch
|
|
318
|
+
@pos = @tabstr.length + @tabsearch.length
|
|
319
|
+
rescue
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
def tab_hist(str)
|
|
323
|
+
sel = @history.select {|el| el =~ /#{str}/}
|
|
324
|
+
hist = tabselect(sel, true)
|
|
325
|
+
@tabsearch = hist if hist
|
|
326
|
+
@pos = @tabstr.length + @tabsearch.length if hist
|
|
327
|
+
end
|
|
328
|
+
def tabselect(ary, hist=false) # Let user select from the incoming array
|
|
329
|
+
ary.uniq!
|
|
315
330
|
@c_row, @c_col = @c.pos
|
|
316
331
|
chr = ""
|
|
317
332
|
i = 0
|
|
318
|
-
ary.length < 5 ? l = ary.length : l = 5
|
|
319
333
|
while chr != "ENTER"
|
|
320
334
|
@c.clear_screen_down
|
|
335
|
+
ary.length - i < 5 ? l = ary.length - i : l = 5
|
|
321
336
|
l.times do |x|
|
|
337
|
+
tl = @tabsearch.length
|
|
322
338
|
if x == 0
|
|
323
339
|
@c.clear_line
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
tabline = "#{@prompt}#{tabstart}#{@tabsearch.c(@c_tabselect)}#{tabchoice}#{@tabend}"
|
|
340
|
+
tabchoice = ary[i].sub(/(.*?)[ ,].*/, '\1')
|
|
341
|
+
tabline = "#{@prompt}#{cmd_check(@tabstr)}#{tabchoice.c(@c_tabselect)}#{@tabend}"
|
|
327
342
|
print tabline # Full command line
|
|
328
|
-
@c_col = @pos0 + @tabstr.length +
|
|
343
|
+
@c_col = @pos0 + @tabstr.length + tabchoice.length
|
|
329
344
|
nextline
|
|
330
|
-
print "
|
|
345
|
+
print " " + ary[i].sub(/(.*?)#{@tabsearch}(.*)/, '\1'.c(@c_tabselect) + @tabsearch + '\2'.c(@c_tabselect))
|
|
331
346
|
else
|
|
332
|
-
|
|
347
|
+
begin
|
|
348
|
+
print " " + ary[i+x].sub(/(.*?)#{@tabsearch}(.*)/, '\1'.c(@c_taboption) + @tabsearch + '\2'.c(@c_taboption))
|
|
349
|
+
rescue
|
|
350
|
+
end
|
|
333
351
|
end
|
|
334
352
|
nextline
|
|
335
353
|
end
|
|
@@ -348,11 +366,11 @@ def tabselect(ary) # Let user select from the incoming array
|
|
|
348
366
|
chr = "ENTER"
|
|
349
367
|
when 'BACK'
|
|
350
368
|
@tabsearch.chop! unless @tabsearch == ''
|
|
351
|
-
tab_all(@tabsearch)
|
|
369
|
+
hist ? tab_hist(@tabsearch) : tab_all(@tabsearch)
|
|
352
370
|
return @tabsearch
|
|
353
371
|
when /^[[:print:]]$/
|
|
354
372
|
@tabsearch += chr
|
|
355
|
-
tab_all(@tabsearch)
|
|
373
|
+
hist ? tab_hist(@tabsearch) : tab_all(@tabsearch)
|
|
356
374
|
return @tabsearch
|
|
357
375
|
end
|
|
358
376
|
end
|
|
@@ -380,7 +398,7 @@ def cmd_check(str) # Check if each element on the readline matches commands, nic
|
|
|
380
398
|
el.c(@c_nick)
|
|
381
399
|
elsif @gnick.include?(el)
|
|
382
400
|
el.c(@c_gnick)
|
|
383
|
-
elsif File.
|
|
401
|
+
elsif File.exist?(el.sub(/^~/, "/home/#{@user}"))
|
|
384
402
|
el.c(@c_path)
|
|
385
403
|
elsif system "which #{el}", %i[out err] => File::NULL
|
|
386
404
|
el.c(@c_cmd)
|
|
@@ -407,6 +425,7 @@ def rshrc # Write updates to .rshrc
|
|
|
407
425
|
File.write(Dir.home+'/.rshrc', conf)
|
|
408
426
|
puts "\n .rshrc updated"
|
|
409
427
|
end
|
|
428
|
+
|
|
410
429
|
# RSH FUNCTIONS
|
|
411
430
|
def history # Show history
|
|
412
431
|
puts "History:"
|
|
@@ -468,38 +487,35 @@ loop do
|
|
|
468
487
|
@cmd = getstr # Main work is here
|
|
469
488
|
hist_clean # Clean up the history
|
|
470
489
|
@cmd = "ls" if @cmd == "" # Default to ls when no command is given
|
|
471
|
-
print "\n"
|
|
490
|
+
print "\n"; @c.clear_screen_down
|
|
472
491
|
if @cmd == "r" # Integration with rtfm (https://github.com/isene/RTFM)
|
|
473
492
|
File.write("/tmp/.rshpwd", Dir.pwd)
|
|
474
493
|
system("rtfm /tmp/.rshpwd")
|
|
475
494
|
Dir.chdir(File.read("/tmp/.rshpwd"))
|
|
476
495
|
next
|
|
477
496
|
end
|
|
478
|
-
begin
|
|
497
|
+
begin
|
|
479
498
|
if @cmd.match(/^\s*:/) # Ruby commands are prefixed with ":"
|
|
480
499
|
eval(@cmd[1..-1])
|
|
481
|
-
else
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
500
|
+
else # Execute command
|
|
501
|
+
@cmd.sub!(/^cd (\S*).*/, '\1')
|
|
502
|
+
@cmd = Dir.home if @cmd == "~"
|
|
503
|
+
dir = @cmd.strip.sub(/~/, Dir.home)
|
|
504
|
+
if Dir.exists?(dir)
|
|
505
|
+
Dir.chdir(dir)
|
|
506
|
+
else
|
|
487
507
|
ca = @nick.transform_keys {|k| /((^\K\s*\K)|(\|\K\s*\K))\b(?<!-)#{Regexp.escape k}\b/}
|
|
488
508
|
@cmd = @cmd.gsub(Regexp.union(ca.keys), @nick)
|
|
489
509
|
ga = @gnick.transform_keys {|k| /\b#{Regexp.escape k}\b/}
|
|
490
510
|
@cmd = @cmd.gsub(Regexp.union(ga.keys), @gnick)
|
|
491
511
|
puts "#{Time.now.strftime("%H:%M:%S")}: #{@cmd}".c(@c_stamp)
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
512
|
+
if @cmd == "fzf" # fzf integration (https://github.com/junegunn/fzf)
|
|
513
|
+
res = `#{@cmd}`.chomp
|
|
514
|
+
Dir.chdir(File.dirname(res))
|
|
515
|
+
else
|
|
516
|
+
if File.exist?(@cmd) then system("#{ENV['EDITOR']} #{@cmd}") # Try open with user's editor
|
|
496
517
|
elsif system(@cmd) # Try execute the command
|
|
497
|
-
else
|
|
498
|
-
puts "No such command: #{@cmd}"
|
|
499
|
-
end
|
|
500
|
-
rescue
|
|
501
|
-
if File.exist?(@cmd) # Try to open file with user's editor
|
|
502
|
-
system("#{ENV['EDITOR']} #{@cmd}")
|
|
518
|
+
else puts "No such command: #{@cmd}"
|
|
503
519
|
end
|
|
504
520
|
end
|
|
505
521
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby-shell
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '0.
|
|
4
|
+
version: '0.6'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Geir Isene
|
|
@@ -11,7 +11,9 @@ cert_chain: []
|
|
|
11
11
|
date: 2023-05-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: 'A shell written in Ruby with extensive tab completions, aliases/nicks,
|
|
14
|
-
history, syntax highlighting and
|
|
14
|
+
history, syntax highlighting, theming and more. In continual development. New in
|
|
15
|
+
0.6: Included history search with Shift-TAB + general improvements (thanks to folks
|
|
16
|
+
at #ruby at Libera.Chat).'
|
|
15
17
|
email: g@isene.com
|
|
16
18
|
executables:
|
|
17
19
|
- rsh
|