ruby-shell 0.3.1 → 0.5

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 +6 -0
  3. data/bin/rsh +108 -89
  4. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae06a31d3704b03f547c511116723ebfc3b890000fb74fac0b5cd098a44dbad5
4
- data.tar.gz: 81a6f4a939ebed04a679579e16daa6921d25a45bed4f30e8b59caba5c1300e75
3
+ metadata.gz: 43147c77abd46c4331dc8cf1c7ed4902f2849c7d11a67f00309ac45da5211c55
4
+ data.tar.gz: 99926b773d53e5b7302a954d62eb3f766ef6caf0c6837cfd77dbdabe4f6a7132
5
5
  SHA512:
6
- metadata.gz: 40bf4cf2c129d0ef8bdc114aec76e96b41b961467b2cc72bf962a2f7bb43d2225f6b9d2a142c7c90037ef4b526e35cb4e892906b984f22a85a142b1f9b0b5ae3
7
- data.tar.gz: 1cd7e4bc2ad55bf3906d107702f604e1931d555cad50b491a573556d4cc23d0273980aa0744f803dbec1d6f23a582f6adf7904f473b257917e06a00c0cf85a14
6
+ metadata.gz: f53b1c639d01623da942f8255bbfe3b32a53b95faf693c18a4520ac5541c3937a073e67cdd0cee5c2b3b24d71805ca412a45293cd85311bc90c1499af11ba271
7
+ data.tar.gz: a7c9b7d2255c62169b6cbf3b019f49a61843e3b0051836863c495278b69ce121b99b57208aea75e35a6d5d2b33085cd770644383d7505f3361501e6941aebed2
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
1
  # rsh
2
+ ![Ruby](https://img.shields.io/badge/language-Ruby-red) [![Gem Version](https://badge.fury.io/rb/ruby-shell.svg)](https://badge.fury.io/rb/ruby-shell) ![Unlicense](https://img.shields.io/badge/license-Unlicense-green) ![Stay Amazing](https://img.shields.io/badge/Stay-Amazing-important)
3
+
2
4
  The Ruby SHell
3
5
 
4
6
  # Why?
@@ -29,6 +31,9 @@ Add command nicks (aliases) with `:nick "some_nick = some_command"`, e.g. `:nick
29
31
  ## Tab completion
30
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.
31
33
 
34
+ ## Integrations
35
+ 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.
36
+
32
37
  ## Syntax highlighting
33
38
  rsh will highlight nicks, gnicks, commands and dirs/files as they are written on the command line.
34
39
 
@@ -44,6 +49,7 @@ Variable | Description
44
49
  `@c_path` | Color for valid path
45
50
  `@c_tabselect` | Color for selected tabcompleted item
46
51
  `@c_taboption` | Color for unselected tabcompleted item
52
+ `@c_stamp` | Color for time stamp/command
47
53
 
48
54
  # Enter the world of Ruby
49
55
  By entering `:some-ruby-command` you have full access to the Ruby universe right from your command line. You can do anything from `:puts 2 + 13` or `:if 0.7 > Math::sin(34) then puts "OK" end` or whatever tickles you fancy.
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.5"
18
18
 
19
19
  # MODULES, CLASSES AND EXTENSIONS
20
20
  class String # Add coloring to strings (with escaping for Readline)
@@ -101,31 +101,31 @@ begin # Requires
101
101
  end
102
102
  begin # Initialization
103
103
  # Theming
104
- @c_prompt = 196 # Color for basic prompt
105
- @c_cmd = 48 # Color for valid command
106
- @c_nick = 51 # Color for matching nick
107
- @c_gnick = 87 # Color for matching gnick
108
- @c_path = 208 # Color for valid path
109
- @c_switch = 148 # Color for switches/options
110
- @c_tabselect = 207 # Color for selected tabcompleted item
111
- @c_taboption = 244 # Color for unselected tabcompleted item
104
+ @c_prompt = 196 # Color for basic prompt
105
+ @c_cmd = 48 # Color for valid command
106
+ @c_nick = 51 # Color for matching nick
107
+ @c_gnick = 87 # Color for matching gnick
108
+ @c_path = 208 # Color for valid path
109
+ @c_switch = 148 # Color for switches/options
110
+ @c_tabselect = 207 # Color for selected tabcompleted item
111
+ @c_taboption = 244 # Color for unselected tabcompleted item
112
+ @c_stamp = 244 # Color for time stamp/command
112
113
  # Prompt
113
- @user = Etc.getlogin # For use in @prompt
114
- @node = Etc.uname[:nodename] # For use in @prompt
115
- @prompt = "rsh >".c(@c_prompt).b # Very basic prompt if not defined in .rshrc
114
+ @prompt = "rsh > ".c(@c_prompt).b # Very basic prompt if not defined in .rshrc
116
115
  # Hash & array initializations
117
- @nick = {} # Initiate alias/nick hash
118
- @gnick = {} # Initiate generic/global alias/nick hash
119
- @history = [] # Initiate history array
116
+ @nick = {} # Initiate alias/nick hash
117
+ @gnick = {} # Initiate generic/global alias/nick hash
118
+ @history = [] # Initiate history array
120
119
  # Paths
120
+ @user = Etc.getpwuid(Process.euid).name # For use in @prompt
121
121
  @path = ["/bin",
122
122
  "/usr/bin",
123
- "/home/#{@user}/bin"] # Basic paths for executables if not set in .rshrc
123
+ "/home/#{@user}/bin"] # Basic paths for executables if not set in .rshrc
124
124
  # History
125
- @histsize = 100 # Max history if not set in .rshrc
126
- @hloaded = false # Variable to determine if history is loaded
125
+ @histsize = 100 # Max history if not set in .rshrc
126
+ @hloaded = false # Variable to determine if history is loaded
127
127
  # Variable initializations
128
- @cmd = "" # Initiate variable @cmd
128
+ @cmd = "" # Initiate variable @cmd
129
129
  end
130
130
  # GENERIC FUNCTIONS
131
131
  def getchr # Process key presses
@@ -184,9 +184,9 @@ def getstr # A custom Readline-like function
184
184
  text = @history_copy[@stk]
185
185
  @c.clear_line
186
186
  print @prompt
187
- row, pos0 = @c.pos
187
+ row, @pos0 = @c.pos
188
188
  print cmd_check(text)
189
- @c.col(pos0 + @pos)
189
+ @c.col(@pos0 + @pos)
190
190
  chr = getchr
191
191
  return "\n" if chr == "C-G" # Ctrl-G escapes the reasdline
192
192
  case chr
@@ -225,7 +225,7 @@ def getstr # A custom Readline-like function
225
225
  @history_copy[@stk][@pos] = ""
226
226
  end
227
227
  when 'WBACK' # Delete one word to the left (Ctrl-W)
228
- unless @pos == pos0
228
+ unless @pos == @pos0
229
229
  until @history_copy[@stk][@pos - 1] == " " or @pos == 0
230
230
  @pos -= 1
231
231
  @history_copy[@stk][@pos] = ""
@@ -244,25 +244,29 @@ def getstr # A custom Readline-like function
244
244
  @history_copy[@stk] = ""
245
245
  @pos = 0
246
246
  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
- elements.append("") if @tabstr.match(" $")
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
251
257
  i = elements.length - 1
252
- m = elements[i].to_s
253
- if m == "-"
258
+ if @tabsearch =~ /^-/
254
259
  until i == 0
255
260
  i -= 1
256
261
  if elements[i] !~ /^-/
257
- @tabstr.chop!
258
262
  tab_switch(elements[i])
259
263
  break
260
264
  end
261
265
  end
262
266
  else
263
- tab_all(m)
267
+ tab_all(@tabsearch)
264
268
  end
265
- @history_copy[@stk] = @tabstr + @tabend
269
+ @history_copy[@stk] = @tabstr.to_s + @tabsearch.to_s + @tabend.to_s
266
270
  when /^.$/
267
271
  @history_copy[@stk].insert(@pos,chr)
268
272
  @pos += 1
@@ -277,13 +281,17 @@ def getstr # A custom Readline-like function
277
281
  @history[0]
278
282
  end
279
283
  def tab_switch(str) # TAB completion for command switches (TAB after "-")
280
- hlp = `#{str} --help`
281
- hlp = hlp.split("\n").grep(/^\s*-{1,2}[^-]/)
282
- hlp = hlp.map {|h| h.sub(/^\s*/, '')}
283
- switch, tab = tabselect(hlp)
284
- switch = switch.sub(/ .*/, '').sub(/,/, '')
285
- @tabstr += switch
286
- @pos = @tabstr.length
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
294
+ end
287
295
  end
288
296
  def tab_all(str) # TAB completion for Dirs/files, nicks and commands
289
297
  exe = []
@@ -294,41 +302,41 @@ def tab_all(str) # TAB completion for Dirs/files, nicks and commands
294
302
  end
295
303
  exe.prepend(*@nick.keys)
296
304
  exe.prepend(*@gnick.keys)
297
- compl = exe.select {|s| s =~ Regexp.new("^" + str)}
298
- fdir = File.expand_path(str)
299
- fdir += "/" if Dir.exist?(fdir)
300
- fdir += "*"
305
+ compl = exe.select {|s| s =~ Regexp.new("^" + str)}
306
+ fdir = str
307
+ fdir += "/" if Dir.exist?(fdir)
308
+ fdir += "*"
301
309
  compl.prepend(*Dir.glob(fdir))
302
- @tabstr = @tabstr.sub(/#{str}$/, '') unless compl.empty?
303
- match, tab = tabselect(compl) unless compl.empty?
304
- @tabstr += match if match
305
- @tabstr += str if match == ""
306
- @pos = @tabstr.length if match
307
- end
308
- def nextline # Handle going to the next line in the terminal
309
- row, col = @c.pos
310
- if row == @maxrow
311
- @c.scroll_down
312
- @c_row -= 1
313
- end
314
- @c.next_line
310
+ match = tabselect(compl) unless compl.empty?
311
+ @tabsearch = match if match
312
+ @pos = @tabstr.length + @tabsearch.length if match
315
313
  end
316
314
  def tabselect(ary) # Let user select from the incoming array
317
315
  @c_row, @c_col = @c.pos
318
316
  chr = ""
319
- tab = false
320
317
  i = 0
321
- ary.length < 5 ? l = ary.length : l = 5
318
+ ary.length - i < 5 ? l = ary.length - i : l = 5
322
319
  while chr != "ENTER"
323
320
  @c.clear_screen_down
324
321
  l.times do |x|
322
+ tl = @tabsearch.length
325
323
  if x == 0
326
324
  @c.clear_line
327
- print "#{@prompt}#{@tabstr}#{ary[i].sub(/(.*?)[ ,].*/, '\1')}#{@tabend}"
325
+ tabchoice = ary[i].sub(/(.*?)[ ,].*/, '\1')
326
+ tabline = "#{@prompt}#{cmd_check(@tabstr)}#{tabchoice.c(@c_tabselect)}#{@tabend}"
327
+ print tabline # Full command line
328
+ @c_col = @pos0 + @tabstr.length + tabchoice.length
328
329
  nextline
329
- print " #{ary[i]}".c(@c_tabselect)
330
+ sel0 = " " + ary[i][0...tl]
331
+ sel1 = ary[i][tl...].c(@c_tabselect)
332
+ print sel0 + sel1 # Top option selected
330
333
  else
331
- print " #{ary[x+i]}".c(@c_taboption)
334
+ begin
335
+ opt0 = " " + ary[i+x][0...tl]
336
+ opt1 = ary[i+x][tl...].c(@c_taboption)
337
+ print opt0 + opt1 # Next option unselected
338
+ rescue
339
+ end
332
340
  end
333
341
  nextline
334
342
  end
@@ -343,15 +351,30 @@ def tabselect(ary) # Let user select from the incoming array
343
351
  i += 1 unless i > ary.length - 2
344
352
  when 'UP'
345
353
  i -= 1 unless i == 0
346
- when'TAB'
354
+ when 'TAB'
347
355
  chr = "ENTER"
348
- tab = true
356
+ when 'BACK'
357
+ @tabsearch.chop! unless @tabsearch == ''
358
+ tab_all(@tabsearch)
359
+ return @tabsearch
360
+ when /^[[:print:]]$/
361
+ @tabsearch += chr
362
+ tab_all(@tabsearch)
363
+ return @tabsearch
349
364
  end
350
365
  end
351
366
  @c.clear_screen_down
352
367
  @c.row(@c_row)
353
368
  @c.col(@c_col)
354
- return ary[i], tab
369
+ return ary[i]
370
+ end
371
+ def nextline # Handle going to the next line in the terminal
372
+ row, col = @c.pos
373
+ if row == @maxrow
374
+ @c.scroll_down
375
+ @c_row -= 1
376
+ end
377
+ @c.next_line
355
378
  end
356
379
  def hist_clean # Clean up @history
357
380
  @history.uniq!
@@ -445,45 +468,41 @@ end
445
468
 
446
469
  # MAIN PART
447
470
  loop do
471
+ @user = Etc.getpwuid(Process.euid).name # For use in @prompt
472
+ @node = Etc.uname[:nodename] # For use in @prompt
448
473
  h = @history; load(Dir.home+'/.rshrc') if File.exist?(Dir.home+'/.rshrc'); @history = h # reload prompt but not history
449
474
  @prompt.gsub!(/#{Dir.home}/, '~') # Simplify path in prompt
450
475
  @cmd = getstr # Main work is here
451
476
  hist_clean # Clean up the history
452
477
  @cmd = "ls" if @cmd == "" # Default to ls when no command is given
453
- print "\n" # Newline
454
- if @cmd == "x" then rshrc; break; end # A simple way to exit rsh
478
+ print "\n"; @c.clear_screen_down
455
479
  if @cmd == "r" # Integration with rtfm (https://github.com/isene/RTFM)
456
480
  File.write("/tmp/.rshpwd", Dir.pwd)
457
481
  system("rtfm /tmp/.rshpwd")
458
482
  Dir.chdir(File.read("/tmp/.rshpwd"))
459
483
  next
460
484
  end
461
- begin # Execute command
485
+ begin
462
486
  if @cmd.match(/^\s*:/) # Ruby commands are prefixed with ":"
463
487
  eval(@cmd[1..-1])
464
- else
465
- begin # Try cd to cmd
466
- @cmd.sub!(/^cd (\S*).*/, '\1')
467
- @cmd = Dir.home if @cmd == "~"
468
- Dir.chdir(@cmd.strip.sub(/~/, Dir.home))
469
- rescue # If cd fails, execute cmd (unless no such cmd)
470
- ca = @nick.transform_keys {|k| /((^\K\s*\K)|(\|\K\s*\K))\b(?<!-)#{Regexp.escape k}\b/}
471
- @cmd = @cmd.gsub(Regexp.union(ca.keys), @nick)
472
- ga = @gnick.transform_keys {|k| /\b#{Regexp.escape k}\b/}
473
- @cmd = @cmd.gsub(Regexp.union(ga.keys), @gnick)
474
- puts "#{Time.now.strftime("%H:%M:%S")}: #{@cmd}".c(244)
475
- begin
476
- if @cmd == "fzf" # fzf integration (https://github.com/junegunn/fzf)
477
- res = `#{@cmd}`.chomp
478
- Dir.chdir(File.dirname(res))
479
- elsif system(@cmd) # Try execute the command
480
- else
481
- puts "No such command: #{@cmd}"
482
- end
483
- rescue
484
- if File.exist?(@cmd) # Try to open file with user's editor
485
- system("#{ENV['EDITOR']} #{@cmd}")
486
- end
488
+ else # Execute command
489
+ @cmd.sub!(/^cd (\S*).*/, '\1')
490
+ @cmd = Dir.home if @cmd == "~"
491
+ dir = @cmd.strip.sub(/~/, Dir.home)
492
+ Dir.chdir(dir) if Dir.exists?(dir)
493
+ ca = @nick.transform_keys {|k| /((^\K\s*\K)|(\|\K\s*\K))\b(?<!-)#{Regexp.escape k}\b/}
494
+ @cmd = @cmd.gsub(Regexp.union(ca.keys), @nick)
495
+ ga = @gnick.transform_keys {|k| /\b#{Regexp.escape k}\b/}
496
+ @cmd = @cmd.gsub(Regexp.union(ga.keys), @gnick)
497
+ puts "#{Time.now.strftime("%H:%M:%S")}: #{@cmd}".c(@c_stamp)
498
+ if @cmd == "fzf" # fzf integration (https://github.com/junegunn/fzf)
499
+ res = `#{@cmd}`.chomp
500
+ Dir.chdir(File.dirname(res))
501
+ else
502
+ if File.exist?(@cmd) # Try to open file with user's editor
503
+ system("#{ENV['EDITOR']} #{@cmd}")
504
+ elsif system(@cmd) # Try execute the command
505
+ else puts "No such command: #{@cmd}"
487
506
  end
488
507
  end
489
508
  end
metadata CHANGED
@@ -1,18 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-shell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: '0.5'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-24 00:00:00.000000000 Z
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.3.1: Removed unwanted control
15
- chars in input.'
14
+ history, syntax highlighting and theming. New in 0.5: Code clean-up. Even better
15
+ tab completion.'
16
16
  email: g@isene.com
17
17
  executables:
18
18
  - rsh