mysh 0.2.7 → 0.3.0
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.
- checksums.yaml +4 -4
- data/README.md +407 -87
- data/lib/mysh.rb +14 -4
- data/lib/mysh/expression.rb +10 -7
- data/lib/mysh/external_ruby.rb +1 -1
- data/lib/mysh/handlebars.rb +29 -0
- data/lib/mysh/handlebars/string.rb +22 -0
- data/lib/mysh/internal/action.rb +5 -5
- data/lib/mysh/internal/action_pool.rb +1 -1
- data/lib/mysh/internal/actions/cd.rb +2 -1
- data/lib/mysh/internal/actions/help/hbar.txt +13 -12
- data/lib/mysh/internal/actions/help/history.txt +1 -1
- data/lib/mysh/internal/actions/help/kbd.txt +1 -0
- data/lib/mysh/internal/actions/help/sub_help.rb +4 -3
- data/lib/mysh/internal/actions/help/vars.txt +34 -0
- data/lib/mysh/internal/actions/pwd.rb +1 -1
- data/lib/mysh/internal/actions/show/env.rb +3 -1
- data/lib/mysh/internal/actions/show/ruby.rb +1 -1
- data/lib/mysh/internal/actions/type.rb +1 -1
- data/lib/mysh/internal/actions/vars.rb +58 -0
- data/lib/mysh/internal/decorate.rb +13 -28
- data/lib/mysh/pre_processor.rb +11 -0
- data/lib/mysh/quick.rb +1 -0
- data/lib/mysh/shell_variables.rb +29 -0
- data/lib/mysh/shell_variables/evaluate.rb +23 -0
- data/lib/mysh/shell_variables/globalize.rb +9 -0
- data/lib/mysh/shell_variables/shell_variable_keeper.rb +36 -0
- data/lib/mysh/shell_variables/shell_variable_store.rb +76 -0
- data/lib/mysh/user_input.rb +10 -7
- data/lib/mysh/version.rb +1 -1
- data/mysh.gemspec +1 -1
- data/samples/show.txt +1 -1
- data/tests/my_shell_tests.rb +78 -5
- metadata +14 -5
- data/lib/mysh/user_input/handlebars.rb +0 -46
data/lib/mysh.rb
CHANGED
@@ -10,6 +10,9 @@ require_relative 'mysh/quick'
|
|
10
10
|
require_relative 'mysh/expression'
|
11
11
|
require_relative 'mysh/internal'
|
12
12
|
require_relative 'mysh/external_ruby'
|
13
|
+
require_relative 'mysh/handlebars'
|
14
|
+
require_relative 'mysh/shell_variables'
|
15
|
+
require_relative 'mysh/pre_processor'
|
13
16
|
require_relative 'mysh/version'
|
14
17
|
|
15
18
|
#The Mysh (MY SHell) module. A container for mysh and its functionality.
|
@@ -20,7 +23,7 @@ module Mysh
|
|
20
23
|
setup
|
21
24
|
|
22
25
|
while @mysh_running do
|
23
|
-
execute_a_command(
|
26
|
+
execute_a_command(get_command)
|
24
27
|
end
|
25
28
|
end
|
26
29
|
|
@@ -31,7 +34,7 @@ module Mysh
|
|
31
34
|
@mysh_running = true
|
32
35
|
end
|
33
36
|
|
34
|
-
#Execute a single line of input.
|
37
|
+
#Execute a single line of input and handle exceptions.
|
35
38
|
def self.execute_a_command(str)
|
36
39
|
try_execute_command(str)
|
37
40
|
|
@@ -39,11 +42,18 @@ module Mysh
|
|
39
42
|
@mysh_running = false
|
40
43
|
|
41
44
|
rescue Interrupt, StandardError, ScriptError => err
|
42
|
-
puts err
|
45
|
+
puts "Error #{err.class}: #{err}"
|
46
|
+
puts err.backtrace if MNV[:debug]
|
43
47
|
end
|
44
48
|
|
45
|
-
#Try to execute a single line of input.
|
49
|
+
#Try to execute a single line of input. Does not handle exceptions.
|
46
50
|
def self.try_execute_command(input)
|
51
|
+
unless input.start_with?("$")
|
52
|
+
input = input.preprocess
|
53
|
+
end
|
54
|
+
|
55
|
+
puts "=> #{input}" if MNV[:debug]
|
56
|
+
|
47
57
|
try_execute_quick_command(input) ||
|
48
58
|
try_execute_internal_command(input) ||
|
49
59
|
try_execute_external_ruby(input) ||
|
data/lib/mysh/expression.rb
CHANGED
@@ -2,12 +2,11 @@
|
|
2
2
|
|
3
3
|
require 'pp'
|
4
4
|
require 'mathn'
|
5
|
-
|
6
5
|
require_relative 'expression/lineage'
|
7
6
|
|
8
7
|
#* mysh/expression.rb -- The mysh ruby expression processor.
|
9
8
|
#<br>Endemic Code Smells
|
10
|
-
#* :reek:ModuleInitialize
|
9
|
+
#* :reek:ModuleInitialize -- False positive
|
11
10
|
module Mysh
|
12
11
|
|
13
12
|
#Reset the state of the execution hosting environment.
|
@@ -29,13 +28,13 @@ module Mysh
|
|
29
28
|
#* The expression string always begins with an '=' character.
|
30
29
|
def execute(expression)
|
31
30
|
pp $mysh_exec_binding.eval("$mysh_exec_result" + expression)
|
32
|
-
|
33
|
-
puts "#{err.class.to_s}: #{err}"
|
34
|
-
ensure
|
35
|
-
return :expression
|
31
|
+
:expression
|
36
32
|
end
|
37
33
|
|
38
|
-
|
34
|
+
#Return a simple message for less convoluted error messages.
|
35
|
+
def inspect
|
36
|
+
"exec_host"
|
37
|
+
end
|
39
38
|
|
40
39
|
#Get the previous result
|
41
40
|
def result
|
@@ -48,6 +47,10 @@ module Mysh
|
|
48
47
|
nil
|
49
48
|
end
|
50
49
|
|
50
|
+
#Evaluate the string in the my shell context.
|
51
|
+
def mysh_eval(str)
|
52
|
+
$mysh_exec_binding.eval(str)
|
53
|
+
end
|
51
54
|
end
|
52
55
|
|
53
56
|
$mysh_exec_host = exec_class.new
|
data/lib/mysh/external_ruby.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require_relative 'handlebars/string'
|
4
|
+
|
5
|
+
#* user_input/handlebars.rb -- Handlebar embedded ruby support.
|
6
|
+
class Object
|
7
|
+
|
8
|
+
#Show a file with embedded ruby handlebars.
|
9
|
+
#<br>Note:
|
10
|
+
#The message receiver is the evaluation host for the handlebar code.
|
11
|
+
def show_handlebar_file(name, evaluator)
|
12
|
+
puts eval_handlebar_file(name, evaluator)
|
13
|
+
rescue Interrupt, StandardError, ScriptError => err
|
14
|
+
puts "Error in file: #{name}\n#{err.class}: #{err}"
|
15
|
+
puts err.backtrace if MNV[:debug]
|
16
|
+
end
|
17
|
+
|
18
|
+
#Expand a file with embedded ruby handlebars.
|
19
|
+
#<br>Note:
|
20
|
+
#The message receiver is the evaluation host for the handlebar code.
|
21
|
+
#<br>Endemic Code Smells
|
22
|
+
#* :reek:UtilityFunction
|
23
|
+
def eval_handlebar_file(name, evaluator)
|
24
|
+
IO.read(name).preprocess(evaluator)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
#Monkey patches for Mysh handlebars
|
4
|
+
class String
|
5
|
+
|
6
|
+
#Evaluate any variable substitutions in the input.
|
7
|
+
def eval_handlebars(evaluator=$mysh_exec_host)
|
8
|
+
gsub(/{{.*?}}/m) do |match|
|
9
|
+
code = match[2...-2]
|
10
|
+
silent = code.end_with?("#")
|
11
|
+
result = evaluator.mysh_eval(code)
|
12
|
+
|
13
|
+
(result unless silent).to_s
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
#Process quoted brace characters
|
18
|
+
def eval_quoted_braces
|
19
|
+
gsub(/\\[\{\}]/) {|found| found[1]}
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/mysh/internal/action.rb
CHANGED
@@ -28,6 +28,11 @@ module Mysh
|
|
28
28
|
[@name].concat(@description)
|
29
29
|
end
|
30
30
|
|
31
|
+
#Evaluate the string in the my shell context.
|
32
|
+
def mysh_eval(str)
|
33
|
+
@exec_binding.eval(str)
|
34
|
+
end
|
35
|
+
|
31
36
|
private
|
32
37
|
|
33
38
|
#Create a binding for mysh to execute expressions in.
|
@@ -35,11 +40,6 @@ module Mysh
|
|
35
40
|
binding
|
36
41
|
end
|
37
42
|
|
38
|
-
#Evaluate the string in the my shell context.
|
39
|
-
def mysh_eval(str)
|
40
|
-
@exec_binding.eval(str)
|
41
|
-
end
|
42
|
-
|
43
43
|
end
|
44
44
|
|
45
45
|
end
|
@@ -1,35 +1,36 @@
|
|
1
1
|
Help: About mysh handlebars:
|
2
2
|
|
3
|
-
In mysh, it is possible to embed snippets of ruby into text files
|
4
|
-
command line through the use of handlebars. Handlebars
|
3
|
+
In mysh, it is possible to embed snippets of ruby into text files, in shell
|
4
|
+
variables or on the command line through the use of handlebars. Handlebars
|
5
|
+
look like this:
|
5
6
|
|
6
7
|
\{\{ code goes here \}\}
|
7
8
|
|
8
9
|
Lets see a simple example of putting the result of a calculation into the
|
9
10
|
command line:
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
mysh>echo \{\{ (1..10).map {|i| i.to_s}.join(" ") \}\} > foo.txt
|
13
|
+
mysh>type foo.txt
|
14
|
+
1 2 3 4 5 6 7 8 9 10
|
14
15
|
|
15
16
|
Handlebars work by evaluating the ruby code within the \{\{ \}\} sequence in
|
16
17
|
the appropriate execution environment. For the command line, this is the same
|
17
18
|
environment used for the '=' quick execution command. For example:
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
mysh>=a="A very long string indeed!"
|
21
|
+
"A very long string indeed!"
|
22
|
+
mysh>echo \{\{ a \}\}
|
23
|
+
A very long string indeed!
|
23
24
|
|
24
25
|
The value returned by expression is coverted to a string (if needed) and then
|
25
26
|
inserted in place of the handlebar expression. There are, however, times when
|
26
27
|
it is not desired to insert anything in the place of the code snippet. For
|
27
28
|
those cases, simply end the expression with a '#' character. For example:
|
28
29
|
|
29
|
-
mysh>echo \{\{ "not embedded" #\}\} \{\{ "embedded" \}\}
|
30
|
-
|
30
|
+
mysh>echo \{\{ "not embedded" #\}\} \{\{ "embedded" \}\}
|
31
|
+
embedded
|
31
32
|
|
32
33
|
Finally, it may be that it is desired to embed braces into a text file or
|
33
|
-
the command line. In that case precede the brace with a
|
34
|
+
the command line. In that case precede the brace with a backslash character
|
34
35
|
like: \\{ or \\}
|
35
36
|
|
@@ -10,7 +10,7 @@ the quick form, ! is used, the space is optional.
|
|
10
10
|
Quick Long Command
|
11
11
|
Form Form Description
|
12
12
|
===== ======= ===========
|
13
|
-
! history Display the history buffer.
|
13
|
+
! history Display the entire history buffer.
|
14
14
|
|
15
15
|
!5 history 5 Retrieve history entry 5 and present this to the user
|
16
16
|
as the next command.
|
@@ -14,7 +14,7 @@ module Mysh
|
|
14
14
|
|
15
15
|
#Execute a help command.
|
16
16
|
def call(_args)
|
17
|
-
show_handlebar_file(ACTIONS_PATH + 'help/' + @file_name)
|
17
|
+
show_handlebar_file(ACTIONS_PATH + 'help/' + @file_name, self)
|
18
18
|
end
|
19
19
|
|
20
20
|
end
|
@@ -22,6 +22,7 @@ module Mysh
|
|
22
22
|
#Add help topics here. Don't sweat the order; they get sorted by name.
|
23
23
|
# Name Description Help File
|
24
24
|
help = [['', 'General help on mysh.', 'help.txt' ],
|
25
|
+
['$', 'Help on mysh variables.', 'vars.txt' ],
|
25
26
|
['show', 'Help on the show command.', 'show.txt' ],
|
26
27
|
['@', 'Help on the show command.', 'show.txt' ],
|
27
28
|
['env', 'Help on the show env command.', 'env.txt' ],
|
@@ -30,8 +31,8 @@ module Mysh
|
|
30
31
|
['=', 'Help on ruby expressions.', 'expr.txt' ],
|
31
32
|
['quick', 'Help on quick commands.', 'quick.txt' ],
|
32
33
|
['gls', 'Help on gls internal mysh command.', 'gls.txt' ],
|
33
|
-
['!', '
|
34
|
-
['history', '
|
34
|
+
['!', 'Help on the history command.', 'history.txt'],
|
35
|
+
['history', 'Help on the history command.', 'history.txt'],
|
35
36
|
['kbd', 'Help on mysh keyboard mapping.', 'kbd.txt' ],
|
36
37
|
['{{', 'Help on mysh handlebars.', 'hbar.txt' ],
|
37
38
|
['help', 'This help on the help command.', 'h_o_h.txt' ],
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Help: mysh variables:
|
2
|
+
|
3
|
+
In mysh, variables are kept that control the behavior of the shell. This simple
|
4
|
+
command is used to set, delete, and display these variables. The basic method
|
5
|
+
for setting a variable is:
|
6
|
+
|
7
|
+
$name=value
|
8
|
+
|
9
|
+
Where:
|
10
|
+
* name is a word matching the regex: /[a-z][a-z0-9_]*/. Lower case only.
|
11
|
+
* value is a string, with embedded variables and handlebars.
|
12
|
+
|
13
|
+
To erase the value of a variable, use: $$name=
|
14
|
+
To display the name/value of a variable, use: $$name
|
15
|
+
To display all variable names/values use: $$
|
16
|
+
|
17
|
+
As an escapement, the string $$$$ maps to a single $$.
|
18
|
+
|
19
|
+
Some variables that are used in mysh are:
|
20
|
+
|
21
|
+
$$d The current date.
|
22
|
+
$$date_fmt The format for the date: "%Y-%m-%d"
|
23
|
+
$$debug Does the shell display additional debugging info (true/false)
|
24
|
+
$$h The home folder's path
|
25
|
+
$$post_prompt The prompt used when a line is continued with a trailing \\
|
26
|
+
character.
|
27
|
+
$$pre_prompt A prompt string displayed before the actual command prompt.
|
28
|
+
Delete the pre_prompt variable to disable pre-prompting.
|
29
|
+
$$prompt The user prompt.
|
30
|
+
$$t The current time.
|
31
|
+
$$time_fmt The format for the time: "%H:%M"
|
32
|
+
$$u The current user.
|
33
|
+
$$w The current working directory's path.
|
34
|
+
|
@@ -16,10 +16,12 @@ module Mysh
|
|
16
16
|
private
|
17
17
|
|
18
18
|
#Get the info
|
19
|
+
#<br>Endemic Code Smells
|
20
|
+
#* :reek:UtilityFunction
|
19
21
|
def info
|
20
22
|
[["user", ENV['USER']],
|
21
23
|
["home", ENV['HOME']],
|
22
|
-
["name",
|
24
|
+
["name", $PROGRAM_NAME.decorate],
|
23
25
|
["shell", ENV['SHELL'] || ENV['ComSpec']],
|
24
26
|
["host", ENV['HOSTNAME'] || ENV['COMPUTERNAME']],
|
25
27
|
["os", ENV['OS']],
|
@@ -19,7 +19,7 @@ module Mysh
|
|
19
19
|
#<br>Endemic Code Smells
|
20
20
|
#* :reek:UtilityFunction
|
21
21
|
def info
|
22
|
-
[["location",
|
22
|
+
[["location", RbConfig.ruby.decorate],
|
23
23
|
["description", RUBY_DESCRIPTION],
|
24
24
|
["version", RUBY_VERSION],
|
25
25
|
["jversion", (JRUBY_VERSION rescue nil)],
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
#* mysh/internal/actions/vars.rb -- The mysh internal variables commands.
|
4
|
+
module Mysh
|
5
|
+
|
6
|
+
#* mysh/internal/actions/vars.rb -- The mysh internal variable commands.
|
7
|
+
class VarsCommand < Action
|
8
|
+
|
9
|
+
#The mysh variable parsing regex.
|
10
|
+
VAR_EXP = %r{(?<name> [a-z][a-z0-9_]*){0}
|
11
|
+
(?<equals> =){0}
|
12
|
+
(?<value> \S.*){0}
|
13
|
+
\$ (\g<name> \s* (\g<equals> \s* \g<value>?)?)?}x
|
14
|
+
|
15
|
+
#Setup an internal action.
|
16
|
+
def initialize(name, description)
|
17
|
+
@name = @equals = @value = nil
|
18
|
+
super(name, description)
|
19
|
+
end
|
20
|
+
|
21
|
+
#Execute a command against the internal mysh variables.
|
22
|
+
def call(str)
|
23
|
+
match = VAR_EXP.match(str.chomp)
|
24
|
+
@name, @equals, @value = match[:name], match[:equals], match[:value]
|
25
|
+
do_command
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
#Do the actual work here.
|
30
|
+
def do_command
|
31
|
+
sym = @name.to_sym if @name
|
32
|
+
|
33
|
+
if @value
|
34
|
+
MNV[sym] = @value
|
35
|
+
elsif @equals
|
36
|
+
MNV[sym] = ""
|
37
|
+
elsif @name
|
38
|
+
puts "#{@name} = #{MNV.get_source(sym)}"
|
39
|
+
else
|
40
|
+
show_all_values
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#Display all variables neatly.
|
45
|
+
def show_all_values
|
46
|
+
puts MNV.keys
|
47
|
+
.sort
|
48
|
+
.map {|sym| ["$" + sym.to_s, MNV.get_source(sym)]}
|
49
|
+
.format_mysh_bullets
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
#The show command action object.
|
55
|
+
desc = 'Set/query mysh variables. See ?$ for more.'
|
56
|
+
VARS_COMMAND = VarsCommand.new('$<name>=value', desc)
|
57
|
+
COMMANDS.add_action(VARS_COMMAND)
|
58
|
+
end
|
@@ -1,37 +1,22 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
3
|
#* mysh/internal/decorate.rb -- mysh internal file name beauty treatments.
|
4
|
-
|
4
|
+
class String
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
dress_up_quotes(dress_up_slashes(name))
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
#Dress up slashes and backslashes.
|
17
|
-
def dress_up_slashes(name)
|
18
|
-
backslash? ? name.gsub("/", "\\") : name
|
19
|
-
end
|
20
|
-
|
21
|
-
#Dress up in quotes if needed.
|
22
|
-
#<br>Endemic Code Smells
|
23
|
-
#* :reek:UtilityFunction
|
24
|
-
def dress_up_quotes(name)
|
25
|
-
name[' '] ? "\"#{name}\"" : name
|
26
|
-
end
|
6
|
+
#Make the file name fit the local system.
|
7
|
+
def decorate
|
8
|
+
self.dress_up_slashes
|
9
|
+
.dress_up_quotes
|
10
|
+
end
|
27
11
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
MiniReadline::PLATFORM == :windows
|
33
|
-
end
|
12
|
+
#Dress up slashes and backslashes.
|
13
|
+
def dress_up_slashes
|
14
|
+
MiniReadline::PLATFORM == :windows ? self.gsub("/", "\\") : self
|
15
|
+
end
|
34
16
|
|
17
|
+
#Dress up in quotes if needed.
|
18
|
+
def dress_up_quotes
|
19
|
+
self[' '] ? "\"#{self}\"" : self
|
35
20
|
end
|
36
21
|
|
37
22
|
end
|