ruby-shell 0.1

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 (5) hide show
  1. checksums.yaml +7 -0
  2. data/.rshrc +12 -0
  3. data/README.md +49 -0
  4. data/bin/rsh +486 -0
  5. metadata +48 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a6549e60bd6e3eadce8bb94374b5ce63808623993dc3392dacef9baa6aa096db
4
+ data.tar.gz: a182ba6217152b67ce55167fc7298b46870daf207a472815e3b8dfe2502b8dd2
5
+ SHA512:
6
+ metadata.gz: faeff68227a6184f93db225bebfff949243b5e5bc92f8d3d6fdb8a84859d5b5af27cd783983fd478402ff0caef56f0bc464bcf076792b38affac0199a8369d3f
7
+ data.tar.gz: b53005bad6d781cc5e113110ee7e56fb90e79f7643044a61ddfc4f4648637f245f84b2d5af6b8134b6693d941251cea472100eb14a7bc934f09dab96b46ec86e
data/.rshrc ADDED
@@ -0,0 +1,12 @@
1
+ @prompt = "#{@user}@#{@node}".c(46) + ":".c(255) + " #{Dir.pwd}/".c(196) + " ".c(7)
2
+ @nick = {"ls"=>"ls --color -F", "la"=>"ls -a --color -F", "ll"=>"ls -l --color -F", "l"=>"less"}
3
+ @gnick = {}
4
+ @history = []
5
+ @c_prompt = 196 # Color for basic prompt
6
+ @c_cmd = 48 # Color for valid command
7
+ @c_nick = 51 # Color for matching nick
8
+ @c_gnick = 87 # Color for matching gnick
9
+ @c_path = 208 # Color for valid path
10
+ @c_tabselect = 207 # Color for selected tabcompleted item
11
+ @c_taboption = 244 # Color for unselected tabcompleted item
12
+
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # rsh
2
+ The Ruby SHell
3
+
4
+ # Why?
5
+ Ruby is my goto language (pun kinda intended). I want full control over my tools and I like challenges that I can tinker with late at night. This is an incomplete project continually being improved. Feel free to add suggestions or code.
6
+
7
+ # Design principles
8
+ Simple. One file. Minimum external requirements.
9
+
10
+ # Installation
11
+ Clone this repo and drop `rsh` into your preferred bin directory. Drop `.rshrc` into your home directory and edit as you see fit.
12
+
13
+ Or simply `gem install rsh`.
14
+
15
+ # Features
16
+ * Aliases (called `nicks`in rsh) - both for commands and general nicks
17
+ * Syntax highlighting, matching nicks, system commands and valid dirs/files
18
+ * Tab completions for nicks, system commands, command switches and dirs/files
19
+ * Tab completion presents matches in a list to pick from
20
+ * History with simple editing
21
+ * Config file (`.rshrc`) updates on exit
22
+ * Set of simple rsh specific commands like `nick`, `nick?`, `history` and `rmhistory`
23
+ * rsh specific commands and full set of Ruby commands available via `:command`
24
+ * All colors are themable in `.rshrc`
25
+
26
+ ## Nicks
27
+ 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 `:nicks?`. Remove a nick with `:nick "-some_command"`, e.g. `:nick "-ls"` to remove an `ls` nick. Same for gnicks.
28
+
29
+ ## Tab completion
30
+ 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 preceeding 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
+
32
+ ## Syntax highlighting
33
+ rsh will highlight nicks, gnicks, commands and dirs/files as they are written on the command line.
34
+
35
+ ## Theming
36
+ In the supplied `.rshrc`, you will find a set of colors that you can change:
37
+
38
+ Variable | Description
39
+ ----------------|-----------------------------------------
40
+ `@c_prompt` | Color for basic prompt
41
+ `@c_cmd` | Color for valid command
42
+ `@c_nick` | Color for matching nick
43
+ `@c_gnick` | Color for matching gnick
44
+ `@c_path` | Color for valid path
45
+ `@c_tabselect` | Color for selected tabcompleted item
46
+ `@c_taboption` | Color for unselected tabcompleted item
47
+
48
+ # License and copyringht
49
+ Forget it.
data/bin/rsh ADDED
@@ -0,0 +1,486 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+ #
4
+ # SCRIPT INFO
5
+ # Name: RTFM - Ruby Terminal File Manager
6
+ # Language: Pure Ruby, best viewed in VIM
7
+ # Author: Geir Isene <g@isene.com>
8
+ # Web_site: http://isene.com/
9
+ # Github: https://github.com/isene/RTFM
10
+ # License: I release all copyright claims. This code is in the public domain.
11
+ # Permission is granted to use, copy modify, distribute, and sell
12
+ # this software for any purpose. I make no guarantee about the
13
+ # suitability of this software for any purpose and I am not liable
14
+ # for any damages resulting from its use. Further, I am under no
15
+ # obligation to maintain or extend this software. It is provided
16
+ # on an 'as is' basis without any expressed or implied warranty.
17
+ @version = "0.1"
18
+
19
+ # MODULES, CLASSES AND EXTENSIONS
20
+ class String # Add coloring to strings (with escaping for Readline)
21
+ def c(code); color(self, "\001\e[38;5;#{code}m\002"); end
22
+ def b; color(self, "\001\e[1m\002"); end
23
+ def i; color(self, "\001\e[3m\002"); end
24
+ def u; color(self, "\001\e[4m\002"); end
25
+ def l; color(self, "\001\e[5m\002"); end
26
+ def color(text, color_code) "#{color_code}#{text}\001\e[0m\002" end
27
+ end
28
+ module Cursor # Terminal cursor movement ANSI codes (thanks to https://github.com/piotrmurach/tty-cursor/tree/master)
29
+ module_function
30
+ ESC = "\e".freeze
31
+ CSI = "\e[".freeze
32
+ def save # Save current position
33
+ print(Gem.win_platform? ? CSI + 's' : ESC + '7')
34
+ end
35
+ def restore # Restore cursor position
36
+ print(Gem.win_platform? ? CSI + 'u' : ESC + '8')
37
+ end
38
+ def pos # Query cursor current position
39
+ res = ''
40
+ $stdin.raw do |stdin|
41
+ $stdout << "\e[6n"
42
+ $stdout.flush
43
+ while (c = stdin.getc) != 'R'
44
+ res << c if c
45
+ end
46
+ end
47
+ m = res.match /(?<row>\d+);(?<col>\d+)/
48
+ return m[:row].to_i, m[:col].to_i
49
+ end
50
+ def up(n = nil) # Move cursor up by n
51
+ print(CSI + "#{(n || 1)}A")
52
+ end
53
+ def down(n = nil) # Move the cursor down by n
54
+ print(CSI + "#{(n || 1)}B")
55
+ end
56
+ def left(n = nil) # Move the cursor backward by n
57
+ print(CSI + "#{n || 1}D")
58
+ end
59
+ def right(n = nil) # Move the cursor forward by n
60
+ print(CSI + "#{n || 1}C")
61
+ end
62
+ def col(n = nil) # Cursor moves to nth position horizontally in the current line
63
+ print(CSI + "#{n || 1}G")
64
+ end
65
+ def row(n = nil) # Cursor moves to the nth position vertically in the current column
66
+ print(CSI + "#{n || 1}d")
67
+ end
68
+ def next_line # Move cursor down to beginning of next line
69
+ print(CSI + 'E' + CSI + "1G")
70
+ end
71
+ def prev_line # Move cursor up to beginning of previous line
72
+ print(CSI + 'A' + CSI + "1G")
73
+ end
74
+ def clear_char(n = nil) # Erase n characters from the current cursor position
75
+ print(CSI + "#{n}X")
76
+ end
77
+ def clear_line # Erase the entire current line and return to beginning of the line
78
+ print(CSI + '2K' + CSI + "1G")
79
+ end
80
+ def clear_line_before # Erase from the beginning of the line up to and including the current cursor position.
81
+ print(CSI + '1K')
82
+ end
83
+ def clear_line_after # Erase from the current position (inclusive) to the end of the line
84
+ print(CSI + '0K')
85
+ end
86
+ def scroll_up # Scroll display up one line
87
+ print(ESC + 'M')
88
+ end
89
+ def scroll_down # Scroll display down one line
90
+ print(ESC + 'D')
91
+ end
92
+ def clear_screen_down
93
+ print(CSI + 'J')
94
+ end
95
+ end
96
+ # INITIALIZATION
97
+ begin # Requires
98
+ require 'etc'
99
+ require 'io/console'
100
+ end
101
+ begin # Initialization
102
+ # Theming
103
+ @c_prompt = 196 # Color for basic prompt
104
+ @c_cmd = 48 # Color for valid command
105
+ @c_nick = 51 # Color for matching nick
106
+ @c_gnick = 87 # Color for matching gnick
107
+ @c_path = 208 # Color for valid path
108
+ @c_tabselect = 207 # Color for selected tabcompleted item
109
+ @c_taboption = 244 # Color for unselected tabcompleted item
110
+ # Prompt
111
+ @user = Etc.getlogin # For use in @prompt
112
+ @node = Etc.uname[:nodename] # For use in @prompt
113
+ @prompt = "rsh >".c(@c_prompt).b # Very basic prompt if not defined in .rshrc
114
+ # Hash & array initializations
115
+ @nick = {} # Initiate alias/nick hash
116
+ @gnick = {} # Initiate generic/global alias/nick hash
117
+ @history = [] # Initiate history array
118
+ # Paths
119
+ @path = ["/bin",
120
+ "/usr/bin",
121
+ "/home/#{@user}/bin"] # Basic paths for executables if not set in .rshrc
122
+ # History
123
+ @histsize = 100 # Max history if not set in .rshrc
124
+ @hloaded = false # Variable to determine if history is loaded
125
+ # Variable initializations
126
+ @cmd = "" # Initiate variable @cmd
127
+ end
128
+ # GENERIC FUNCTIONS
129
+ def getchr # Process key presses
130
+ c = STDIN.getch
131
+ case c
132
+ when "\e" # ANSI escape sequences
133
+ case $stdin.getc
134
+ when '[' # CSI
135
+ case $stdin.getc
136
+ when 'A' then chr = "UP"
137
+ when 'B' then chr = "DOWN"
138
+ when 'C' then chr = "RIGHT"
139
+ when 'D' then chr = "LEFT"
140
+ when 'Z' then chr = "S-TAB"
141
+ when '2' then chr = "INS" ; chr = "C-INS" if STDIN.getc == "^"
142
+ when '3' then chr = "DEL" ; chr = "C-DEL" if STDIN.getc == "^"
143
+ when '5' then chr = "PgUP" ; chr = "C-PgUP" if STDIN.getc == "^"
144
+ when '6' then chr = "PgDOWN" ; chr = "C-PgDOWN" if STDIN.getc == "^"
145
+ when '7' then chr = "HOME" ; chr = "C-HOME" if STDIN.getc == "^"
146
+ when '8' then chr = "END" ; chr = "C-END" if STDIN.getc == "^"
147
+ end
148
+ when 'O' # Set Ctrl+ArrowKey equal to ArrowKey; May be used for other purposes in the future
149
+ case $stdin.getc
150
+ when 'a' then chr = "C-UP"
151
+ when 'b' then chr = "C-DOWN"
152
+ when 'c' then chr = "C-RIGHT"
153
+ when 'd' then chr = "C-LEFT"
154
+ end
155
+ end
156
+ when "", "" then chr = "BACK"
157
+ when "" then chr = "C-C"
158
+ when "" then chr = "C-D"
159
+ when "" then chr = "C-G"
160
+ when " " then chr = "C-K"
161
+ when " " then chr = "C-L"
162
+ when "" then chr = "C-N"
163
+ when "" then chr = "C-O"
164
+ when "" then chr = "C-P"
165
+ when "" then chr = "C-T"
166
+ when "" then chr = "C-Y"
167
+ when "" then chr = "WBACK"
168
+ when "" then chr = "LDEL"
169
+ when "\r" then chr = "ENTER"
170
+ when "\t" then chr = "TAB"
171
+ when /./ then chr = c
172
+ end
173
+ return chr
174
+ end
175
+ def getstr # A custom Readline-like function
176
+ @stk = 0
177
+ @pos = 0
178
+ chr = ""
179
+ @history.insert(0, "")
180
+ @history_copy = @history.map(&:clone)
181
+ while chr != "ENTER" # Keep going with readline until user presses ENTER
182
+ text = @history_copy[@stk]
183
+ @c.clear_line
184
+ print @prompt
185
+ row, pos0 = @c.pos
186
+ print cmd_check(text)
187
+ @c.col(pos0 + @pos)
188
+ chr = getchr
189
+ return "\n" if chr == "C-G" # Ctrl-G escapes the reasdline
190
+ case chr
191
+ when 'C-C' # Ctrl-C exits gracefully but without updating .rshrc
192
+ print "\n"
193
+ exit
194
+ when 'C-D' # Ctrl-D exits after updating .rshrc
195
+ rshrc
196
+ exit
197
+ when 'C-L' # Clear screen and set position to top of the screen
198
+ @c.row(1)
199
+ @c.clear_screen_down
200
+ when 'UP' # Go up in history
201
+ unless @stk >= @history_copy.length - 1
202
+ @stk += 1
203
+ @pos = @history_copy[@stk].length
204
+ end
205
+ when 'DOWN' # Go down in history
206
+ unless @stk == 0
207
+ @stk -= 1
208
+ @pos = @history_copy[@stk].length
209
+ end
210
+ when 'RIGHT' # Move right on the readline
211
+ @pos += 1 unless @pos >= @history_copy[@stk].length
212
+ when 'LEFT' # Move left on the readline
213
+ @pos -= 1 unless @pos <= 0
214
+ when 'HOME' # Go to beginning of the readline
215
+ @pos = 0
216
+ when 'END' # Go to the end of the readline
217
+ @pos = @history_copy[@stk].length
218
+ when 'DEL' # Delete one character
219
+ @history_copy[@stk][@pos] = ""
220
+ when 'BACK' # Delete one character to the left
221
+ unless @pos <= 0
222
+ @pos -= 1
223
+ @history_copy[@stk][@pos] = ""
224
+ end
225
+ when 'WBACK' # Delete one word to the left (Ctrl-W)
226
+ unless @pos == pos0
227
+ until @history_copy[@stk][@pos - 1] == " " or @pos == 0
228
+ @pos -= 1
229
+ @history_copy[@stk][@pos] = ""
230
+ end
231
+ if @history_copy[@stk][@pos - 1] == " "
232
+ @pos -= 1
233
+ @history_copy[@stk][@pos] = ""
234
+ end
235
+ end
236
+ when 'C-K' # Kill/delete that entry in the history
237
+ @history_copy.delete_at(@stk)
238
+ @history.delete_at(@stk)
239
+ @stk -= 1
240
+ @pos = @history_copy[@stk].length
241
+ when 'LDEL' # Delete readline (Ctrl-U)
242
+ @history_copy[@stk] = ""
243
+ @pos = 0
244
+ when 'TAB' # Tab completion of dirs and files
245
+ @tabstr = @history_copy[@stk][0...@pos]
246
+ @tabend = @history_copy[@stk][@pos..]
247
+ elements = @tabstr.split(" ")
248
+ elements.append("") if @tabstr.match(" $")
249
+ i = elements.length - 1
250
+ m = elements[i].to_s
251
+ if m == "-"
252
+ until i == 0
253
+ i -= 1
254
+ if elements[i] !~ /^-/
255
+ @tabstr.chop!
256
+ tab_switch(elements[i])
257
+ break
258
+ end
259
+ end
260
+ else
261
+ tab_all(m)
262
+ end
263
+ @history_copy[@stk] = @tabstr + @tabend
264
+ when /^.$/
265
+ @history_copy[@stk].insert(@pos,chr)
266
+ @pos += 1
267
+ end
268
+ end
269
+ @history.insert(0, @history_copy[@stk])
270
+ @history[0]
271
+ end
272
+ def tab_switch(str) # TAB completion for command switches (TAB after "-")
273
+ hlp = `#{str} --help`
274
+ hlp = hlp.split("\n").grep(/^\s*-{1,2}[^-]/)
275
+ hlp = hlp.map {|h| h.sub(/^\s*/, '')}
276
+ switch, tab = tabselect(hlp)
277
+ switch = switch.sub(/ .*/, '').sub(/,/, '')
278
+ @tabstr += switch
279
+ @pos = @tabstr.length
280
+ end
281
+ def tab_all(str) # TAB completion for Dirs/files, nicks and commands
282
+ exe = []
283
+ @path.each do |p|
284
+ Dir.glob(p).each do |c|
285
+ exe.append(File.basename(c)) if File.executable?(c) and not Dir.exist?(c)
286
+ end
287
+ end
288
+ exe.prepend(*@nick.keys)
289
+ exe.prepend(*@gnick.keys)
290
+ compl = exe.select {|s| s =~ Regexp.new("^" + str)}
291
+ fdir = File.expand_path(str)
292
+ fdir += "/" if Dir.exist?(fdir)
293
+ fdir += "*"
294
+ compl.prepend(*Dir.glob(fdir))
295
+ @tabstr = @tabstr.sub(/#{str}$/, '') unless compl.empty?
296
+ match, tab = tabselect(compl) unless compl.empty?
297
+ @tabstr += match if match
298
+ @tabstr += str if match == ""
299
+ @pos = @tabstr.length if match
300
+ end
301
+ def nextline # Handle going to the next line in the terminal
302
+ row, col = @c.pos
303
+ if row == @maxrow
304
+ @c.scroll_down
305
+ @c_row -= 1
306
+ end
307
+ @c.next_line
308
+ end
309
+ def tabselect(ary) # Let user select from the incoming array
310
+ @c_row, @c_col = @c.pos
311
+ chr = ""
312
+ tab = false
313
+ i = 0
314
+ ary.length < 5 ? l = ary.length : l = 5
315
+ while chr != "ENTER"
316
+ @c.clear_screen_down
317
+ l.times do |x|
318
+ if x == 0
319
+ @c.clear_line
320
+ print "#{@prompt}#{@tabstr}#{ary[i].sub(/(.*?)[ ,].*/, '\1')}#{@tabend}"
321
+ nextline
322
+ print " #{ary[i]}".c(@c_tabselect)
323
+ else
324
+ print " #{ary[x+i]}".c(@c_taboption)
325
+ end
326
+ nextline
327
+ end
328
+ @c.row(@c_row)
329
+ @c.col(@c_col)
330
+ chr = getchr
331
+ case chr
332
+ when 'C-G', 'C-C'
333
+ @c.clear_screen_down
334
+ return ""
335
+ when 'DOWN'
336
+ i += 1 unless i > ary.length - 2
337
+ when 'UP'
338
+ i -= 1 unless i == 0
339
+ when'TAB'
340
+ chr = "ENTER"
341
+ tab = true
342
+ end
343
+ end
344
+ @c.clear_screen_down
345
+ @c.row(@c_row)
346
+ @c.col(@c_col)
347
+ return ary[i], tab
348
+ end
349
+ def hist_clean # Clean up @history
350
+ @history.uniq!
351
+ @history.compact!
352
+ @history.delete("")
353
+ end
354
+ def cmd_check(str) # Check if each element on the readline matches commands, nicks, paths; color them
355
+ str.gsub(/\S+/) do |el|
356
+ if @nick.include?(el)
357
+ el.c(@c_nick)
358
+ elsif @gnick.include?(el)
359
+ el.c(@c_gnick)
360
+ elsif File.exists?(el.sub(/^~/, "/home/#{@user}"))
361
+ el.c(@c_path)
362
+ elsif system("which '#{el}' >/dev/null")
363
+ el.c(@c_cmd)
364
+ else
365
+ el
366
+ end
367
+ end
368
+ end
369
+ def rshrc # Write updates to .rshrc
370
+ hist_clean
371
+ if File.exist?(Dir.home+'/.rshrc')
372
+ conf = File.read(Dir.home+'/.rshrc')
373
+ else
374
+ conf = ""
375
+ end
376
+ conf.sub!(/^@nick.*\n/, "")
377
+ conf += "@nick = #{@nick}\n"
378
+ conf.sub!(/^@gnick.*\n/, "")
379
+ conf += "@gnick = #{@gnick}\n"
380
+ conf.sub!(/^@history.*\n/, "")
381
+ conf += "@history = #{@history.last(@histsize)}\n"
382
+ File.write(Dir.home+'/.rshrc', conf)
383
+ puts "\n .rshrc updated"
384
+ end
385
+ # RSH FUNCTIONS
386
+ def history # Show history
387
+ puts "History:"
388
+ puts @history
389
+ end
390
+ def rmhistory # Delete history
391
+ @history = []
392
+ puts "History deleted."
393
+ end
394
+ def nick(nick_str) # Define a new nick like this: `:nick "ls = ls --color"`
395
+ if nick_str.match(/^\s*-/)
396
+ source = nick_str.sub(/^\s*-/, '')
397
+ @nick.delete(source)
398
+ else
399
+ source = nick_str.sub(/ =.*/, '')
400
+ target = nick_str.sub(/.*= /, '')
401
+ @nick[source] = target
402
+ end
403
+ rshrc
404
+ end
405
+ def gnick(nick_str) # Define a generic/global nick to match not only commands (format like nick)
406
+ if nick_str.match(/^\s*-/)
407
+ source = nick_str.sub(/^\s*-/, '')
408
+ @gnick.delete(source)
409
+ else
410
+ source = nick_str.sub(/ =.*/, '')
411
+ target = nick_str.sub(/.*= /, '')
412
+ @gnick[source] = target
413
+ end
414
+ rshrc
415
+ end
416
+ def nick? # Show nicks
417
+ puts " Command nicks:".c(@c_nick)
418
+ @nick.each {|key, value| puts " #{key} = #{value}"}
419
+ puts " General nicks:".c(@c_gnick)
420
+ @gnick.each {|key, value| puts " #{key} = #{value}"}
421
+ end
422
+
423
+ # INITIAL SETUP
424
+ begin # Load .rshrc and populate @history
425
+ trap "SIGINT" do print "\n"; exit end
426
+ load(Dir.home+'/.rshrc') if File.exist?(Dir.home+'/.rshrc') # Initial loading - to get history
427
+ @c = Cursor # Initiate @c as Cursor
428
+ @c.save # Get max row & col
429
+ @c.row(8000)
430
+ @c.col(8000)
431
+ @maxrow, @maxcol = @c.pos
432
+ @c.restore # Max row & col gotten, cursor restored
433
+ hist_clean # Remove duplicates, etc
434
+ @path.map! {|p| p + "/*"} # Set proper format for path search
435
+ end
436
+
437
+ # MAIN PART
438
+ loop do
439
+ h = @history; load(Dir.home+'/.rshrc') if File.exist?(Dir.home+'/.rshrc'); @history = h # reload prompt but not history
440
+ @prompt.gsub!(/#{Dir.home}/, '~') # Simplify path in prompt
441
+ @cmd = getstr # Main work is here
442
+ hist_clean # Clean up the history
443
+ @cmd = "ls" if @cmd == "" # Default to ls when no command is given
444
+ print "\n" # Newline
445
+ if @cmd == "x" then rshrc; break; end # A simple way to exit rsh
446
+ if @cmd == "r" # Integration with rtfm (https://github.com/isene/RTFM)
447
+ File.write("/tmp/.rshpwd", Dir.pwd)
448
+ system("rtfm /tmp/.rshpwd")
449
+ Dir.chdir(File.read("/tmp/.rshpwd"))
450
+ next
451
+ end
452
+ begin # Execute command
453
+ if @cmd.match(/^\s*:/) # Ruby commands are prefixed with ":"
454
+ eval(@cmd[1..-1])
455
+ else
456
+ begin # Try cd to cmd
457
+ @cmd.sub!(/^cd (\S*).*/, '\1')
458
+ @cmd = Dir.home if @cmd == "~"
459
+ Dir.chdir(@cmd.strip.sub(/~/, Dir.home))
460
+ rescue # If cd fails, execute cmd (unless no such cmd)
461
+ ca = @nick.transform_keys {|k| /((^\K\s*\K)|(\|\K\s*\K))\b(?<!-)#{Regexp.escape k}\b/}
462
+ @cmd = @cmd.gsub(Regexp.union(ca.keys), @nick)
463
+ ga = @gnick.transform_keys {|k| /\b#{Regexp.escape k}\b/}
464
+ @cmd = @cmd.gsub(Regexp.union(ga.keys), @gnick)
465
+ puts "#{Time.now.strftime("%H:%M:%S")}: #{@cmd}".c(244)
466
+ begin
467
+ if @cmd == "fzf" # fzf integration (https://github.com/junegunn/fzf)
468
+ res = `#{@cmd}`.chomp
469
+ Dir.chdir(File.dirname(res))
470
+ elsif system(@cmd) # Try execute the command
471
+ else
472
+ puts "No such command: #{@cmd}"
473
+ end
474
+ rescue
475
+ if File.exist?(@cmd) # Try to open file with user's editor
476
+ system("#{ENV['EDITOR']} #{@cmd}")
477
+ end
478
+ end
479
+ end
480
+ end
481
+ rescue StandardError => err # Throw error nicely
482
+ puts "#{err}"
483
+ end
484
+ end
485
+
486
+ # vim: set sw=2 sts=2 et fdm=syntax fdn=2 fcs=fold\:\ :
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-shell
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Geir Isene
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-05-23 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A shell written in Ruby with extensive tab completions, aliases/nicks,
14
+ history, syntax highlighting and theming.
15
+ email: g@isene.com
16
+ executables:
17
+ - rsh
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - ".rshrc"
22
+ - README.md
23
+ - bin/rsh
24
+ homepage: https://isene.com/
25
+ licenses:
26
+ - Unlicense
27
+ metadata:
28
+ source_code_uri: https://github.com/isene/rsh
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubygems_version: 3.3.5
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: rsh - Ruby SHell
48
+ test_files: []