mysh 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +95 -28
  3. data/lib/mysh.rb +13 -39
  4. data/lib/mysh/binding_wrapper.rb +21 -0
  5. data/lib/mysh/exceptions.rb +4 -0
  6. data/lib/mysh/expression.rb +11 -4
  7. data/lib/mysh/external_ruby.rb +20 -7
  8. data/lib/mysh/globalize.rb +18 -0
  9. data/lib/mysh/handlebars.rb +0 -3
  10. data/lib/mysh/init.rb +26 -0
  11. data/lib/mysh/internal/action.rb +7 -2
  12. data/lib/mysh/internal/action_pool.rb +9 -4
  13. data/lib/mysh/internal/actions/command_line.rb +56 -0
  14. data/lib/mysh/internal/actions/command_line/debug.rb +39 -0
  15. data/lib/mysh/internal/actions/command_line/init.rb +50 -0
  16. data/lib/mysh/internal/actions/command_line/load.rb +25 -0
  17. data/lib/mysh/internal/actions/command_line/post_prompt.rb +44 -0
  18. data/lib/mysh/internal/actions/command_line/pre_prompt.rb +44 -0
  19. data/lib/mysh/internal/actions/command_line/prompt.rb +42 -0
  20. data/lib/mysh/internal/actions/command_line/quit.rb +19 -0
  21. data/lib/mysh/internal/actions/command_line/usage.rb +23 -0
  22. data/lib/mysh/internal/actions/comment.rb +20 -0
  23. data/lib/mysh/internal/actions/elapsed.rb +27 -0
  24. data/lib/mysh/internal/actions/exit.rb +2 -3
  25. data/lib/mysh/internal/actions/gls.rb +1 -1
  26. data/lib/mysh/internal/actions/help/expr.txt +6 -9
  27. data/lib/mysh/internal/actions/help/quick.txt +6 -0
  28. data/lib/mysh/internal/actions/help/sub_help.rb +1 -0
  29. data/lib/mysh/internal/actions/help/usage.txt +8 -0
  30. data/lib/mysh/internal/actions/help/vars.txt +2 -2
  31. data/lib/mysh/internal/actions/load.rb +42 -0
  32. data/lib/mysh/internal/actions/quit.rb +18 -0
  33. data/lib/mysh/internal/actions/say.rb +20 -0
  34. data/lib/mysh/internal/actions/show/env.rb +13 -11
  35. data/lib/mysh/internal/actions/type.rb +4 -3
  36. data/lib/mysh/internal/actions/vars.rb +5 -5
  37. data/lib/mysh/internal/manage.rb +1 -1
  38. data/lib/mysh/process.rb +52 -0
  39. data/lib/mysh/quick.rb +3 -1
  40. data/lib/mysh/shell_variables.rb +0 -1
  41. data/lib/mysh/sources/console.rb +44 -0
  42. data/lib/mysh/{user_input → sources}/parse.rb +1 -1
  43. data/lib/mysh/{user_input/smart_source.rb → sources/smart_auto_complete.rb} +1 -1
  44. data/lib/mysh/sources/string.rb +33 -0
  45. data/lib/mysh/user_input.rb +14 -30
  46. data/lib/mysh/version.rb +1 -1
  47. data/samples/load.rb +6 -0
  48. data/samples/script.mysh +11 -0
  49. data/samples/sleep.rb +6 -0
  50. data/samples/sleep.txt +2 -0
  51. data/tests/my_shell_tests.rb +6 -4
  52. metadata +30 -5
  53. data/lib/mysh/shell_variables/globalize.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e859f5e9fd3f2d6d4e88de719444088195e2d1e0
4
- data.tar.gz: e2eb0dacb82603274b4511a7b6f72f366230649e
3
+ metadata.gz: 7927b9f18a9a450e85b27f329ef62a9cc4dc212b
4
+ data.tar.gz: d058babe1aadabcb1b63bb5eaa9af689f2674ab5
5
5
  SHA512:
6
- metadata.gz: 09493f5a93d52dbe8812cbf01c7cf3418fb0f2c627935f258b86b4819ee874ce986453eb5a43c98b67da911fc95ee39062dde4795c1d2fe4db86b394702c21cf
7
- data.tar.gz: abde27a389011b5175a46579c5878a4e514a6906d178893df5623f9df4cbbbecf1b496e3acf315ca0bf661d1299c6b89683075863437ad81d458ee84b174c7ef
6
+ metadata.gz: 40c991266f6c8b9185d2c635ba496cd3c6ba593744efa299cd088767f03f3be63400b05fafc1a6db31567e447a7fa21fddc9144476b564b85b0eaea7a6902398
7
+ data.tar.gz: 96f671dec8eaba3798c5bd807c54ae681c588f69c9b530cda545af70e3c9fff8f0f5481018d3d065cefa7ec9ef26ce89be26c0de9702ea94525baba8dd91fa37
data/README.md CHANGED
@@ -47,29 +47,68 @@ The mysh gem includes a simple executable called mysh. The template for running
47
47
  the mysh is:
48
48
 
49
49
  ```
50
- mysh <args>
50
+ mysh <options>
51
51
  ```
52
52
 
53
- Where args are currently a work in progress and not available at this time.
54
-
55
- When mysh is run, the user is presented with a command prompt:
53
+ Where the available options are:
54
+
55
+ Option | Short Form | Description
56
+ ---------------------|-------------|---------------------------
57
+ --debug | -d | Turn on mysh debugging.
58
+ --no-debug | -nd | Turn off mysh debugging.
59
+ --help | -? -h | Display mysh usage info and exit.
60
+ --init filename | -i filename | Initialize mysh by loading the specified file.
61
+ --no-init | -ni | Do not load a file to initialize mysh.
62
+ --load filename | -l filename | Load the specified file into the mysh.
63
+ --post-prompt "str" | -pp "str" | Set the mysh line continuation prompt to "str".
64
+ --no-post-prompt | -npp | Turn off mysh line continuation prompting.
65
+ --pre-prompt "str" | -pr "str" | Set the mysh pre prompt to "str".
66
+ --no-pre-prompt | -npr | Turn off mysh pre prompting.
67
+ --prompt "str" | -p "str" | Set the mysh prompt to "str".
68
+ --no-prompt | -np | Turn off mysh prompting.
69
+ --quit | | Quit out of the mysh program.
70
+
71
+ <br>When mysh is run, the user is presented with a command prompt:
56
72
 
57
73
  ```
58
74
  $ mysh
59
75
  /cygdrive/c/Sites/mysh
60
76
  mysh>
61
-
62
77
  ```
78
+
63
79
  Now the user (that's you) may enter commands that hopefully increase the level
64
80
  of awesome coolness in the known universe. Entropy does not take vacations so
65
81
  hop to it! :-)
66
82
 
83
+ Now that we've launched mysh, what exactly does it do? This can be summarized
84
+ with just two words: Boot and REPL.
85
+
86
+ ###Boot
87
+
88
+ When mysh starts up, it, like most programs must first get itself initialized
89
+ and acclimated to its environment. The boot/initialization process of mysh is
90
+ somewhat modeled after (well if I'm honest, more like inspired by) that of the
91
+ famous bash shell. On startup:
92
+
93
+ 1. Process pre-boot options. Some command line options are processed early.
94
+ These are --help, -h, -?, --init, -i, --no-init, -ni, and --quit. See above
95
+ for details on these.
96
+ 2. Try to load and execute the mysh init file. There are two possible files
97
+ for this role. They are the ~/mysh_init.mysh and ~/mysh_init.rb files. If
98
+ both files should be present, the .mysh file is processed and the .rb is
99
+ ignored. NOTE: If an init file should be specified with the --init (-i)
100
+ option, or disabled with the --no-init (-ni) option, this step is skipped.
101
+ 3. The rest of the command line options are processed at this time. Again,
102
+ see above for details.
103
+
104
+
67
105
  ###REPL
68
106
 
69
- Now for a little more detail. The mysh program is built around a design pattern
70
- called REPL. This stands for Read Eval Print and Loop and is used in may
71
- utilities like irb, pry and the rails console. To better use mysh, it is good
72
- to understand each of these four operating steps.
107
+ Now for a little more detail about what happens after booting up. The mysh
108
+ program is built around a design pattern called REPL. This stands for Read Eval
109
+ Print and Loop and is used in may utilities like irb, pry and the rails
110
+ console. To better use mysh, it is good to understand each of these four
111
+ operating steps.
73
112
 
74
113
  ####READ
75
114
 
@@ -126,8 +165,10 @@ be taken for the input. The four types are:
126
165
  character in the input. These signature characters are:
127
166
  * ! to access the mysh command history buffer. For more information see
128
167
  Command History below.
168
+ * \# a comment. Performs no operation.
129
169
  * $ to access or update mysh variables. For more information see Shell
130
170
  Variables below.
171
+ * % to execute a command and then display the elapsed execution time.
131
172
  * = to evaluate an expression of Ruby code. For more information see Ruby
132
173
  Expressions below.
133
174
  * ? to access the mysh help subsystem. For more information see Shell Help
@@ -137,10 +178,11 @@ character in the input. These signature characters are:
137
178
 
138
179
  2. Internal Commands - These commands are recognized by having the first word
139
180
  in the input match a word stored in an internal hash of command actions. For
140
- more information see Interanl Commands below.
141
- 3. External Ruby Commands - These commands are recognized by having the first
142
- word in the input have the extension (*.rb) of a ruby source file. For more
143
- information see External Ruby Commands below.
181
+ more information see Internal Commands below.
182
+ 3. External mysh files - These commands are recognized by having the first
183
+ word in the input have a recognized extension. That is (*.rb) of a ruby source
184
+ file, (*.mysh) for a mysh script file and (*.txt) for a text file. For more
185
+ information see External Mysh Commands below.
144
186
  4. External Commands - Any command not matching any of the above is sent to the
145
187
  system shell for execution. For more information see External Commands below.
146
188
 
@@ -222,14 +264,11 @@ baz yes
222
264
 
223
265
  The processing of input continues (looping) until it doesn't. This occurs when
224
266
  a command to stop looping is entered or the mini_readline gem signals
225
- end-of-input condition. The commands that do this are:
267
+ end-of-input condition. The (internal) commands that do this are:
226
268
 
227
269
  * exit - exit the current mysh level.
228
270
  * quit - terminate the mysh program.
229
271
 
230
- Work-in-progress - mysh only has one level at this time so these two commands
231
- do exactly the same thing... for now!
232
-
233
272
  An end-of-input condition is signaled by the user by entering Ctrl-z (in
234
273
  windows) or Alt-z (in Linux/Mac). See the mini_readline gem (link above) for
235
274
  more information on the keyboard mappings used by mysh.
@@ -268,7 +307,7 @@ those cases, simply end the expression with a '#' character. For example:
268
307
 
269
308
  Finally, it may be that it is desired to embed braces into a text file or
270
309
  the command line. In that case precede the brace with a backslash character
271
- like: \{ or \}
310
+ like: \\{ or \\}
272
311
 
273
312
  ### Command History
274
313
 
@@ -305,9 +344,7 @@ To display the name/value of a variable, use:
305
344
 
306
345
  $name
307
346
 
308
- To display all variable names/values use:
309
-
310
- $
347
+ To display all variable names/values use just enter a single $ sign.
311
348
 
312
349
  As an escapement, the string $$ maps to a single $.
313
350
 
@@ -319,7 +356,7 @@ $d | The current date.
319
356
  $date_fmt | The format for the date: "%Y-%m-%d"
320
357
  $debug | Does the shell display additional debugging info (true/false)
321
358
  $h | The home folder's path
322
- $post_prompt| The prompt used when a line is continued with a trailing \\ character.
359
+ $post_prompt| The prompt used when a line is continued with a trailing \\ character. By default this is the same as the normal prompt.
323
360
  $pre_prompt | A prompt string displayed before the actual command prompt. Delete the pre_prompt variable to disable pre-prompting.
324
361
  $prompt | The user prompt.
325
362
  $t | The current time.
@@ -434,6 +471,7 @@ math | Help on math functions.
434
471
  quick | Help on quick commands.
435
472
  ruby | Help on the show ruby command.
436
473
  show | Help on the show command.
474
+ usage | Help on mysh usage options.
437
475
  {{ | Help on mysh handlebars.
438
476
 
439
477
 
@@ -500,17 +538,42 @@ Command | Description
500
538
  cd {dir} | Change directory to the optional dir parameter and then display the current working directory.
501
539
  exit | Exit mysh.
502
540
  gls {-l} {mask}| Display the loaded ruby gems. Use optional -l for a more details and a mask to limit output.
503
- history {index}| Display the mysh command history, or if an index is specified, retrieve the command with that index value.
541
+ history {index}| The mysh command history. If an index is specified, get the command with that index value.
542
+ load file | Load a ruby program, mysh script, or text file into the mysh environment.
504
543
  pwd | Display the current working directory.
505
544
  quit | Exit mysh.
506
- type | Display a text file with optional embedded handlebars.
545
+ say <stuff> | Display the text in the command arguments.
546
+ type file | Display a text file with support for optional embedded handlebars and mysh variables.
507
547
  vls {mask} | Display the loaded modules, matching the optional mask, that have version info.
508
548
 
509
- ### External Ruby Commands
549
+ Note that the load command applied to a mysh script file acts exactly the same
550
+ as if the script file were executed directly from the command line. As a
551
+ result of this:
510
552
 
511
- Any command that ends with a ".rb" extension will be sent as the target of the
512
- ruby interpreter. So for example, let's run the test.rb file located in the
513
- samples folder:
553
+ ```
554
+ myfile.mysh
555
+ load myfile.mysh
556
+ ```
557
+ do the same thing. In addition:
558
+ ```
559
+ myfile.txt
560
+ load myfile.txt
561
+ type myfile.txt
562
+ ```
563
+ are also all equivalent. See External Mysh Commands below for more info.
564
+
565
+ ### External Mysh Commands
566
+
567
+ These commands are recognized by having the first word in the input have a
568
+ recognized extension. These are:
569
+
570
+ Extension | Description
571
+ ---------------|----------------------------------------------------
572
+ .rb | A ruby source file executed via a new instance of the compiler.
573
+ .mysh | A mysh script file. Commands in this file are executed as if the user typed them in at the console.
574
+ .txt | A text file. The file (with any embedded code and veriables) is displayed on the console.
575
+
576
+ Here is a sample session with an external Ruby program.
514
577
 
515
578
  ```
516
579
  mysh>$debug = on
@@ -544,6 +607,10 @@ require "mysh"
544
607
  Mysh.run
545
608
  ```
546
609
 
610
+ The run command takes an optional array of command line style options similar
611
+ in nature to the ARGV ruby constant. If omitted, mysh is run with no optional
612
+ parameters. These parameters are documented in the Usage section above.
613
+
547
614
  #### Adding New Commands
548
615
 
549
616
  It is possible to add new internal commands to the mysh CLI. This may done
data/lib/mysh.rb CHANGED
@@ -5,6 +5,8 @@
5
5
  require 'English'
6
6
  require 'in_array'
7
7
 
8
+ require_relative 'mysh/exceptions'
9
+ require_relative 'mysh/binding_wrapper'
8
10
  require_relative 'mysh/user_input'
9
11
  require_relative 'mysh/quick'
10
12
  require_relative 'mysh/expression'
@@ -13,55 +15,27 @@ require_relative 'mysh/external_ruby'
13
15
  require_relative 'mysh/handlebars'
14
16
  require_relative 'mysh/shell_variables'
15
17
  require_relative 'mysh/pre_processor'
18
+ require_relative 'mysh/process'
19
+ require_relative 'mysh/globalize'
20
+ require_relative 'mysh/init'
21
+
16
22
  require_relative 'mysh/version'
17
23
 
18
24
  #The Mysh (MY SHell) module. A container for mysh and its functionality.
19
25
  module Mysh
20
26
 
21
27
  #The actual shell method.
22
- def self.run
23
- setup
24
-
25
- while @mysh_running do
26
- execute_a_command(get_command)
27
- end
28
- end
29
-
30
- #Common initialization tasks.
31
- def self.setup
32
- reset_host
33
- init_input
34
- @mysh_running = true
35
- end
36
-
37
- #Execute a single line of input and handle exceptions.
38
- def self.execute_a_command(str)
39
- try_execute_command(str)
40
-
41
- rescue MiniReadlineEOI
42
- @mysh_running = false
43
-
44
- rescue Interrupt, StandardError, ScriptError => err
45
- puts "Error #{err.class}: #{err}"
46
- puts err.backtrace if MNV[:debug]
47
- end
48
-
49
- #Try to execute a single line of input. Does not handle exceptions.
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]
28
+ def self.run(args=[])
29
+ process_command_args(args, :pre_boot)
30
+ mysh_load_init
31
+ process_command_args(args, :post_boot)
56
32
 
57
- try_execute_quick_command(input) ||
58
- try_execute_internal_command(input) ||
59
- try_execute_external_ruby(input) ||
60
- system(input)
33
+ process_console
61
34
  end
62
35
 
36
+ reset_host
63
37
  end
64
38
 
65
39
  if __FILE__ == $0
66
- Mysh.run #Run a shell if this file is run directly.
40
+ Mysh.run(ARGV) #Run a shell if this file is run directly.
67
41
  end
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+
3
+ #* mysh/internal/binding_wrapper.rb -- An action compatible wrapper for a binding.
4
+ module Mysh
5
+
6
+ #* mysh/internal/binding_wrapper.rb -- An action compatible wrapper for a binding.
7
+ class BindingWrapper
8
+
9
+ #Setup a binding wrapper
10
+ def initialize(binding)
11
+ @exec_binding = binding
12
+ end
13
+
14
+ #Evaluate the string in the wrapped context.
15
+ def mysh_eval(str)
16
+ @exec_binding.eval(str)
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,4 @@
1
+ # coding: utf-8
2
+
3
+ #Exit the current mysh processing loop.
4
+ class MyshExit < Exception; end
@@ -20,7 +20,7 @@ module Mysh
20
20
  #Set up a new execution environment
21
21
  def initialize
22
22
  $mysh_exec_result = nil
23
- $mysh_exec_binding = binding
23
+ $mysh_exec_binding = mysh_binding
24
24
  end
25
25
 
26
26
  #Do the actual work of executing an expression.
@@ -36,6 +36,13 @@ module Mysh
36
36
  "exec_host"
37
37
  end
38
38
 
39
+ #Evaluate the string in the my shell context.
40
+ def mysh_eval(str)
41
+ $mysh_exec_binding.eval(str)
42
+ end
43
+
44
+ private
45
+
39
46
  #Get the previous result
40
47
  def result
41
48
  $mysh_exec_result
@@ -47,9 +54,9 @@ module Mysh
47
54
  nil
48
55
  end
49
56
 
50
- #Evaluate the string in the my shell context.
51
- def mysh_eval(str)
52
- $mysh_exec_binding.eval(str)
57
+ #Create a binding for mysh to execute expressions in.
58
+ def mysh_binding
59
+ binding
53
60
  end
54
61
  end
55
62
 
@@ -4,16 +4,29 @@
4
4
  module Mysh
5
5
 
6
6
  #Try to execute as a Ruby program.
7
+ #<br>Endemic Code Smells
8
+ #* :reek:TooManyStatements
7
9
  def self.try_execute_external_ruby(str)
8
- cmd = str.split[0]
10
+ args = parse_args(str.chomp)
11
+ file_name = args.shift
9
12
 
10
- if cmd && File.extname(cmd) == '.rb'
11
- new_command = "#{RbConfig.ruby} #{str}"
12
- puts "=> #{new_command}" if MNV[:debug]
13
- system(new_command)
14
- :ruby_exec
15
- end
13
+ if (file_name)
14
+ ext = File.extname(file_name)
16
15
 
16
+ if ext == '.rb'
17
+ new_command = "#{RbConfig.ruby} #{str}"
18
+ puts "=> #{new_command}" if MNV[:debug]
19
+ system(new_command)
20
+ :ruby_exec
21
+ elsif ext == '.mysh'
22
+ Mysh.process_file(file_name)
23
+ :mysh_script
24
+ elsif ext == '.txt'
25
+ exec_host = BindingWrapper.new(binding)
26
+ show_handlebar_file(file_name, exec_host)
27
+ :internal
28
+ end
29
+ end
17
30
  end
18
31
 
19
32
  end
@@ -0,0 +1,18 @@
1
+ # coding: utf-8
2
+
3
+ #Monkey patches for mysh global entities.
4
+ class Object
5
+
6
+ #Make the environment variable store accessible everywhere.
7
+ MNV = Mysh::MNV
8
+
9
+ private
10
+
11
+ #The mysh equivalent of the system method.
12
+ #<br>Endemic Code Smells
13
+ #* :reek:UtilityFunction
14
+ def mysh(str)
15
+ Mysh.try_execute_command(str)
16
+ end
17
+
18
+ end
@@ -10,9 +10,6 @@ class Object
10
10
  #The message receiver is the evaluation host for the handlebar code.
11
11
  def show_handlebar_file(name, evaluator)
12
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
13
  end
17
14
 
18
15
  #Expand a file with embedded ruby handlebars.
data/lib/mysh/init.rb ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+
3
+ #* mysh/init.rb -- The mysh init file loader.
4
+ module Mysh
5
+
6
+ #Set the init file used to startup mysh to none so far.
7
+ $mysh_init_file = nil
8
+
9
+ #Perform init phase processing.
10
+ def self.mysh_load_init
11
+
12
+ unless $mysh_init_file || !(home = ENV['HOME'])
13
+ name_mysh = home + '/mysh_init.mysh'
14
+ name_rb = home + '/mysh_init.rb'
15
+
16
+ if File.file?(name_mysh)
17
+ process_file($mysh_init_file = name_mysh)
18
+ elsif File.file?(name_rb)
19
+ load ($mysh_init_file = name_rb)
20
+ end
21
+ end
22
+
23
+ $mysh_init_file = '<none found>' unless $mysh_init_file
24
+ end
25
+
26
+ end