ruby-shell 0.1

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