ruby-shell 0.4 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
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