{"id":17942646,"url":"https://github.com/petercamilleri/mini_readline","last_synced_at":"2025-04-03T13:27:42.477Z","repository":{"id":56883853,"uuid":"49334208","full_name":"PeterCamilleri/mini_readline","owner":"PeterCamilleri","description":"A gem for console command entry with line edit, history, and prefill and security options. The goal of this gem is to create a lightweight, portable, pure Ruby alternative to Readline.","archived":false,"fork":false,"pushed_at":"2021-05-19T15:08:08.000Z","size":252,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-24T20:14:17.717Z","etag":null,"topics":["commandline-interface","readline","ruby","rubygem","user-interface"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PeterCamilleri.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-01-09T17:34:41.000Z","updated_at":"2021-05-19T15:08:11.000Z","dependencies_parsed_at":"2022-08-20T13:10:55.635Z","dependency_job_id":null,"html_url":"https://github.com/PeterCamilleri/mini_readline","commit_stats":null,"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeterCamilleri%2Fmini_readline","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeterCamilleri%2Fmini_readline/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeterCamilleri%2Fmini_readline/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeterCamilleri%2Fmini_readline/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PeterCamilleri","download_url":"https://codeload.github.com/PeterCamilleri/mini_readline/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247008824,"owners_count":20868428,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["commandline-interface","readline","ruby","rubygem","user-interface"],"created_at":"2024-10-29T03:06:38.459Z","updated_at":"2025-04-03T13:27:42.451Z","avatar_url":"https://github.com/PeterCamilleri.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MiniReadline\n\nThis gem is used to get console style input from the user, with support for\ninline editing, command history, and stock or customizable auto-complete.\n\nThe mini readline gem is an experiment in replacing the standard readline gem\nthat is part of Ruby. The mini readline project will try to focus on the needs\nof Ruby programs. It will also try to correct a number of irritating issues\nencountered when running cross platform environments. This is achieved through\nthe use of the mini_term gem that deals with the mess of getting proper access\nto the low-level \"terminal\".\n\nWhile the standard readline gem tries its best to be compatible with the GNU\nReadline library written in \"C\", mini_readline does not. Instead it takes on\nthe goal of being best suited to the needs of Ruby programmers. While this\nmakes it much less useful to those porting over Unix/Linux utilities, it makes\nit more useful to Ruby programmers creating CLI utilities in that language.\n\nFurther, while spread out over a much larger number of smaller, manageable\nfiles, mini readline has only 1238 lines of code. In fact, only two files have\nmore than 100 lines in total. The rb-readline gem has a much larger 9480 lines\nof code with 8920 of them in a single, monster file. While the smaller files do\nhave some downsides, bloated files are, in my opinion, worse.\n\nFinally, I know this whole effort must seem to give off a sort of angry birds\nvibe against the original rb-readline gem. That is not my intent at all. I owe\na great debt of gratitude to the authors and maintainers of that vital code.\nTheir getting around the whole Win32API, dl obsolescence debacle saved me so\nmuch time and frustration that words do not suffice. Thanks!\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'mini_readline'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install mini_readline\n\nThe mini_readline gem itself is found at: ( https://rubygems.org/gems/mini_readline )\n\n## Key Mappings\nThe mini_readline gem supports a simple set of editing commands. These vary\nsomewhat based on the system platform. The keyboard mappings (and alias\nmappings) are listed below:\n\nEditor Action    | Windows Key                      | Mac/Linux Key\n-----------------|----------------------------------|------------\nEnter            | Enter                            | Enter\nLeft             | Left Arrow, Pad Left             | Left Arrow, Ctrl-B\nWord Left        | Ctrl Left Arrow, Ctrl Pad Left   | Ctrl Left Arrow, Alt-b\nRight            | Right Arrow, Pad Right           | Right Arrow, Ctrl-F\nWord Right       | Ctrl Right Arrow, Ctrl Pad Right | Ctrl Right Arrow, Alt-f\nGo to start      | Home, Pad Home                   | Home, Ctrl-A\nGo to end        | End, Pad End                     | End, Ctrl-E\nPrevious History | Up Arrow, Pad Up                 | Up Arrow, Ctrl-R\nNext History     | Down Arrow, Pad Down             | Down Arrow\nErase Left       | Backspace, Ctrl-H                | Backspace, Ctrl-H\nErase All Left   |                                  | Ctrl-U\nErase Right      | Delete, Ctrl-Backspace           | Delete, Ctrl-Backspace\nErase All Right  |                                  | Ctrl-K\nErase All        | Escape                           | Ctrl-L\nAuto-complete    | Tab, Ctrl-I                      | Tab, Ctrl-I\nEnd of Input     | Ctrl-Z                           | Alt-z\n\n### Notes\n* The label \"Mac/Linux\" also includes the Cygwin platform.\n* On \"Mac/Linux\" systems lacking an Alt key, these sequences may be\nreplaced by Escape followed by the appropriate letter.\n* References to Pad keys under Windows assume that Num Lock is not engaged.\n* Support for End of Input is controlled by the eoi_detect option. See options\nbelow.\n* These keyboard mappings are the standard ones included with mini_readline.\nSee the section Adding Custom Key Maps below for more info.\n\n## Usage\n\nThe typical way of utilizing this gem is to place the following:\n\n```ruby\nrequire 'mini_readline'\n```\n\n### Demos\n\nThere are a number of demo/test programs available for the mini_readline gem.\nThese are:\n\n    $ irbm\n    Starting an IRB console with mini_readline (0.7.2).\n    irb(main):001:0\u003e\n\nThis runs against the most recently installed gem. Also available in the gem\nroot folder is the irbt test utility.\n\n    $ ruby irbt.rb\n\nwhich again, uses the most recent gem installed in the system.\n\n    $ ruby irbt.rb local\n\nwhich uses the local copy of mini_readline, ignoring the system gems. This can\nalso be accomplished with the command:\n\n    $ rake console\n\n### Compatible Mode\n\nIn compatible mode, mini_readline tries to be somewhat compatible with the\nclassic system readline facility. This means that MiniReadline module methods\nare used to obtain user input. Here is this compatible mode in action with\nentry history enabled:\n\n```ruby\nMiniReadline.readline('\u003e', true)\n```\nand with entry history disabled:\n```ruby\nMiniReadline.readline('\u003e')\n```\nor\n```ruby\nMiniReadline.readline('\u003e', false)\n```\n\nWhere the string argument is the prompt seen by the user and the flag controls\nthe history buffer. Use true to enable history and false to disable it.\n\n##### Extensions\n\nIn addition to the standard readline arguments, additional arguments may be\npassed in to access additional features. This is done with an optional trailing\nhash argument. For example, the following bit of compatibility mode code gets\na string with password hiding:\n```ruby\nMiniReadline.readline(\"\u003e\", false, secret_mask: \"*\")\n```\nSee the section Options below for more information on the sorts of things that\ncan be accomplished with these options settings.\n\n##### Module Aliasing [Support Ended]\n\nIn an attempt to enhance compatibility, the mini_readline gem had the ability\nto alias itself as the readline gem. This feature was found to be unworkable\nand has been removed as of Version 0.7.0.\n\nThis feature was controlled by two global variables:\n\n```ruby\n$force_alias_read_line_module\n$no_alias_read_line_module\n```\nNote: Using these variables now has no effect whatsoever.\n\n### Native Mode\n\nIn native mode, instances of the Readline class are used to get user input.\n\n```ruby\nedit = MiniReadline::Readline.new\n```\n\nThe constructor takes an optional argument. A hash of options that are used\nas instance level options.\n\n\u003cbr\u003eOnce an instance is created it may be used as follows:\n\n```ruby\nuser_entry = edit.readline(options)\n```\nWhere an optional hash of options settings. For example, to specify a\nnon-default prompt with history enabled, use the following:\n\n```ruby\nuser_entry = edit.readline(prompt: '? ', history: true)\n```\n\n\nIn addition, it is possible to get a hold\nof the history buffer of the edit object with:\n```ruby\nhist = edit.history\n```\nThis method answers an array of strings. Entries added to this array are\navailable to the edit instance. For example, the following adds a rather\nmenacing entry to the history buffer.\n```ruby\nedit.history \u003c\u003c \"launch --weapons:nuclear --all\"\n```\nMaybe I should cut back on the Fallout/4?\n\n### Options\nIn mini_readline, options exist at three levels:\n* The MiniReadline module hash BASE_OPTIONS. These options are shared by\nall instances of the Readline class. These options can be modified by\nchanging entries in the MiniReadline::BASE_OPTIONS hash.\n* The instance options associated with each instance of the Readline class.\nThese options may be specified when a Readline instance is created (with new)\nor by getting the instance options with the instance_options property and\nadding/changing entries to/in it.\n* The options hash argument of the Readline class's readline instance method.\n\n\u003cbr\u003eThe options in effect during a read line operation are expressed as:\n\n```ruby\nMiniReadline::BASE_OPTIONS.merge(instance_options).merge(options)\n```\n\u003cbr\u003eThis means that instance_options entries override those in BASE_OPTION and\nreadline parameter option entries override both instance_options and BASE_OPTION\nentries.\n\n\u003cbr\u003eThe available options are described below:\n```ruby\n# The base options shared by all instances.\nBASE_OPTIONS = {\n  :scroll_step   =\u003e 12,       # The amount scrolled.\n\n  :prompt        =\u003e \"\u003e\",      # The default prompt.\n  :alt_prompt    =\u003e \"\u003c\u003c \",    # The prompt when scrolled.\n                              # Set to nil to use main prompt.\n\n  :auto_complete =\u003e false,    # Is auto complete enabled?\n  :auto_source   =\u003e nil,      # Filled in by auto_complete.rb\n                              # MiniReadline::QuotedFileFolderSource\n\n  :chomp         =\u003e false,    # Remove the trailing new-line?\n\n  :eoi_detect    =\u003e false,    # Is end of input detection enabled?\n\n  :history       =\u003e false,    # Is the history buffer enabled?\n  :log           =\u003e [],       # Default is no previous history\n  :no_blanks     =\u003e true,     # No empty lines in history.\n  :no_dups       =\u003e true,     # No duplicate lines in history.\n  :no_move       =\u003e false,    # Don't move history entries.\n\n  :secret_mask   =\u003e nil,      # No secret password mask. Use the\n                              # string \"*\" to use stars or \" \"\n                              # for invisible secrets.\n\n  :initial       =\u003e \"\"        # The initial text for the entry.\n                              # An empty string for none.\n}\n```\n\n\u003cbr\u003eWhile most of these options are self explanatory, a few could stand some\nfurther description:\n* :prompt is the standard prompt used when text is not scrolled.\n* :alt_prompt is the prompt used when the text must be scrolled to fit on the\nscreen. If this is set to nil, then the main prompt is always used.\n\u003cbr\u003eBoth the prompt and alt_prompt may contain ANSI terminal control sequences.\nThese are restricted, however, to those commands that do not alter the position\nof the cursor. So basically colors, highlighting, etc.\n* :auto_complete is disabled by default. Of course there are a number of ways\nto enable it, or to make auto-complete enabled the default use:\n```ruby\nrequire 'mini_readline'\nMiniReadline::BASE_OPTION[:auto_complete] = true\n```\n* :auto_source is the class of the source for auto-complete data. By default\nthis is MiniReadline::QuotedFileFolderSource. This option can be changed up to\nget auto-complete data other than files and folders. See Auto-Compete below for\nmore details.\n* :chomp is used to remove the trailing new-line character that garnishes the\ntext from the user. Set to true for clean text, and to false for parsley to\nthrow out.\n* :eoi_detect is used to control the end of input detection logic. If disabled,\neoi inputs are treated as unmapped. If enabled, they raise a MiniReadlineEOI\nexception.\n* A few options control the history buffer. With the history option on, lines\nentered are retained in a buffer. Otherwise, no record is kept of entered text.\nWhen no_blanks is set, blank lines are not saved. When no_dups is set,\nduplicate lines are not saved. If so, when duplicates do occur, the no_move\noption keeps the older copy. Otherwise the newer copy is retained.\n* :secret_mask is a masking character to be used for sensitive input like a\npassword or missile launch code. This should be exactly one character long.\nTypical values are \"\\*\" or \" \". Also, any secret entries should be done with\nthe history option **TURNED OFF**. Otherwise later entries will be able to\nretrieve the secret codes by just scrolling through previous entries.\n* :initial is the initial text used to prefill the readline edit area with the\nspecified text. Leave as an empty string to default to the empty edit area.\n\nFinally the :window_width option is now ignored. Screen width now automatically\ndetermined.\n\n### Auto-Complete\nThe mini readline gem comes with four auto-complete engines. These are:\n\n###### MiniReadline::ArraySource\nMake a selection from an array of choices. That array is found in the\noption :array_src. This can either be an array of strings or a proc (or lambda)\nthat returns an array of strings. This is an excellent choice for choosing\nfrom a list or program generated selection of choices.\n\n###### MiniReadline::FileFolderSource\nA simple, in-line auto-complete for files and folders. This is an excellent\nchoice for cases where file names are to be used by a ruby program or passed\nto a Linux/Other command line shell.\n\n###### MiniReadline::QuotedFileFolderSource\nA simple, in-line auto-complete for files and folders embedded in quotes.\nThis is a good choice where the returned string is to be evaluated as ruby\ncode. The enclosing quotes will ensure that file names are evaluated as\nstrings. NOTE: This is the default auto-complete data source.\n\n###### MiniReadline::AutoFileSource\nThis auto-complete for files and folders is designed to automatically select\nthe appropriate folder separator character and use quotes when files contain\nembedded spaces. This is a good choice when building commands with files that\nwill be passed to the command line processor in multi-platform, portable\nenvironments. Please see the Important Security Note below.\n\n### Adding Custom Auto-Completers\nIt is possible, and fairly straightforward to add application specific\nauto-completers to mini readline. To show how this might be done, the\nFile and Folder data source is shown. Essential components of this class are\nthe initialize, rebuild, and next methods.\n\n```ruby\n  class FileFolderSource\n\n    #Create a new file/folder auto-data source. NOP\n    def initialize(options)\n      # Save or ignore the options hash.\n    end\n\n    #Construct a new data list for auto-complete given the current contents\n    #of the mini_readline edit buffer. Return true-ish for success and\n    #false-ish for failure.\n    def rebuild(str)\n      extract_root_pivot(str)\n\n      list = Dir.glob(@pivot + '*')\n\n      @cycler = list.empty? ? nil : list.cycle\n    end\n\n    #Parse the string into the two basic components. This is not part of the\n    #protocol but is included to give an example of splitting the invariant\n    #(root) part of the buffer from the variable (pivot) part.\n    def extract_root_pivot(str)\n      @root, @pivot = /\\S+$/ =~ str ? [$PREMATCH, $MATCH] : [str, \"\"]\n    end\n\n    #Get the next string for auto-complete. Note that this is the entire\n    #string, not just the pivot bit at the end.\n    def next\n      @root + @cycler.next\n    end\n\n  end\n```\nTo enable the use of a custom auto-completer, three things must be done:\n* The option[:auto_complete] must be set to true\n* The option[:auto_source] must be set to the class name of the new completer.\n* Any optional, additional options required by the completer must be set.\n\n\u003cbr\u003e See the section Options above for more details on setting/controlling\noptions.\n\n\u003cbr\u003eNote: Elsewhere in the code above there exists a require 'English'\nstatement to permit the use of clearer, easier to read access to regular\nexpression results.\n\n\u003cbr\u003e An example of a custom auto-complete facility may be found in the mysh\ngem located at: https://github.com/PeterCamilleri/mysh/blob/master/lib/mysh/sources/smart_auto_complete.rb\n\n### Adding Custom Key Maps\nIt is possible to override the default keyboard maps used by the mini_readline\ngem. The following shows the installation of a retro, WordStar\u0026#8482; inspired\nkeyboard mapping for a Windows system:\n\n```ruby\nMiniTerm.add_map(:windows) do |map|\n  map[\" \"..\"~\"] = :insert_text\n\n  #Left Arrows\n  map[\"\\x13\"]  = :go_left\n  map[\"\\x01\"]  = :word_left\n\n  #Right Arrows\n  map[\"\\x04\"]  = :go_right\n  map[\"\\x06\"]  = :word_right\n\n  #Up Arrows\n  map[\"\\x05\"]  = :previous_history\n\n  #Down Arrows\n  map[\"\\x18\"]  = :next_history\n\n  #The Home and End keys\n  map[\"\\x17\"]  = :go_home\n  map[\"\\x12\"]  = :go_end\n\n  #The Backspace and Delete keys\n  map[\"\\x08\"]  = :delete_left\n  map[\"\\x7F\"]  = :delete_right\n  map[\"\\x11\\x13\"] = :delete_all_left\n  map[\"\\x11\\x04\"] = :delete_all_right\n\n  #Auto-completion.\n  map[\"\\t\"]    = :auto_complete\n\n  #The Enter key\n  map[\"\\x0D\"]  = :enter\n\n  #The Escape key\n  map[\"\\e\"]    = :cancel\n\n  #End of Input\n  map[\"\\x1A\"]  = :end_of_input\nend\n```\n\n\n### Important Security Note\n\nIt must be remembered that any time strings are passed to the command line\nprocessor, there are serious security concerns. Passing such strings should\nonly be done in cases where the user would be trusted with access to the\ncommand line itself. Untrusted users should **never** be given such access!\n\n## Demo\nA simple demo of mini_readline in action is available. To access this demo use\nthe following:\n\n    $ sire\n\nThis will launch SIRE, a Simple Interactive Ruby Environment, a sort of\nsimple minded irb knock-off. The utility supports a number of options that\nallow the behaviour of the gem to be explored. These are:\n\nOption | Effect\n-------|-------\nlocal  | Use the mini_readline in the lib folder. For testing.\ngem    | Use the mini_readline installed as a gem. The default.\nold    | Use the old readline facility.\nmap1   | Install a Wordstar keyboard map.\nhelp   | Display usage info and exit.\n-?     | Same thing.\n\n#### Testing Shell Out Bugs\n\nOf note, the run method can be used to test for the shell process bug. For\nexample:\n\n    SIRE\u003e(run 'ls').split(\"\\n\")\n    [\"Gemfile\",\n     \"LICENSE.txt\",\n     \"README.md\",\n     \"Rakefile\",\n     \"bin\",\n     \"lib\",\n     \"mini_readline.gemspec\",\n     \"rdoc\",\n     \"reek.txt\",\n     \"sire.rb\",\n     \"tests\"]\n    SIRE\u003e\n\nAfter this command is run, the program should continue to operate correctly\nand not go bannanas. To test the behavior of the (currently broken) standard\nreadline library, use:\n\n    $ sire.rb old\n\n## Cross Platform Portability Progress\n\nThe mini_readline gem was initially designed for use with MRI version 1.9.3 or\nlater. With version 0.9.0, the internal raw_term code is replaced with the new\nmini_term gem. That gem requires Ruby 2.0.0 or greater and now so does\nmini_readline.\n\nAs almost all of the platform specific responsibility has been moved to the\nmini_term gem, the tracking of portability progress issues now resides there\nas well. Please see [mini_term](https://github.com/PeterCamilleri/mini_term)\nfor more information.\n\n## Contributing\n\nAll participation is welcomed. There are two fabulous plans to choose from:\n\n#### Plan A\n\n1. Fork it ( https://github.com/PeterCamilleri/mini_readline/fork )\n2. Switch to the development branch ('git branch development')\n3. Create your feature branch ('git checkout -b my-new-feature')\n4. Commit your changes ('git commit -am \"Add some feature\"')\n5. Push to the branch ('git push origin my-new-feature')\n6. Create new Pull Request\n\n#### Plan B\n\nGo to the GitHub repository and raise an issue calling attention to some\naspect that could use some TLC or a suggestion or an idea. Please see\n( https://github.com/PeterCamilleri/mini_readline/issues )\n\nThis is a low pressure environment. All are welcome!\n\n## License\n\nThe gem is available as open source under the terms of the\n[MIT License](./LICENSE.txt).\n\n## Code of Conduct\n\nEveryone interacting in the fully_freeze project’s codebases, issue trackers,\nchat rooms and mailing lists is expected to follow the\n[code of conduct](./CODE_OF_CONDUCT.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpetercamilleri%2Fmini_readline","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpetercamilleri%2Fmini_readline","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpetercamilleri%2Fmini_readline/lists"}