mini_readline 0.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 (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +207 -0
  6. data/Rakefile +40 -0
  7. data/lib/mini_readline.rb +28 -0
  8. data/lib/mini_readline/options.rb +19 -0
  9. data/lib/mini_readline/raw_term.rb +14 -0
  10. data/lib/mini_readline/raw_term/other.rb +67 -0
  11. data/lib/mini_readline/raw_term/other/map.rb +75 -0
  12. data/lib/mini_readline/raw_term/other/set_posn.rb +22 -0
  13. data/lib/mini_readline/raw_term/windows.rb +88 -0
  14. data/lib/mini_readline/raw_term/windows/map.rb +71 -0
  15. data/lib/mini_readline/raw_term/windows/set_posn.rb +40 -0
  16. data/lib/mini_readline/raw_term/windows/win_32_api.rb +47 -0
  17. data/lib/mini_readline/read_line.rb +65 -0
  18. data/lib/mini_readline/read_line/edit.rb +87 -0
  19. data/lib/mini_readline/read_line/edit/cancel.rb +15 -0
  20. data/lib/mini_readline/read_line/edit/delete_left.rb +21 -0
  21. data/lib/mini_readline/read_line/edit/delete_right.rb +19 -0
  22. data/lib/mini_readline/read_line/edit/enter.rb +14 -0
  23. data/lib/mini_readline/read_line/edit/go_end.rb +14 -0
  24. data/lib/mini_readline/read_line/edit/go_home.rb +14 -0
  25. data/lib/mini_readline/read_line/edit/go_left.rb +18 -0
  26. data/lib/mini_readline/read_line/edit/go_right.rb +18 -0
  27. data/lib/mini_readline/read_line/edit/insert_text.rb +18 -0
  28. data/lib/mini_readline/read_line/edit/next_history.rb +19 -0
  29. data/lib/mini_readline/read_line/edit/previous_history.rb +19 -0
  30. data/lib/mini_readline/read_line/edit/unmapped.rb +18 -0
  31. data/lib/mini_readline/read_line/edit_window.rb +72 -0
  32. data/lib/mini_readline/read_line/edit_window/sync_cursor.rb +15 -0
  33. data/lib/mini_readline/read_line/edit_window/sync_window.rb +46 -0
  34. data/lib/mini_readline/read_line/history.rb +61 -0
  35. data/lib/mini_readline/version.rb +4 -0
  36. data/mini_readline.gemspec +26 -0
  37. data/reek.txt +1 -0
  38. data/sire.rb +102 -0
  39. data/tests/mini_readline_tests.rb +55 -0
  40. metadata +110 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7f2544e80871d4cdeb122d167832d6e09c74fbb3
4
+ data.tar.gz: e072a14bf924b8f046355c499655230b220f9a3f
5
+ SHA512:
6
+ metadata.gz: c8d40fe8058e368fa90d7aeb1216706fbac6de549f888fe0e91acfd59801a6d6de831c66f895f7ec6894af2fd9559174dcf457f2a0c06c8b565047c0df148aa6
7
+ data.tar.gz: 1b28d4f253743d843f3697c1116008d76dc9c9c9ba7081a36ccf893012399ce83fae0cea41b0ae8c93996a93afb75559da6d2b0ba330c5a30a39f3d295ce56d1
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ *.bat
2
+ *.zip
3
+ *.tmp
4
+ *.gem
5
+ *.rbc
6
+ /.bundle/
7
+ /.yardoc
8
+ /Gemfile.lock
9
+ /_yardoc/
10
+ /coverage/
11
+ docs/.~lock.*
12
+ /rdoc/
13
+ /pkg/
14
+ /tmp/
15
+ temp.txt
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mini_readline.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Peter Camilleri
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,207 @@
1
+ # MiniReadline
2
+
3
+ This gem is used to get console style input from the user, with support for
4
+ inline editing and command history.
5
+
6
+ The mini readline gem is an experiment in replacing the standard readline gem
7
+ that is part of Ruby. The reasons for doing this are somewhat shaky, but here
8
+ is a list of what is hoped to be accomplished here.
9
+
10
+ * The standard readline gem works poorly under Windows.
11
+ <br>- The keypad arrow keys do not work.
12
+ <br>- If the program attempts to send data to a subprocess, it breaks.
13
+ * The code is so convoluted that it is difficult to fix or re-factor.
14
+ * The code is just plain UGLY! With all we've learned about object oriented
15
+ design, there just HAD to be a better way!
16
+ * Finally, since this code will borrow a lot from the original, it is hoped
17
+ that I will see the same bugs and fix them. Then perhaps it can be seen how
18
+ the original code can also be fixed. In the long run, this is perhaps the
19
+ most important goal.
20
+
21
+ ## Installation
22
+
23
+ Add this line to your application's Gemfile:
24
+
25
+ ```ruby
26
+ gem 'mini_readline'
27
+ ```
28
+
29
+ And then execute:
30
+
31
+ $ bundle
32
+
33
+ Or install it yourself as:
34
+
35
+ $ gem install mini_readline
36
+
37
+ ## Usage
38
+
39
+ The typical way of utilizing this gem is to place the following:
40
+
41
+ ```ruby
42
+ require 'mini_readline'
43
+ ```
44
+
45
+ <br>By default, the constant Readline is set to the MiniReadline module. If this
46
+ is not desired use the following:
47
+
48
+ ```ruby
49
+ $no_alias_read_line_module = true
50
+ require 'mini_readline'
51
+ ```
52
+
53
+ ### Compatible Mode
54
+
55
+ In this mode, mini_readline is somewhat compatible with the classic readline.
56
+ Simply use:
57
+
58
+ ```ruby
59
+ Readline.readline('>', true)
60
+ ```
61
+ or to avoid tracking command history, use:
62
+
63
+ ```ruby
64
+ Readline.readline('>', false)
65
+ ```
66
+ Where the string argument is the prompt seen by the user and the flag controls
67
+ the history buffer. This assumes that the $no_alias_read_line_module setting
68
+ mentioned above was *not* used. If it was, then these somewhat less compatible
69
+ forms are required:
70
+ ```ruby
71
+ MiniReadline.readline('>', true)
72
+ ```
73
+ and
74
+ ```ruby
75
+ MiniReadline.readline('>', false)
76
+ ```
77
+
78
+
79
+ ### Native Mode
80
+
81
+ In native mode, instances of the Readline class are used to get user input.
82
+
83
+ ```ruby
84
+ edit = MiniReadline::Readline.new()
85
+ ```
86
+
87
+ The constructor takes a single optional argument which is either:
88
+ * An array of strings; A history buffer pre-loaded with commands.
89
+ * An empty array; A history buffer with no pre-load.
90
+ * The value **false**, to disable the history buffer.
91
+
92
+ <br>Once an instance is created it may be used as follows:
93
+
94
+ ```ruby
95
+ edit.readline(prompt, options)
96
+ ```
97
+ Where prompt is a prompt string and options is a hash of options settings.
98
+ More on options below. In addition, it is possible to get a hold of the
99
+ history buffer of the edit object with:
100
+ ```ruby
101
+ hist = edit.history
102
+ ```
103
+ This method answers an array of strings. Entries added to this array are
104
+ available to the edit instance. For example, the following makes a rather
105
+ menacing part of the history buffer.
106
+ ```ruby
107
+ hist << "launch --weapons:nuclear --all"
108
+ ```
109
+
110
+ ### Options
111
+ In mini_readline, options exist at two levels:
112
+ * The MiniReadline module hash BASE_OPTIONS. These options are shared by
113
+ all instances of the Readline class.
114
+ * The options hash argument of the Readline class's readline instance method.
115
+
116
+ <br>The available options are described below:
117
+ ```ruby
118
+ BASE_OPTIONS = {
119
+ :window_width => 79, #The width of the edit area.
120
+ :scroll_step => 12, #The amount scrolled.
121
+ :alt_prompt => "<< ", #The prompt when scrolled.
122
+ #Set to nil for no alt prompt.
123
+
124
+ :no_blanks => true, #No empty lines in history.
125
+ :no_dups => true, #No duplicate lines in history.
126
+
127
+ :term => nil, #Filled in by raw_term.rb
128
+
129
+ :debug => false} #Used during development.
130
+ ```
131
+
132
+ <br>The options in effect on any given call of the readline method are the
133
+ module base options plus any options passed in as an argument. The passed in
134
+ options override the base options for the duration of that method call.
135
+
136
+ #### Notes
137
+ * Since the compatibility mode does not accept an options hash, the only way to
138
+ affect options in this case is to modify the MiniReadline::BASE_OPTIONS hash.
139
+ * The :term option is the low level console io object used to get data
140
+ from the user and control what is displayed. This gem automatically adapts to
141
+ the environment and plugs in the needed object. This can be overridden where
142
+ special io needs exist.
143
+
144
+ ## Demo
145
+ A simple demo of mini_readline in action is available. To access this demo use
146
+ the following from the mini_readline root folder:
147
+
148
+ $ ruby sire.rb
149
+
150
+ This will launch SIRE, a Simple Interactive Ruby Environment, a sort of
151
+ simple minded irb knock-off. This starts off by requiring the mini
152
+ readline gem from either the system gem library or the local lib folder or
153
+ if all fails, it will load the "classic" Readline gem. Here is a typical run:
154
+
155
+ C:\Sites\mini_readline>ruby sire.rb
156
+
157
+
158
+ Loaded mini_readline from the local code folder.
159
+
160
+ Welcome to a Simple Interactive Ruby Environment
161
+ Use the command 'q' to quit.
162
+
163
+ SIRE>
164
+ Of note, the run method can be used to test for the shell process bug. For
165
+ example:
166
+
167
+ SIRE>(run 'ls').split("\n")
168
+ ["Gemfile",
169
+ "LICENSE.txt",
170
+ "README.md",
171
+ "Rakefile",
172
+ "bin",
173
+ "lib",
174
+ "mini_readline.gemspec",
175
+ "rdoc",
176
+ "reek.txt",
177
+ "sire.rb",
178
+ "tests"]
179
+ SIRE>
180
+ After this command is run, the program should continue to operate correctly
181
+ and not go bannanas. To test the behavior of the standard readline library, use:
182
+
183
+ $ ruby sire.rb old
184
+
185
+ To test the local copy of mini_readline in the lib folder instead of the
186
+ system gem, use this instead:
187
+
188
+ $ ruby sire.rb local
189
+
190
+ ## Testing
191
+ To date this code has been tested under:
192
+ * Windows 7 with MRI ruby 2.1.6p336 (2015-04-13 revision 50298) [i386-mingw32]
193
+ * Windows 7 + Cygwin with ruby 2.2.3p173 (2015-08-18 revision 51636) [i386-cygwin]
194
+
195
+ <br>More testing is clearly called for.
196
+
197
+ ## Contributing
198
+
199
+ Bug reports and pull requests are welcome on GitHub at
200
+ https://github.com/PeterCamilleri/mini_readline.
201
+
202
+
203
+ ## License
204
+
205
+ The gem is available as open source under the terms of the
206
+ [MIT License](http://opensource.org/licenses/MIT).
207
+
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env rake
2
+ # coding: utf-8
3
+
4
+ require 'rake/testtask'
5
+ require 'rdoc/task'
6
+ require "bundler/gem_tasks"
7
+
8
+ #Generate internal documentation with rdoc.
9
+ RDoc::Task.new do |rdoc|
10
+ rdoc.rdoc_dir = "rdoc"
11
+
12
+ #List out all the files to be documented.
13
+ rdoc.rdoc_files.include("lib/**/*.rb", "license.txt", "README.md")
14
+
15
+ #Make all access levels visible.
16
+ rdoc.options << '--visibility' << 'private'
17
+ #rdoc.options << '--verbose'
18
+ #rdoc.options << '--coverage-report'
19
+
20
+ #Set a title.
21
+ rdoc.options << '--title' << 'Mini Readline Gem'
22
+ end
23
+
24
+ #Run the mini_readline unit test suite.
25
+ Rake::TestTask.new do |t|
26
+ #List out all the test files.
27
+ t.test_files = FileList['tests/**/*.rb']
28
+ t.verbose = false
29
+ end
30
+
31
+ desc "Run a scan for smelly code!"
32
+ task :reek do |t|
33
+ `reek --no-color lib > reek.txt`
34
+ end
35
+
36
+ desc "What version of mine_readline is this?"
37
+ task :vers do |t|
38
+ puts
39
+ puts "mini_readline version = #{MiniReadline::VERSION}"
40
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+
3
+ require_relative "mini_readline/version"
4
+ require_relative "mini_readline/options"
5
+ require_relative "mini_readline/read_line"
6
+ require_relative "mini_readline/raw_term"
7
+
8
+ #The \MiniReadline module. A replacement for the rb_readline gem predicated
9
+ #on the notion/hope that the code shouldn't smell like an abandoned fish
10
+ #processing plant. To this end, it drops the pretext of being compatible
11
+ #with the GNU readline library and instead embraces OOD principles. I hope.
12
+ #* mini_readline.rb - The root file that gathers up all the system's parts.
13
+ module MiniReadline
14
+
15
+ #The instances of Readline with and without history.
16
+ @readers = {true => Readline.new([]), false => Readline.new(nil)}
17
+
18
+ #The (limited) compatibility module function.
19
+ #<br>Endemic Code Smells
20
+ #* :reek:BooleanParameter -- Required for compatibility
21
+ def self.readline(prompt, history = false)
22
+ @readers[history].readline(prompt)
23
+ end
24
+ end
25
+
26
+ unless $no_alias_read_line_module
27
+ Readline = MiniReadline
28
+ end
@@ -0,0 +1,19 @@
1
+ # coding: utf-8
2
+
3
+ #* options.rb - Options selection, control, and access
4
+ module MiniReadline
5
+
6
+ #The base options shared by all instances.
7
+ BASE_OPTIONS = {:window_width => 79, #The width of the edit area.
8
+ :scroll_step => 12, #The amount scrolled.
9
+ :alt_prompt => "<< ", #The prompt when scrolled.
10
+ #Set to nil for no alt prompt.
11
+
12
+ :no_blanks => true, #No empty lines in history.
13
+ :no_dups => true, #No duplicate lines in history.
14
+
15
+ :term => nil, #Filled in by raw_term.rb
16
+
17
+ :debug => false #Used during development.
18
+ }
19
+ end
@@ -0,0 +1,14 @@
1
+ # coding: utf-8
2
+
3
+ #Select the type of platform in use.
4
+ if (RUBY_PLATFORM =~ /\bcygwin\b/i) || (RUBY_PLATFORM !~ /mswin|mingw/)
5
+ require_relative 'raw_term/other'
6
+ else
7
+ require_relative 'raw_term/windows'
8
+ end
9
+
10
+ #* raw_term.rb - Platform determination for raw terminal access.
11
+ module MiniReadline
12
+ #Get an instance of a raw terminal controller object.
13
+ BASE_OPTIONS[:term] = RawTerm.new
14
+ end
@@ -0,0 +1,67 @@
1
+ # coding: utf-8
2
+
3
+ require 'io/console'
4
+ require_relative 'other/map'
5
+ require_relative 'other/set_posn'
6
+
7
+ #* raw_term/other.rb - Support for raw terminal access in non-windows systems.
8
+ module MiniReadline
9
+
10
+ #The detected platform is not windows.
11
+ PLATFORM = :other
12
+
13
+ #The class used to manipulate console i/o on a low level.
14
+ class RawTerm
15
+
16
+ #Carriage return
17
+ CARRIAGE_RETURN = "\x0D"
18
+
19
+ #Bell
20
+ BELL = "\x07"
21
+
22
+ #Set up the Other Raw Terminal.
23
+ def initialize
24
+ end
25
+
26
+ #Output a string
27
+ def put_string(str)
28
+ scan_string(str)
29
+ print(str)
30
+ end
31
+
32
+ #Home the cursor and start at a known state.
33
+ def initialize_parms
34
+ put_string CARRIAGE_RETURN
35
+ end
36
+
37
+ #Start on a new line.
38
+ def put_new_line
39
+ print("\n")
40
+ end
41
+
42
+ #Sound a beep
43
+ def beep
44
+ print BELL
45
+ end
46
+
47
+ #Get a uncooked character keystroke.
48
+ #<br>Notes
49
+ #* This needs to be tested under Linux, Cygwin, and Apple.
50
+ #<br>Endemic Code Smells
51
+ #* :reek:UtilityFunction -- For now, the way things are.
52
+ def get_raw_char
53
+ STDIN.getch
54
+ end
55
+
56
+ #Determine the affect of a string on the cursor.
57
+ def scan_string(str)
58
+ str.chars.each do |char|
59
+ if char == CARRIAGE_RETURN
60
+ @cursor_posn = 0
61
+ else
62
+ @cursor_posn += 1
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,75 @@
1
+ # coding: utf-8
2
+
3
+ #* other/map.rb - Character mapping for other systems.
4
+ module MiniReadline
5
+
6
+ #* other/map.rb - Character mapping for other systems.
7
+ class RawTerm
8
+
9
+ #Create a hash with a default value.
10
+ MAP = Hash.new {|_hash, key| [:unmapped, key]}
11
+
12
+ #Map the printable characters.
13
+ (32..126).each do |code|
14
+ char = code.chr
15
+ MAP[char] = [:insert_text, char]
16
+ end
17
+
18
+ #Map the non-terminal entries.
19
+ MAP["\e"] = false
20
+ MAP["\e["] = false
21
+ MAP["\eO"] = false
22
+
23
+ #Map the non-printing characters.
24
+
25
+ #Left Arrows
26
+ MAP["\e[D"] = [:go_left]
27
+ MAP["\e[D"] = [:go_left]
28
+
29
+ #Right Arrows
30
+ MAP["\e[C"] = [:go_right]
31
+ MAP["\eOC"] = [:go_right]
32
+
33
+ #Up Arrows
34
+ MAP["\e[A"] = [:previous_history]
35
+ MAP["\eOA"] = [:previous_history]
36
+
37
+ #Down Arrows
38
+ MAP["\e[B"] = [:next_history]
39
+ MAP["\eOB"] = [:next_history]
40
+
41
+ #The Home keys
42
+ MAP["\e[H"] = [:go_home]
43
+ MAP["\eOH"] = [:go_home]
44
+
45
+ #The End keys
46
+ MAP["\e[F"] = [:go_end]
47
+ MAP["\eOF"] = [:go_end]
48
+
49
+ #The Backspace key
50
+ MAP["\x7F"] = [:delete_left]
51
+
52
+ #The Delete keys
53
+ MAP["\x1F"] = [:delete_right]
54
+ MAP["\e[3"] = false
55
+ MAP["\e[3~"] = [:delete_right]
56
+
57
+ #The Enter key
58
+ MAP["\x0D"] = [:enter]
59
+
60
+ #The Cancel key
61
+ MAP["\x02"] = [:cancel]
62
+
63
+ #Get a mapped sequence.
64
+ def get_mapped_keystroke
65
+ key_seq, key_cmd = "", nil
66
+
67
+ begin
68
+ key_seq << get_raw_char
69
+ key_cmd = MAP[key_seq]
70
+ end until key_cmd
71
+
72
+ key_cmd
73
+ end
74
+ end
75
+ end