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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/bin/rsh +88 -72
  4. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 03f10b7b8ca979952b3a717420c8cc6002c2ad443933b7006ba9c460e83ef09e
4
- data.tar.gz: fee02bd24b9796a4ab8852fa4a9ca6d591942b4aa08461e7decaf7ecf73da334
3
+ metadata.gz: a90c70f4301d27cd625341258f896e214b489b7bc7f94df209696970f00d44e9
4
+ data.tar.gz: 769a76676650f1bc307c22dcc4f6b2198196673b7c70acead191d6a08c802e30
5
5
  SHA512:
6
- metadata.gz: 817094937e32711d26dcc291c5c470e85a1f3901a335c427eede150465747f0761939ce5ccd686630bc3daf0200976533d4fe5e9f3259a364ed384c983aafb0f
7
- data.tar.gz: 1f6401e2afef2bb22089b5e28e5c977cf42b85e66182a223e780c25319ec77e168588afc74ea9713224e20bbd1d892da52510c66dc02876b1cec67013c09d231
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.3.1"
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 << "\e[6n"
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
- @tabstr = @history_copy[@stk][0...@pos]
248
- @tabend = @history_copy[@stk][@pos..]
249
- elements = @tabstr.split(" ")
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 tab_switch(str) # TAB completion for command switches (TAB after "-")
284
- begin
285
- hlp = `#{str} --help`
286
- hlp = hlp.split("\n").grep(/^\s*-{1,2}[^-]/)
287
- hlp = hlp.map {|h| h.sub(/^\s*/, '')}
288
- switch = tabselect(hlp)
289
- switch = switch.sub(/ .*/, '').sub(/,/, '')
290
- @tabsearch.chop!
291
- @tabsearch += switch
292
- @pos = @tabstr.length + @tabsearch.length
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 = exe.select {|s| s =~ Regexp.new("^" + str)}
306
- fdir = str
307
- fdir += "/" if Dir.exist?(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 = tabselect(compl) unless compl.empty?
311
- @tabsearch = match if match
312
- @pos = @tabstr.length + @tabsearch.length if match
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 tabselect(ary) # Let user select from the incoming array
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
- tabstart = cmd_check(@tabstr)
325
- tabchoice = ary[i].sub(/(.*?)[ ,].*/, '\1')[@tabsearch.length..]
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 + @tabsearch.length + tabchoice.length
343
+ @c_col = @pos0 + @tabstr.length + tabchoice.length
329
344
  nextline
330
- print " #{ary[i]}".c(@c_tabselect) # Top option selected
345
+ print " " + ary[i].sub(/(.*?)#{@tabsearch}(.*)/, '\1'.c(@c_tabselect) + @tabsearch + '\2'.c(@c_tabselect))
331
346
  else
332
- print " #{ary[x+i]}".c(@c_taboption) # Next option unselected
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.exists?(el.sub(/^~/, "/home/#{@user}"))
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" # Newline
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 # Execute command
497
+ begin
479
498
  if @cmd.match(/^\s*:/) # Ruby commands are prefixed with ":"
480
499
  eval(@cmd[1..-1])
481
- else
482
- begin # Try cd to cmd
483
- @cmd.sub!(/^cd (\S*).*/, '\1')
484
- @cmd = Dir.home if @cmd == "~"
485
- Dir.chdir(@cmd.strip.sub(/~/, Dir.home))
486
- rescue # If cd fails, execute cmd (unless no such cmd)
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
- begin
493
- if @cmd == "fzf" # fzf integration (https://github.com/junegunn/fzf)
494
- res = `#{@cmd}`.chomp
495
- Dir.chdir(File.dirname(res))
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'
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 theming. New in 0.4: Much better tab completion.'
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