brakeman 6.2.2 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +17 -0
  3. data/bundle/load.rb +7 -6
  4. data/bundle/ruby/3.1.0/gems/csv-3.3.2/LICENSE.txt +33 -0
  5. data/bundle/ruby/3.1.0/gems/csv-3.3.2/NEWS.md +965 -0
  6. data/bundle/ruby/3.1.0/gems/csv-3.3.2/README.md +55 -0
  7. data/bundle/ruby/3.1.0/gems/csv-3.3.2/lib/csv/core_ext/array.rb +9 -0
  8. data/bundle/ruby/3.1.0/gems/csv-3.3.2/lib/csv/core_ext/string.rb +9 -0
  9. data/bundle/ruby/3.1.0/gems/csv-3.3.2/lib/csv/fields_converter.rb +96 -0
  10. data/bundle/ruby/3.1.0/gems/csv-3.3.2/lib/csv/input_record_separator.rb +18 -0
  11. data/bundle/ruby/3.1.0/gems/csv-3.3.2/lib/csv/parser.rb +1292 -0
  12. data/bundle/ruby/3.1.0/gems/csv-3.3.2/lib/csv/row.rb +757 -0
  13. data/bundle/ruby/3.1.0/gems/csv-3.3.2/lib/csv/table.rb +1055 -0
  14. data/bundle/ruby/3.1.0/gems/csv-3.3.2/lib/csv/version.rb +6 -0
  15. data/bundle/ruby/3.1.0/gems/csv-3.3.2/lib/csv/writer.rb +209 -0
  16. data/bundle/ruby/3.1.0/gems/csv-3.3.2/lib/csv.rb +3017 -0
  17. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/config.rb +22 -26
  18. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/history.rb +3 -3
  19. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/io/ansi.rb +64 -111
  20. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/io/dumb.rb +16 -2
  21. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/io/windows.rb +77 -60
  22. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/io.rb +14 -0
  23. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_actor/base.rb +10 -4
  24. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_actor/emacs.rb +96 -96
  25. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_actor/vi_command.rb +182 -182
  26. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_actor/vi_insert.rb +137 -137
  27. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_stroke.rb +26 -16
  28. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/line_editor.rb +238 -404
  29. data/bundle/ruby/3.1.0/gems/reline-0.6.0/lib/reline/unicode.rb +415 -0
  30. data/bundle/ruby/3.1.0/gems/reline-0.6.0/lib/reline/version.rb +3 -0
  31. data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline.rb +18 -18
  32. data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/NEWS.md +50 -0
  33. data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/parsers/baseparser.rb +54 -45
  34. data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/parsers/pullparser.rb +4 -0
  35. data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/rexml.rb +1 -1
  36. data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/source.rb +45 -4
  37. data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/text.rb +15 -40
  38. data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/History.rdoc +6 -0
  39. data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/sexp.rb +1 -1
  40. data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/sexp_processor.rb +1 -1
  41. data/bundle/ruby/3.1.0/gems/terminal-table-3.0.2/History.rdoc +142 -0
  42. data/bundle/ruby/3.1.0/gems/terminal-table-3.0.2/README.md +417 -0
  43. data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-3.0.2}/lib/terminal-table/cell.rb +8 -8
  44. data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-3.0.2}/lib/terminal-table/row.rb +18 -4
  45. data/bundle/ruby/3.1.0/gems/terminal-table-3.0.2/lib/terminal-table/separator.rb +66 -0
  46. data/bundle/ruby/3.1.0/gems/terminal-table-3.0.2/lib/terminal-table/style.rb +284 -0
  47. data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-3.0.2}/lib/terminal-table/table.rb +47 -18
  48. data/bundle/ruby/3.1.0/gems/terminal-table-3.0.2/lib/terminal-table/util.rb +13 -0
  49. data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-3.0.2}/lib/terminal-table/version.rb +1 -1
  50. data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-3.0.2}/lib/terminal-table.rb +2 -2
  51. data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-3.0.2}/terminal-table.gemspec +3 -3
  52. data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/creole.rb +2 -0
  53. data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/liquid.rb +0 -3
  54. data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/mapping.rb +3 -3
  55. data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/rdoc.rb +0 -8
  56. data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/template.rb +27 -3
  57. data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt.rb +1 -4
  58. data/bundle/ruby/3.1.0/gems/{unicode-display_width-1.8.0 → unicode-display_width-2.6.0}/CHANGELOG.md +65 -2
  59. data/bundle/ruby/3.1.0/gems/{unicode-display_width-1.8.0 → unicode-display_width-2.6.0}/MIT-LICENSE.txt +1 -1
  60. data/bundle/ruby/3.1.0/gems/{unicode-display_width-1.8.0 → unicode-display_width-2.6.0}/README.md +67 -20
  61. data/bundle/ruby/3.1.0/gems/unicode-display_width-2.6.0/data/display_width.marshal.gz +0 -0
  62. data/bundle/ruby/3.1.0/gems/unicode-display_width-2.6.0/lib/unicode/display_width/constants.rb +10 -0
  63. data/bundle/ruby/3.1.0/gems/unicode-display_width-2.6.0/lib/unicode/display_width/index.rb +34 -0
  64. data/bundle/ruby/3.1.0/gems/unicode-display_width-2.6.0/lib/unicode/display_width/no_string_ext.rb +8 -0
  65. data/bundle/ruby/3.1.0/gems/unicode-display_width-2.6.0/lib/unicode/display_width/string_ext.rb +9 -0
  66. data/bundle/ruby/3.1.0/gems/unicode-display_width-2.6.0/lib/unicode/display_width.rb +123 -0
  67. data/lib/brakeman/app_tree.rb +23 -18
  68. data/lib/brakeman/checks/check_deserialize.rb +4 -1
  69. data/lib/brakeman/checks/check_evaluation.rb +20 -2
  70. data/lib/brakeman/checks/check_model_attr_accessible.rb +1 -0
  71. data/lib/brakeman/file_parser.rb +2 -1
  72. data/lib/brakeman/options.rb +8 -5
  73. data/lib/brakeman/processors/alias_processor.rb +6 -2
  74. data/lib/brakeman/processors/lib/file_type_detector.rb +9 -7
  75. data/lib/brakeman/report/ignore/config.rb +0 -1
  76. data/lib/brakeman/report/report_sarif.rb +122 -2
  77. data/lib/brakeman/rescanner.rb +40 -390
  78. data/lib/brakeman/scanner.rb +62 -38
  79. data/lib/brakeman/tracker/file_cache.rb +83 -0
  80. data/lib/brakeman/tracker.rb +19 -2
  81. data/lib/brakeman/version.rb +1 -1
  82. data/lib/brakeman.rb +12 -2
  83. metadata +170 -160
  84. data/bundle/ruby/3.1.0/gems/reline-0.5.10/lib/reline/terminfo.rb +0 -158
  85. data/bundle/ruby/3.1.0/gems/reline-0.5.10/lib/reline/unicode.rb +0 -671
  86. data/bundle/ruby/3.1.0/gems/reline-0.5.10/lib/reline/version.rb +0 -3
  87. data/bundle/ruby/3.1.0/gems/terminal-table-1.8.0/History.rdoc +0 -85
  88. data/bundle/ruby/3.1.0/gems/terminal-table-1.8.0/README.rdoc +0 -247
  89. data/bundle/ruby/3.1.0/gems/terminal-table-1.8.0/lib/terminal-table/separator.rb +0 -14
  90. data/bundle/ruby/3.1.0/gems/terminal-table-1.8.0/lib/terminal-table/style.rb +0 -79
  91. data/bundle/ruby/3.1.0/gems/tilt-2.4.0/lib/tilt/erubis.rb +0 -51
  92. data/bundle/ruby/3.1.0/gems/tilt-2.4.0/lib/tilt/maruku.rb +0 -10
  93. data/bundle/ruby/3.1.0/gems/tilt-2.4.0/lib/tilt/wikicloth.rb +0 -12
  94. data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/data/display_width.marshal.gz +0 -0
  95. data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/lib/unicode/display_width/constants.rb +0 -8
  96. data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/lib/unicode/display_width/index.rb +0 -12
  97. data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/lib/unicode/display_width/no_string_ext.rb +0 -7
  98. data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/lib/unicode/display_width/string_ext.rb +0 -17
  99. data/bundle/ruby/3.1.0/gems/unicode-display_width-1.8.0/lib/unicode/display_width.rb +0 -51
  100. /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/BSDL +0 -0
  101. /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/COPYING +0 -0
  102. /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/README.md +0 -0
  103. /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/face.rb +0 -0
  104. /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_actor/composite.rb +0 -0
  105. /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/key_actor.rb +0 -0
  106. /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/kill_ring.rb +0 -0
  107. /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/lib/reline/unicode/east_asian_width.rb +0 -0
  108. /data/bundle/ruby/3.1.0/gems/{reline-0.5.10 → reline-0.6.0}/license_of_rb-readline +0 -0
  109. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/LICENSE.txt +0 -0
  110. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/README.md +0 -0
  111. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/attlistdecl.rb +0 -0
  112. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/attribute.rb +0 -0
  113. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/cdata.rb +0 -0
  114. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/child.rb +0 -0
  115. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/comment.rb +0 -0
  116. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/doctype.rb +0 -0
  117. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/document.rb +0 -0
  118. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/dtd/attlistdecl.rb +0 -0
  119. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/dtd/dtd.rb +0 -0
  120. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/dtd/elementdecl.rb +0 -0
  121. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/dtd/entitydecl.rb +0 -0
  122. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/dtd/notationdecl.rb +0 -0
  123. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/element.rb +0 -0
  124. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/encoding.rb +0 -0
  125. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/entity.rb +0 -0
  126. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/formatters/default.rb +0 -0
  127. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/formatters/pretty.rb +0 -0
  128. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/formatters/transitive.rb +0 -0
  129. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/functions.rb +0 -0
  130. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/instruction.rb +0 -0
  131. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/light/node.rb +0 -0
  132. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/namespace.rb +0 -0
  133. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/node.rb +0 -0
  134. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/output.rb +0 -0
  135. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/parent.rb +0 -0
  136. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/parseexception.rb +0 -0
  137. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/parsers/lightparser.rb +0 -0
  138. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/parsers/sax2parser.rb +0 -0
  139. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/parsers/streamparser.rb +0 -0
  140. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/parsers/treeparser.rb +0 -0
  141. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/parsers/ultralightparser.rb +0 -0
  142. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/parsers/xpathparser.rb +0 -0
  143. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/quickpath.rb +0 -0
  144. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/sax2listener.rb +0 -0
  145. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/security.rb +0 -0
  146. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/streamlistener.rb +0 -0
  147. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/undefinednamespaceexception.rb +0 -0
  148. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/validation/relaxng.rb +0 -0
  149. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/validation/validation.rb +0 -0
  150. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/validation/validationexception.rb +0 -0
  151. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/xmldecl.rb +0 -0
  152. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/xmltokens.rb +0 -0
  153. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/xpath.rb +0 -0
  154. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml/xpath_parser.rb +0 -0
  155. /data/bundle/ruby/3.1.0/gems/{rexml-3.3.8 → rexml-3.4.0}/lib/rexml.rb +0 -0
  156. /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/Manifest.txt +0 -0
  157. /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/README.rdoc +0 -0
  158. /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/composite_sexp_processor.rb +0 -0
  159. /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/pt_testcase.rb +0 -0
  160. /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/sexp_matcher.rb +0 -0
  161. /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/strict_sexp.rb +0 -0
  162. /data/bundle/ruby/3.1.0/gems/{sexp_processor-4.17.2 → sexp_processor-4.17.3}/lib/unique.rb +0 -0
  163. /data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-3.0.2}/Gemfile +0 -0
  164. /data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-3.0.2}/LICENSE.txt +0 -0
  165. /data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-3.0.2}/Manifest +0 -0
  166. /data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-3.0.2}/Todo.rdoc +0 -0
  167. /data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-3.0.2}/lib/terminal-table/import.rb +0 -0
  168. /data/bundle/ruby/3.1.0/gems/{terminal-table-1.8.0 → terminal-table-3.0.2}/lib/terminal-table/table_helper.rb +0 -0
  169. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/COPYING +0 -0
  170. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/_emacs_org.rb +0 -0
  171. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/_handlebars.rb +0 -0
  172. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/_jbuilder.rb +0 -0
  173. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/_org.rb +0 -0
  174. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/asciidoc.rb +0 -0
  175. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/babel.rb +0 -0
  176. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/builder.rb +0 -0
  177. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/cli.rb +0 -0
  178. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/coffee.rb +0 -0
  179. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/commonmarker.rb +0 -0
  180. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/csv.rb +0 -0
  181. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/erb.rb +0 -0
  182. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/erubi.rb +0 -0
  183. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/etanni.rb +0 -0
  184. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/haml.rb +0 -0
  185. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/kramdown.rb +0 -0
  186. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/livescript.rb +0 -0
  187. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/markaby.rb +0 -0
  188. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/nokogiri.rb +0 -0
  189. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/pandoc.rb +0 -0
  190. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/pipeline.rb +0 -0
  191. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/plain.rb +0 -0
  192. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/prawn.rb +0 -0
  193. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/radius.rb +0 -0
  194. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/rdiscount.rb +0 -0
  195. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/redcarpet.rb +0 -0
  196. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/redcloth.rb +0 -0
  197. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/rst-pandoc.rb +0 -0
  198. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/sass.rb +0 -0
  199. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/slim.rb +0 -0
  200. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/string.rb +0 -0
  201. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/typescript.rb +0 -0
  202. /data/bundle/ruby/3.1.0/gems/{tilt-2.4.0 → tilt-2.5.0}/lib/tilt/yajl.rb +0 -0
@@ -13,7 +13,6 @@ class Reline::LineEditor
13
13
  attr_accessor :prompt_proc
14
14
  attr_accessor :auto_indent_proc
15
15
  attr_accessor :dig_perfect_match_proc
16
- attr_writer :output
17
16
 
18
17
  VI_MOTIONS = %i{
19
18
  ed_prev_char
@@ -36,7 +35,6 @@ class Reline::LineEditor
36
35
 
37
36
  module CompletionState
38
37
  NORMAL = :normal
39
- COMPLETION = :completion
40
38
  MENU = :menu
41
39
  MENU_WITH_PERFECT_MATCH = :menu_with_perfect_match
42
40
  PERFECT_MATCH = :perfect_match
@@ -72,17 +70,21 @@ class Reline::LineEditor
72
70
 
73
71
  MINIMUM_SCROLLBAR_HEIGHT = 1
74
72
 
75
- def initialize(config, encoding)
73
+ def initialize(config)
76
74
  @config = config
77
75
  @completion_append_character = ''
78
76
  @screen_size = [0, 0] # Should be initialized with actual winsize in LineEditor#reset
79
- reset_variables(encoding: encoding)
77
+ reset_variables
80
78
  end
81
79
 
82
80
  def io_gate
83
81
  Reline::IOGate
84
82
  end
85
83
 
84
+ def encoding
85
+ io_gate.encoding
86
+ end
87
+
86
88
  def set_pasting_state(in_pasting)
87
89
  # While pasting, text to be inserted is stored to @continuous_insertion_buffer.
88
90
  # After pasting, this buffer should be force inserted.
@@ -136,9 +138,9 @@ class Reline::LineEditor
136
138
  end
137
139
  end
138
140
 
139
- def reset(prompt = '', encoding:)
141
+ def reset(prompt = '')
140
142
  @screen_size = Reline::IOGate.get_screen_size
141
- reset_variables(prompt, encoding: encoding)
143
+ reset_variables(prompt)
142
144
  @rendered_screen.base_y = Reline::IOGate.cursor_pos.y
143
145
  if ENV.key?('RELINE_ALT_SCROLLBAR')
144
146
  @full_block = '::'
@@ -150,7 +152,7 @@ class Reline::LineEditor
150
152
  @upper_half_block = '▀'
151
153
  @lower_half_block = '▄'
152
154
  @block_elem_width = 1
153
- elsif @encoding == Encoding::UTF_8
155
+ elsif encoding == Encoding::UTF_8
154
156
  @full_block = '█'
155
157
  @upper_half_block = '▀'
156
158
  @lower_half_block = '▄'
@@ -219,10 +221,9 @@ class Reline::LineEditor
219
221
  @eof
220
222
  end
221
223
 
222
- def reset_variables(prompt = '', encoding:)
224
+ def reset_variables(prompt = '')
223
225
  @prompt = prompt.gsub("\n", "\\n")
224
226
  @mark_pointer = nil
225
- @encoding = encoding
226
227
  @is_multiline = false
227
228
  @finished = false
228
229
  @history_pointer = nil
@@ -239,7 +240,7 @@ class Reline::LineEditor
239
240
  @searching_prompt = nil
240
241
  @just_cursor_moving = false
241
242
  @eof = false
242
- @continuous_insertion_buffer = String.new(encoding: @encoding)
243
+ @continuous_insertion_buffer = String.new(encoding: encoding)
243
244
  @scroll_partial_screen = 0
244
245
  @drop_terminate_spaces = false
245
246
  @in_pasting = false
@@ -251,7 +252,7 @@ class Reline::LineEditor
251
252
  @rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0)
252
253
  @input_lines = [[[""], 0, 0]]
253
254
  @input_lines_position = 0
254
- @undoing = false
255
+ @restoring = false
255
256
  @prev_action_state = NullActionState
256
257
  @next_action_state = NullActionState
257
258
  reset_line
@@ -259,11 +260,10 @@ class Reline::LineEditor
259
260
 
260
261
  def reset_line
261
262
  @byte_pointer = 0
262
- @buffer_of_lines = [String.new(encoding: @encoding)]
263
+ @buffer_of_lines = [String.new(encoding: encoding)]
263
264
  @line_index = 0
264
265
  @cache.clear
265
266
  @line_backup_in_history = nil
266
- @multibyte_buffer = String.new(encoding: 'ASCII-8BIT')
267
267
  end
268
268
 
269
269
  def multiline_on
@@ -275,7 +275,7 @@ class Reline::LineEditor
275
275
  end
276
276
 
277
277
  private def insert_new_line(cursor_line, next_line)
278
- @buffer_of_lines.insert(@line_index + 1, String.new(next_line, encoding: @encoding))
278
+ @buffer_of_lines.insert(@line_index + 1, String.new(next_line, encoding: encoding))
279
279
  @buffer_of_lines[@line_index] = cursor_line
280
280
  @line_index += 1
281
281
  @byte_pointer = 0
@@ -297,8 +297,8 @@ class Reline::LineEditor
297
297
  end
298
298
  end
299
299
 
300
- private def split_by_width(str, max_width, offset: 0)
301
- Reline::Unicode.split_by_width(str, max_width, @encoding, offset: offset)
300
+ private def split_line_by_width(str, max_width, offset: 0)
301
+ Reline::Unicode.split_line_by_width(str, max_width, encoding, offset: offset)
302
302
  end
303
303
 
304
304
  def current_byte_pointer_cursor
@@ -388,8 +388,8 @@ class Reline::LineEditor
388
388
  if (cached = cached_wraps[[prompt, line]])
389
389
  next cached
390
390
  end
391
- *wrapped_prompts, code_line_prompt = split_by_width(prompt, width).first.compact
392
- wrapped_lines = split_by_width(line, width, offset: calculate_width(code_line_prompt, true)).first.compact
391
+ *wrapped_prompts, code_line_prompt = split_line_by_width(prompt, width)
392
+ wrapped_lines = split_line_by_width(line, width, offset: calculate_width(code_line_prompt, true))
393
393
  wrapped_prompts.map { |p| [p, ''] } + [[code_line_prompt, wrapped_lines.first]] + wrapped_lines.drop(1).map { |c| ['', c] }
394
394
  end
395
395
  end
@@ -413,7 +413,7 @@ class Reline::LineEditor
413
413
  # do nothing
414
414
  elsif level == :blank
415
415
  Reline::IOGate.move_cursor_column base_x
416
- @output.write "#{Reline::IOGate.reset_color_sequence}#{' ' * width}"
416
+ Reline::IOGate.write "#{Reline::IOGate.reset_color_sequence}#{' ' * width}"
417
417
  else
418
418
  x, w, content = new_items[level]
419
419
  cover_begin = base_x != 0 && new_levels[base_x - 1] == level
@@ -423,7 +423,7 @@ class Reline::LineEditor
423
423
  content, pos = Reline::Unicode.take_mbchar_range(content, base_x - x, width, cover_begin: cover_begin, cover_end: cover_end, padding: true)
424
424
  end
425
425
  Reline::IOGate.move_cursor_column x + pos
426
- @output.write "#{Reline::IOGate.reset_color_sequence}#{content}#{Reline::IOGate.reset_color_sequence}"
426
+ Reline::IOGate.write "#{Reline::IOGate.reset_color_sequence}#{content}#{Reline::IOGate.reset_color_sequence}"
427
427
  end
428
428
  base_x += width
429
429
  end
@@ -436,8 +436,8 @@ class Reline::LineEditor
436
436
  # Calculate cursor position in word wrapped content.
437
437
  def wrapped_cursor_position
438
438
  prompt_width = calculate_width(prompt_list[@line_index], true)
439
- line_before_cursor = whole_lines[@line_index].byteslice(0, @byte_pointer)
440
- wrapped_line_before_cursor = split_by_width(' ' * prompt_width + line_before_cursor, screen_width).first.compact
439
+ line_before_cursor = Reline::Unicode.escape_for_print(whole_lines[@line_index].byteslice(0, @byte_pointer))
440
+ wrapped_line_before_cursor = split_line_by_width(' ' * prompt_width + line_before_cursor, screen_width)
441
441
  wrapped_cursor_y = wrapped_prompt_and_input_lines[0...@line_index].sum(&:size) + wrapped_line_before_cursor.size - 1
442
442
  wrapped_cursor_x = calculate_width(wrapped_line_before_cursor.last)
443
443
  [wrapped_cursor_x, wrapped_cursor_y]
@@ -459,18 +459,23 @@ class Reline::LineEditor
459
459
  end
460
460
 
461
461
  def render_finished
462
- render_differential([], 0, 0)
463
- lines = @buffer_of_lines.size.times.map do |i|
464
- line = prompt_list[i] + modified_lines[i]
465
- wrapped_lines, = split_by_width(line, screen_width)
466
- wrapped_lines.last.empty? ? "#{line} " : line
462
+ Reline::IOGate.buffered_output do
463
+ render_differential([], 0, 0)
464
+ lines = @buffer_of_lines.size.times.map do |i|
465
+ line = Reline::Unicode.strip_non_printing_start_end(prompt_list[i]) + modified_lines[i]
466
+ wrapped_lines = split_line_by_width(line, screen_width)
467
+ wrapped_lines.last.empty? ? "#{line} " : line
468
+ end
469
+ Reline::IOGate.write lines.map { |l| "#{l}\r\n" }.join
467
470
  end
468
- @output.puts lines.map { |l| "#{l}\r\n" }.join
469
471
  end
470
472
 
471
473
  def print_nomultiline_prompt
474
+ Reline::IOGate.disable_auto_linewrap(true) if Reline::IOGate.win?
472
475
  # Readline's test `TestRelineAsReadline#test_readline` requires first output to be prompt, not cursor reset escape sequence.
473
- @output.write @prompt if @prompt && !@is_multiline
476
+ Reline::IOGate.write Reline::Unicode.strip_non_printing_start_end(@prompt) if @prompt && !@is_multiline
477
+ ensure
478
+ Reline::IOGate.disable_auto_linewrap(false) if Reline::IOGate.win?
474
479
  end
475
480
 
476
481
  def render
@@ -499,13 +504,16 @@ class Reline::LineEditor
499
504
  end
500
505
  end
501
506
 
502
- render_differential new_lines, wrapped_cursor_x, wrapped_cursor_y - screen_scroll_top
507
+ Reline::IOGate.buffered_output do
508
+ render_differential new_lines, wrapped_cursor_x, wrapped_cursor_y - screen_scroll_top
509
+ end
503
510
  end
504
511
 
505
512
  # Reflects lines to be rendered and new cursor position to the screen
506
513
  # by calculating the difference from the previous render.
507
514
 
508
515
  private def render_differential(new_lines, new_cursor_x, new_cursor_y)
516
+ Reline::IOGate.disable_auto_linewrap(true) if Reline::IOGate.win?
509
517
  rendered_lines = @rendered_screen.lines
510
518
  cursor_y = @rendered_screen.cursor_y
511
519
  if new_lines != rendered_lines
@@ -536,6 +544,8 @@ class Reline::LineEditor
536
544
  Reline::IOGate.move_cursor_column new_cursor_x
537
545
  Reline::IOGate.move_cursor_down new_cursor_y - cursor_y
538
546
  @rendered_screen.cursor_y = new_cursor_y
547
+ ensure
548
+ Reline::IOGate.disable_auto_linewrap(false) if Reline::IOGate.win?
539
549
  end
540
550
 
541
551
  private def clear_rendered_screen_cache
@@ -570,8 +580,9 @@ class Reline::LineEditor
570
580
  @context
571
581
  end
572
582
 
573
- def retrieve_completion_block(set_completion_quote_character = false)
574
- @line_editor.retrieve_completion_block(set_completion_quote_character)
583
+ def retrieve_completion_block(_unused = false)
584
+ preposing, target, postposing, _quote = @line_editor.retrieve_completion_block
585
+ [preposing, target, postposing]
575
586
  end
576
587
 
577
588
  def call_completion_proc_with_checking_args(pre, target, post)
@@ -791,98 +802,73 @@ class Reline::LineEditor
791
802
  @config.editing_mode
792
803
  end
793
804
 
794
- private def menu(_target, list)
805
+ private def menu(list)
795
806
  @menu_info = MenuInfo.new(list)
796
807
  end
797
808
 
798
- private def complete_internal_proc(list, is_menu)
799
- preposing, target, postposing = retrieve_completion_block
800
- list = list.select { |i|
801
- if i and not Encoding.compatible?(target.encoding, i.encoding)
802
- raise Encoding::CompatibilityError, "#{target.encoding.name} is not compatible with #{i.encoding.name}"
809
+ private def filter_normalize_candidates(target, list)
810
+ target = target.downcase if @config.completion_ignore_case
811
+ list.select do |item|
812
+ next unless item
813
+ unless Encoding.compatible?(target.encoding, item.encoding)
814
+ # Workaround for Readline test
815
+ if defined?(::Readline) && ::Readline == ::Reline
816
+ raise Encoding::CompatibilityError, "incompatible character encodings: #{target.encoding} and #{item.encoding}"
817
+ end
803
818
  end
819
+
804
820
  if @config.completion_ignore_case
805
- i&.downcase&.start_with?(target.downcase)
821
+ item.downcase.start_with?(target)
806
822
  else
807
- i&.start_with?(target)
808
- end
809
- }.uniq
810
- if is_menu
811
- menu(target, list)
812
- return nil
813
- end
814
- completed = list.inject { |memo, item|
815
- begin
816
- memo_mbchars = memo.unicode_normalize.grapheme_clusters
817
- item_mbchars = item.unicode_normalize.grapheme_clusters
818
- rescue Encoding::CompatibilityError
819
- memo_mbchars = memo.grapheme_clusters
820
- item_mbchars = item.grapheme_clusters
821
- end
822
- size = [memo_mbchars.size, item_mbchars.size].min
823
- result = +''
824
- size.times do |i|
825
- if @config.completion_ignore_case
826
- if memo_mbchars[i].casecmp?(item_mbchars[i])
827
- result << memo_mbchars[i]
828
- else
829
- break
830
- end
831
- else
832
- if memo_mbchars[i] == item_mbchars[i]
833
- result << memo_mbchars[i]
834
- else
835
- break
836
- end
837
- end
823
+ item.start_with?(target)
838
824
  end
839
- result
840
- }
841
- [target, preposing, completed, postposing]
825
+ end.map do |item|
826
+ item.unicode_normalize
827
+ rescue Encoding::CompatibilityError
828
+ item
829
+ end.uniq
842
830
  end
843
831
 
844
- private def perform_completion(list, just_show_list)
832
+ private def perform_completion(preposing, target, postposing, quote, list)
833
+ candidates = filter_normalize_candidates(target, list)
834
+
845
835
  case @completion_state
846
- when CompletionState::NORMAL
847
- @completion_state = CompletionState::COMPLETION
848
836
  when CompletionState::PERFECT_MATCH
849
- @dig_perfect_match_proc&.(@perfect_matched)
850
- end
851
- if just_show_list
852
- is_menu = true
853
- elsif @completion_state == CompletionState::MENU
854
- is_menu = true
855
- elsif @completion_state == CompletionState::MENU_WITH_PERFECT_MATCH
856
- is_menu = true
857
- else
858
- is_menu = false
859
- end
860
- result = complete_internal_proc(list, is_menu)
861
- if @completion_state == CompletionState::MENU_WITH_PERFECT_MATCH
837
+ if @dig_perfect_match_proc
838
+ @dig_perfect_match_proc.call(@perfect_matched)
839
+ return
840
+ end
841
+ when CompletionState::MENU
842
+ menu(candidates)
843
+ return
844
+ when CompletionState::MENU_WITH_PERFECT_MATCH
845
+ menu(candidates)
862
846
  @completion_state = CompletionState::PERFECT_MATCH
847
+ return
863
848
  end
864
- return if result.nil?
865
- target, preposing, completed, postposing = result
866
- return if completed.nil?
867
- if target <= completed and (@completion_state == CompletionState::COMPLETION)
868
- if list.include?(completed)
869
- if list.one?
870
- @completion_state = CompletionState::PERFECT_MATCH
871
- else
872
- @completion_state = CompletionState::MENU_WITH_PERFECT_MATCH
873
- perform_completion(list, true) if @config.show_all_if_ambiguous
874
- end
875
- @perfect_matched = completed
849
+
850
+ completed = Reline::Unicode.common_prefix(candidates, ignore_case: @config.completion_ignore_case)
851
+ return if completed.empty?
852
+
853
+ append_character = ''
854
+ if candidates.include?(completed)
855
+ if candidates.one?
856
+ append_character = quote || completion_append_character.to_s
857
+ @completion_state = CompletionState::PERFECT_MATCH
858
+ elsif @config.show_all_if_ambiguous
859
+ menu(candidates)
860
+ @completion_state = CompletionState::PERFECT_MATCH
876
861
  else
877
- @completion_state = CompletionState::MENU
878
- perform_completion(list, true) if @config.show_all_if_ambiguous
879
- end
880
- if not just_show_list and target < completed
881
- @buffer_of_lines[@line_index] = (preposing + completed + completion_append_character.to_s + postposing).split("\n")[@line_index] || String.new(encoding: @encoding)
882
- line_to_pointer = (preposing + completed + completion_append_character.to_s).split("\n")[@line_index] || String.new(encoding: @encoding)
883
- @byte_pointer = line_to_pointer.bytesize
862
+ @completion_state = CompletionState::MENU_WITH_PERFECT_MATCH
884
863
  end
864
+ @perfect_matched = completed
865
+ else
866
+ @completion_state = CompletionState::MENU
867
+ menu(candidates) if @config.show_all_if_ambiguous
885
868
  end
869
+ @buffer_of_lines[@line_index] = (preposing + completed + append_character + postposing).split("\n")[@line_index] || String.new(encoding: encoding)
870
+ line_to_pointer = (preposing + completed + append_character).split("\n")[@line_index] || String.new(encoding: encoding)
871
+ @byte_pointer = line_to_pointer.bytesize
886
872
  end
887
873
 
888
874
  def dialog_proc_scope_completion_journey_data
@@ -911,8 +897,8 @@ class Reline::LineEditor
911
897
  end
912
898
 
913
899
  private def retrieve_completion_journey_state
914
- preposing, target, postposing = retrieve_completion_block
915
- list = call_completion_proc
900
+ preposing, target, postposing, quote = retrieve_completion_block
901
+ list = call_completion_proc(preposing, target, postposing, quote)
916
902
  return unless list.is_a?(Array)
917
903
 
918
904
  candidates = list.select{ |item| item.start_with?(target) }
@@ -987,10 +973,18 @@ class Reline::LineEditor
987
973
  @drop_terminate_spaces = false
988
974
  end
989
975
 
976
+ ARGUMENT_DIGIT_METHODS = %i[ed_digit vi_zero ed_argument_digit]
977
+ VI_WAITING_ACCEPT_METHODS = %i[vi_change_meta vi_delete_meta vi_yank ed_insert ed_argument_digit]
978
+
990
979
  private def process_key(key, method_symbol)
991
- if key.is_a?(Symbol)
992
- cleanup_waiting
993
- elsif @waiting_proc
980
+ if @waiting_proc
981
+ cleanup_waiting unless key.size == 1
982
+ end
983
+ if @vi_waiting_operator
984
+ cleanup_waiting unless VI_WAITING_ACCEPT_METHODS.include?(method_symbol) || VI_MOTIONS.include?(method_symbol)
985
+ end
986
+
987
+ if @waiting_proc
994
988
  old_byte_pointer = @byte_pointer
995
989
  @waiting_proc.call(key)
996
990
  if @vi_waiting_operator
@@ -1004,23 +998,14 @@ class Reline::LineEditor
1004
998
  return
1005
999
  end
1006
1000
 
1001
+ # Reject multibyte input (converted to ed_insert) in vi_command mode
1002
+ return if method_symbol == :ed_insert && @config.editing_mode_is?(:vi_command)
1003
+
1007
1004
  if method_symbol and respond_to?(method_symbol, true)
1008
1005
  method_obj = method(method_symbol)
1009
1006
  end
1010
- if method_symbol and key.is_a?(Symbol)
1011
- if @vi_arg and argumentable?(method_obj)
1012
- run_for_operators(key, method_symbol) do |with_operator|
1013
- wrap_method_call(method_symbol, method_obj, key, with_operator)
1014
- end
1015
- else
1016
- wrap_method_call(method_symbol, method_obj, key) if method_obj
1017
- end
1018
- @kill_ring.process
1019
- if @vi_arg
1020
- @vi_arg = nil
1021
- end
1022
- elsif @vi_arg
1023
- if key.chr =~ /[0-9]/
1007
+ if @vi_arg
1008
+ if ARGUMENT_DIGIT_METHODS.include?(method_symbol)
1024
1009
  ed_argument_digit(key)
1025
1010
  else
1026
1011
  if argumentable?(method_obj)
@@ -1029,13 +1014,9 @@ class Reline::LineEditor
1029
1014
  end
1030
1015
  elsif method_obj
1031
1016
  wrap_method_call(method_symbol, method_obj, key)
1032
- else
1033
- ed_insert(key) unless @config.editing_mode_is?(:vi_command)
1034
1017
  end
1035
1018
  @kill_ring.process
1036
- if @vi_arg
1037
- @vi_arg = nil
1038
- end
1019
+ @vi_arg = nil
1039
1020
  end
1040
1021
  elsif method_obj
1041
1022
  if method_symbol == :ed_argument_digit
@@ -1046,30 +1027,6 @@ class Reline::LineEditor
1046
1027
  end
1047
1028
  end
1048
1029
  @kill_ring.process
1049
- else
1050
- ed_insert(key) unless @config.editing_mode_is?(:vi_command)
1051
- end
1052
- end
1053
-
1054
- private def normal_char(key)
1055
- @multibyte_buffer << key.combined_char
1056
- if @multibyte_buffer.size > 1
1057
- if @multibyte_buffer.dup.force_encoding(@encoding).valid_encoding?
1058
- process_key(@multibyte_buffer.dup.force_encoding(@encoding), nil)
1059
- @multibyte_buffer.clear
1060
- else
1061
- # invalid
1062
- return
1063
- end
1064
- else # single byte
1065
- return if key.char >= 128 # maybe, first byte of multi byte
1066
- method_symbol = @config.editing_mode.get_method(key.combined_char)
1067
- process_key(key.combined_char, method_symbol)
1068
- @multibyte_buffer.clear
1069
- end
1070
- if @config.editing_mode_is?(:vi_command) and @byte_pointer > 0 and @byte_pointer == current_line.bytesize
1071
- byte_size = Reline::Unicode.get_prev_mbchar_size(@buffer_of_lines[@line_index], @byte_pointer)
1072
- @byte_pointer -= byte_size
1073
1030
  end
1074
1031
  end
1075
1032
 
@@ -1086,23 +1043,23 @@ class Reline::LineEditor
1086
1043
  def input_key(key)
1087
1044
  save_old_buffer
1088
1045
  @config.reset_oneshot_key_bindings
1089
- @dialogs.each do |dialog|
1090
- if key.char.instance_of?(Symbol) and key.char == dialog.name
1091
- return
1092
- end
1093
- end
1094
1046
  if key.char.nil?
1095
1047
  process_insert(force: true)
1096
1048
  @eof = buffer_empty?
1097
1049
  finish
1098
1050
  return
1099
1051
  end
1052
+ @dialogs.each do |dialog|
1053
+ if key.method_symbol == dialog.name
1054
+ return
1055
+ end
1056
+ end
1100
1057
  @completion_occurs = false
1101
1058
 
1102
- if key.char.is_a?(Symbol)
1103
- process_key(key.char, key.char)
1104
- else
1105
- normal_char(key)
1059
+ process_key(key.char, key.method_symbol)
1060
+ if @config.editing_mode_is?(:vi_command) and @byte_pointer > 0 and @byte_pointer == current_line.bytesize
1061
+ byte_size = Reline::Unicode.get_prev_mbchar_size(@buffer_of_lines[@line_index], @byte_pointer)
1062
+ @byte_pointer -= byte_size
1106
1063
  end
1107
1064
 
1108
1065
  @prev_action_state, @next_action_state = @next_action_state, NullActionState
@@ -1112,8 +1069,8 @@ class Reline::LineEditor
1112
1069
  @completion_journey_state = nil
1113
1070
  end
1114
1071
 
1115
- push_input_lines unless @undoing
1116
- @undoing = false
1072
+ push_input_lines unless @restoring
1073
+ @restoring = false
1117
1074
 
1118
1075
  if @in_pasting
1119
1076
  clear_dialogs
@@ -1162,9 +1119,8 @@ class Reline::LineEditor
1162
1119
  end
1163
1120
  end
1164
1121
 
1165
- def call_completion_proc
1166
- result = retrieve_completion_block(true)
1167
- pre, target, post = result
1122
+ def call_completion_proc(pre, target, post, quote)
1123
+ Reline.core.instance_variable_set(:@completion_quote_character, quote)
1168
1124
  result = call_completion_proc_with_checking_args(pre, target, post)
1169
1125
  Reline.core.instance_variable_set(:@completion_quote_character, nil)
1170
1126
  result
@@ -1228,84 +1184,32 @@ class Reline::LineEditor
1228
1184
  process_auto_indent
1229
1185
  end
1230
1186
 
1231
- def set_current_lines(lines, byte_pointer = nil, line_index = 0)
1232
- cursor = current_byte_pointer_cursor
1233
- @buffer_of_lines = lines
1234
- @line_index = line_index
1235
- if byte_pointer
1236
- @byte_pointer = byte_pointer
1237
- else
1238
- calculate_nearest_cursor(cursor)
1239
- end
1240
- process_auto_indent
1241
- end
1242
-
1243
- def retrieve_completion_block(set_completion_quote_character = false)
1244
- if Reline.completer_word_break_characters.empty?
1245
- word_break_regexp = nil
1246
- else
1247
- word_break_regexp = /\A[#{Regexp.escape(Reline.completer_word_break_characters)}]/
1248
- end
1249
- if Reline.completer_quote_characters.empty?
1250
- quote_characters_regexp = nil
1251
- else
1252
- quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/
1253
- end
1254
- before = current_line.byteslice(0, @byte_pointer)
1255
- rest = nil
1256
- break_pointer = nil
1187
+ def retrieve_completion_block
1188
+ quote_characters = Reline.completer_quote_characters
1189
+ before = current_line.byteslice(0, @byte_pointer).grapheme_clusters
1257
1190
  quote = nil
1258
- closing_quote = nil
1259
- escaped_quote = nil
1260
- i = 0
1261
- while i < @byte_pointer do
1262
- slice = current_line.byteslice(i, @byte_pointer - i)
1263
- unless slice.valid_encoding?
1264
- i += 1
1265
- next
1266
- end
1267
- if quote and slice.start_with?(closing_quote)
1268
- quote = nil
1269
- i += 1
1270
- rest = nil
1271
- elsif quote and slice.start_with?(escaped_quote)
1272
- # skip
1273
- i += 2
1274
- elsif quote_characters_regexp and slice =~ quote_characters_regexp # find new "
1275
- rest = $'
1276
- quote = $&
1277
- closing_quote = /(?!\\)#{Regexp.escape(quote)}/
1278
- escaped_quote = /\\#{Regexp.escape(quote)}/
1279
- i += 1
1280
- break_pointer = i - 1
1281
- elsif word_break_regexp and not quote and slice =~ word_break_regexp
1282
- rest = $'
1283
- i += 1
1284
- before = current_line.byteslice(i, @byte_pointer - i)
1285
- break_pointer = i
1286
- else
1287
- i += 1
1288
- end
1289
- end
1290
- postposing = current_line.byteslice(@byte_pointer, current_line.bytesize - @byte_pointer)
1291
- if rest
1292
- preposing = current_line.byteslice(0, break_pointer)
1293
- target = rest
1294
- if set_completion_quote_character and quote
1295
- Reline.core.instance_variable_set(:@completion_quote_character, quote)
1296
- if postposing !~ /(?!\\)#{Regexp.escape(quote)}/ # closing quote
1297
- insert_text(quote)
1191
+ # Calcualte closing quote when cursor is at the end of the line
1192
+ if current_line.bytesize == @byte_pointer && !quote_characters.empty?
1193
+ escaped = false
1194
+ before.each do |c|
1195
+ if escaped
1196
+ escaped = false
1197
+ next
1198
+ elsif c == '\\'
1199
+ escaped = true
1200
+ elsif quote
1201
+ quote = nil if c == quote
1202
+ elsif quote_characters.include?(c)
1203
+ quote = c
1298
1204
  end
1299
1205
  end
1300
- else
1301
- preposing = ''
1302
- if break_pointer
1303
- preposing = current_line.byteslice(0, break_pointer)
1304
- else
1305
- preposing = ''
1306
- end
1307
- target = before
1308
1206
  end
1207
+
1208
+ word_break_characters = quote_characters + Reline.completer_word_break_characters
1209
+ break_index = before.rindex { |c| word_break_characters.include?(c) || quote_characters.include?(c) } || -1
1210
+ preposing = before.take(break_index + 1).join
1211
+ target = before.drop(break_index + 1).join
1212
+ postposing = current_line.byteslice(@byte_pointer, current_line.bytesize - @byte_pointer)
1309
1213
  lines = whole_lines
1310
1214
  if @line_index > 0
1311
1215
  preposing = lines[0..(@line_index - 1)].join("\n") + "\n" + preposing
@@ -1313,7 +1217,7 @@ class Reline::LineEditor
1313
1217
  if (lines.size - 1) > @line_index
1314
1218
  postposing = postposing + "\n" + lines[(@line_index + 1)..-1].join("\n")
1315
1219
  end
1316
- [preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)]
1220
+ [preposing.encode(encoding), target.encode(encoding), postposing.encode(encoding), quote&.encode(encoding)]
1317
1221
  end
1318
1222
 
1319
1223
  def confirm_multiline_termination
@@ -1322,15 +1226,13 @@ class Reline::LineEditor
1322
1226
  end
1323
1227
 
1324
1228
  def insert_multiline_text(text)
1325
- save_old_buffer
1326
1229
  pre = @buffer_of_lines[@line_index].byteslice(0, @byte_pointer)
1327
1230
  post = @buffer_of_lines[@line_index].byteslice(@byte_pointer..)
1328
- lines = (pre + text.gsub(/\r\n?/, "\n") + post).split("\n", -1)
1231
+ lines = (pre + Reline::Unicode.safe_encode(text, encoding).gsub(/\r\n?/, "\n") + post).split("\n", -1)
1329
1232
  lines << '' if lines.empty?
1330
1233
  @buffer_of_lines[@line_index, 1] = lines
1331
1234
  @line_index += lines.size - 1
1332
1235
  @byte_pointer = @buffer_of_lines[@line_index].bytesize - post.bytesize
1333
- push_input_lines
1334
1236
  end
1335
1237
 
1336
1238
  def insert_text(text)
@@ -1370,7 +1272,7 @@ class Reline::LineEditor
1370
1272
  last += current_line.bytesize if last < 0
1371
1273
  first += current_line.bytesize if first < 0
1372
1274
  range = range.exclude_end? ? first...last : first..last
1373
- line = current_line.bytes.reject.with_index{ |c, i| range.include?(i) }.map{ |c| c.chr(Encoding::ASCII_8BIT) }.join.force_encoding(@encoding)
1275
+ line = current_line.bytes.reject.with_index{ |c, i| range.include?(i) }.map{ |c| c.chr(Encoding::ASCII_8BIT) }.join.force_encoding(encoding)
1374
1276
  set_current_line(line)
1375
1277
  else
1376
1278
  set_current_line(current_line.byteslice(0, start))
@@ -1444,10 +1346,11 @@ class Reline::LineEditor
1444
1346
  @completion_occurs = move_completed_list(:down)
1445
1347
  else
1446
1348
  @completion_journey_state = nil
1447
- result = call_completion_proc
1349
+ pre, target, post, quote = retrieve_completion_block
1350
+ result = call_completion_proc(pre, target, post, quote)
1448
1351
  if result.is_a?(Array)
1449
1352
  @completion_occurs = true
1450
- perform_completion(result, false)
1353
+ perform_completion(pre, target, post, quote, result)
1451
1354
  end
1452
1355
  end
1453
1356
  end
@@ -1495,21 +1398,11 @@ class Reline::LineEditor
1495
1398
  # digit or if the existing argument is already greater than a
1496
1399
  # million.
1497
1400
  # GNU Readline:: +self-insert+ (a, b, A, 1, !, …) Insert yourself.
1498
- private def ed_insert(key)
1499
- if key.instance_of?(String)
1500
- begin
1501
- key.encode(Encoding::UTF_8)
1502
- rescue Encoding::UndefinedConversionError
1503
- return
1504
- end
1505
- str = key
1506
- else
1507
- begin
1508
- key.chr.encode(Encoding::UTF_8)
1509
- rescue Encoding::UndefinedConversionError
1510
- return
1511
- end
1512
- str = key.chr
1401
+ private def ed_insert(str)
1402
+ begin
1403
+ str.encode(Encoding::UTF_8)
1404
+ rescue Encoding::UndefinedConversionError
1405
+ return
1513
1406
  end
1514
1407
  if @in_pasting
1515
1408
  @continuous_insertion_buffer << str
@@ -1523,21 +1416,16 @@ class Reline::LineEditor
1523
1416
  alias_method :ed_digit, :ed_insert
1524
1417
  alias_method :self_insert, :ed_insert
1525
1418
 
1526
- private def ed_quoted_insert(str, arg: 1)
1527
- @waiting_proc = proc { |key|
1528
- arg.times do
1529
- if key == "\C-j".ord or key == "\C-m".ord
1530
- key_newline(key)
1531
- elsif key == 0
1532
- # Ignore NUL.
1533
- else
1534
- ed_insert(key)
1535
- end
1419
+ private def insert_raw_char(str, arg: 1)
1420
+ arg.times do
1421
+ if str == "\C-j" or str == "\C-m"
1422
+ key_newline(str)
1423
+ elsif str != "\0"
1424
+ # Ignore NUL.
1425
+ ed_insert(str)
1536
1426
  end
1537
- @waiting_proc = nil
1538
- }
1427
+ end
1539
1428
  end
1540
- alias_method :quoted_insert, :ed_quoted_insert
1541
1429
 
1542
1430
  private def ed_next_char(key, arg: 1)
1543
1431
  byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
@@ -1566,7 +1454,7 @@ class Reline::LineEditor
1566
1454
  alias_method :backward_char, :ed_prev_char
1567
1455
 
1568
1456
  private def vi_first_print(key)
1569
- @byte_pointer, = Reline::Unicode.vi_first_print(current_line)
1457
+ @byte_pointer = Reline::Unicode.vi_first_print(current_line)
1570
1458
  end
1571
1459
 
1572
1460
  private def ed_move_to_beg(key)
@@ -1581,27 +1469,22 @@ class Reline::LineEditor
1581
1469
  alias_method :end_of_line, :ed_move_to_end
1582
1470
 
1583
1471
  private def generate_searcher(search_key)
1584
- search_word = String.new(encoding: @encoding)
1585
- multibyte_buf = String.new(encoding: 'ASCII-8BIT')
1472
+ search_word = String.new(encoding: encoding)
1586
1473
  hit_pointer = nil
1587
1474
  lambda do |key|
1588
1475
  search_again = false
1589
1476
  case key
1590
- when "\C-h".ord, "\C-?".ord
1477
+ when "\C-h", "\C-?"
1591
1478
  grapheme_clusters = search_word.grapheme_clusters
1592
1479
  if grapheme_clusters.size > 0
1593
1480
  grapheme_clusters.pop
1594
1481
  search_word = grapheme_clusters.join
1595
1482
  end
1596
- when "\C-r".ord, "\C-s".ord
1483
+ when "\C-r", "\C-s"
1597
1484
  search_again = true if search_key == key
1598
1485
  search_key = key
1599
1486
  else
1600
- multibyte_buf << key
1601
- if multibyte_buf.dup.force_encoding(@encoding).valid_encoding?
1602
- search_word << multibyte_buf.dup.force_encoding(@encoding)
1603
- multibyte_buf.clear
1604
- end
1487
+ search_word << key
1605
1488
  end
1606
1489
  hit = nil
1607
1490
  if not search_word.empty? and @line_backup_in_history&.include?(search_word)
@@ -1614,10 +1497,10 @@ class Reline::LineEditor
1614
1497
  end
1615
1498
  if @history_pointer
1616
1499
  case search_key
1617
- when "\C-r".ord
1500
+ when "\C-r"
1618
1501
  history_pointer_base = 0
1619
1502
  history = Reline::HISTORY[0..(@history_pointer - 1)]
1620
- when "\C-s".ord
1503
+ when "\C-s"
1621
1504
  history_pointer_base = @history_pointer + 1
1622
1505
  history = Reline::HISTORY[(@history_pointer + 1)..-1]
1623
1506
  end
@@ -1627,10 +1510,10 @@ class Reline::LineEditor
1627
1510
  end
1628
1511
  elsif @history_pointer
1629
1512
  case search_key
1630
- when "\C-r".ord
1513
+ when "\C-r"
1631
1514
  history_pointer_base = 0
1632
1515
  history = Reline::HISTORY[0..@history_pointer]
1633
- when "\C-s".ord
1516
+ when "\C-s"
1634
1517
  history_pointer_base = @history_pointer
1635
1518
  history = Reline::HISTORY[@history_pointer..-1]
1636
1519
  end
@@ -1639,11 +1522,11 @@ class Reline::LineEditor
1639
1522
  history = Reline::HISTORY
1640
1523
  end
1641
1524
  case search_key
1642
- when "\C-r".ord
1525
+ when "\C-r"
1643
1526
  hit_index = history.rindex { |item|
1644
1527
  item.include?(search_word)
1645
1528
  }
1646
- when "\C-s".ord
1529
+ when "\C-s"
1647
1530
  hit_index = history.index { |item|
1648
1531
  item.include?(search_word)
1649
1532
  }
@@ -1654,9 +1537,9 @@ class Reline::LineEditor
1654
1537
  end
1655
1538
  end
1656
1539
  case search_key
1657
- when "\C-r".ord
1540
+ when "\C-r"
1658
1541
  prompt_name = 'reverse-i-search'
1659
- when "\C-s".ord
1542
+ when "\C-s"
1660
1543
  prompt_name = 'i-search'
1661
1544
  end
1662
1545
  prompt_name = "failed #{prompt_name}" unless hit
@@ -1665,57 +1548,28 @@ class Reline::LineEditor
1665
1548
  end
1666
1549
 
1667
1550
  private def incremental_search_history(key)
1668
- unless @history_pointer
1669
- @line_backup_in_history = whole_buffer
1670
- end
1551
+ backup = @buffer_of_lines.dup, @line_index, @byte_pointer, @history_pointer, @line_backup_in_history
1671
1552
  searcher = generate_searcher(key)
1672
1553
  @searching_prompt = "(reverse-i-search)`': "
1673
- termination_keys = ["\C-j".ord]
1674
- termination_keys.concat(@config.isearch_terminators&.chars&.map(&:ord)) if @config.isearch_terminators
1554
+ termination_keys = ["\C-j"]
1555
+ termination_keys.concat(@config.isearch_terminators.chars) if @config.isearch_terminators
1675
1556
  @waiting_proc = ->(k) {
1676
- case k
1677
- when *termination_keys
1678
- if @history_pointer
1679
- buffer = Reline::HISTORY[@history_pointer]
1680
- else
1681
- buffer = @line_backup_in_history
1682
- end
1683
- @buffer_of_lines = buffer.split("\n")
1684
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
1685
- @line_index = @buffer_of_lines.size - 1
1557
+ if k == "\C-g"
1558
+ # cancel search and restore buffer
1559
+ @buffer_of_lines, @line_index, @byte_pointer, @history_pointer, @line_backup_in_history = backup
1686
1560
  @searching_prompt = nil
1687
1561
  @waiting_proc = nil
1688
- @byte_pointer = 0
1689
- when "\C-g".ord
1690
- @buffer_of_lines = @line_backup_in_history.split("\n")
1691
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
1692
- @line_index = @buffer_of_lines.size - 1
1693
- move_history(nil, line: :end, cursor: :end, save_buffer: false)
1562
+ elsif !termination_keys.include?(k) && (k.match?(/[[:print:]]/) || k == "\C-h" || k == "\C-?" || k == "\C-r" || k == "\C-s")
1563
+ search_word, prompt_name, hit_pointer = searcher.call(k)
1564
+ Reline.last_incremental_search = search_word
1565
+ @searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
1566
+ @searching_prompt += ': ' unless @is_multiline
1567
+ move_history(hit_pointer, line: :end, cursor: :end) if hit_pointer
1568
+ else
1569
+ # terminaton_keys and other keys will terminalte
1570
+ move_history(@history_pointer, line: :end, cursor: :start)
1694
1571
  @searching_prompt = nil
1695
1572
  @waiting_proc = nil
1696
- @byte_pointer = 0
1697
- else
1698
- chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT)
1699
- if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k == "\C-?".ord or k == "\C-r".ord or k == "\C-s".ord
1700
- search_word, prompt_name, hit_pointer = searcher.call(k)
1701
- Reline.last_incremental_search = search_word
1702
- @searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
1703
- @searching_prompt += ': ' unless @is_multiline
1704
- move_history(hit_pointer, line: :end, cursor: :end, save_buffer: false) if hit_pointer
1705
- else
1706
- if @history_pointer
1707
- line = Reline::HISTORY[@history_pointer]
1708
- else
1709
- line = @line_backup_in_history
1710
- end
1711
- @line_backup_in_history = whole_buffer
1712
- @buffer_of_lines = line.split("\n")
1713
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
1714
- @line_index = @buffer_of_lines.size - 1
1715
- @searching_prompt = nil
1716
- @waiting_proc = nil
1717
- @byte_pointer = 0
1718
- end
1719
1573
  end
1720
1574
  }
1721
1575
  end
@@ -1770,14 +1624,14 @@ class Reline::LineEditor
1770
1624
  end
1771
1625
  alias_method :history_search_forward, :ed_search_next_history
1772
1626
 
1773
- private def move_history(history_pointer, line:, cursor:, save_buffer: true)
1627
+ private def move_history(history_pointer, line:, cursor:)
1774
1628
  history_pointer ||= Reline::HISTORY.size
1775
1629
  return if history_pointer < 0 || history_pointer > Reline::HISTORY.size
1776
1630
  old_history_pointer = @history_pointer || Reline::HISTORY.size
1777
1631
  if old_history_pointer == Reline::HISTORY.size
1778
- @line_backup_in_history = save_buffer ? whole_buffer : ''
1632
+ @line_backup_in_history = whole_buffer
1779
1633
  else
1780
- Reline::HISTORY[old_history_pointer] = whole_buffer if save_buffer
1634
+ Reline::HISTORY[old_history_pointer] = whole_buffer
1781
1635
  end
1782
1636
  if history_pointer == Reline::HISTORY.size
1783
1637
  buf = @line_backup_in_history
@@ -1787,7 +1641,7 @@ class Reline::LineEditor
1787
1641
  @history_pointer = history_pointer
1788
1642
  end
1789
1643
  @buffer_of_lines = buf.split("\n")
1790
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
1644
+ @buffer_of_lines = [String.new(encoding: encoding)] if @buffer_of_lines.empty?
1791
1645
  @line_index = line == :start ? 0 : line == :end ? @buffer_of_lines.size - 1 : line
1792
1646
  @byte_pointer = cursor == :start ? 0 : cursor == :end ? current_line.bytesize : cursor
1793
1647
  end
@@ -1921,7 +1775,7 @@ class Reline::LineEditor
1921
1775
  alias_method :kill_whole_line, :em_kill_line
1922
1776
 
1923
1777
  private def em_delete(key)
1924
- if buffer_empty? and key == "\C-d".ord
1778
+ if buffer_empty? and key == "\C-d"
1925
1779
  @eof = true
1926
1780
  finish
1927
1781
  elsif @byte_pointer < current_line.bytesize
@@ -1939,9 +1793,11 @@ class Reline::LineEditor
1939
1793
  if current_line.empty? or @byte_pointer < current_line.bytesize
1940
1794
  em_delete(key)
1941
1795
  elsif !@config.autocompletion # show completed list
1942
- result = call_completion_proc
1796
+ pre, target, post, quote = retrieve_completion_block
1797
+ result = call_completion_proc(pre, target, post, quote)
1943
1798
  if result.is_a?(Array)
1944
- perform_completion(result, true)
1799
+ candidates = filter_normalize_candidates(target, result)
1800
+ menu(candidates)
1945
1801
  end
1946
1802
  end
1947
1803
  end
@@ -1973,7 +1829,7 @@ class Reline::LineEditor
1973
1829
 
1974
1830
  private def em_next_word(key)
1975
1831
  if current_line.bytesize > @byte_pointer
1976
- byte_size, _ = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
1832
+ byte_size = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
1977
1833
  @byte_pointer += byte_size
1978
1834
  end
1979
1835
  end
@@ -1981,7 +1837,7 @@ class Reline::LineEditor
1981
1837
 
1982
1838
  private def ed_prev_word(key)
1983
1839
  if @byte_pointer > 0
1984
- byte_size, _ = Reline::Unicode.em_backward_word(current_line, @byte_pointer)
1840
+ byte_size = Reline::Unicode.em_backward_word(current_line, @byte_pointer)
1985
1841
  @byte_pointer -= byte_size
1986
1842
  end
1987
1843
  end
@@ -1989,7 +1845,7 @@ class Reline::LineEditor
1989
1845
 
1990
1846
  private def em_delete_next_word(key)
1991
1847
  if current_line.bytesize > @byte_pointer
1992
- byte_size, _ = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
1848
+ byte_size = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
1993
1849
  line, word = byteslice!(current_line, @byte_pointer, byte_size)
1994
1850
  set_current_line(line)
1995
1851
  @kill_ring.append(word)
@@ -1999,7 +1855,7 @@ class Reline::LineEditor
1999
1855
 
2000
1856
  private def ed_delete_prev_word(key)
2001
1857
  if @byte_pointer > 0
2002
- byte_size, _ = Reline::Unicode.em_backward_word(current_line, @byte_pointer)
1858
+ byte_size = Reline::Unicode.em_backward_word(current_line, @byte_pointer)
2003
1859
  line, word = byteslice!(current_line, @byte_pointer - byte_size, byte_size)
2004
1860
  set_current_line(line, @byte_pointer - byte_size)
2005
1861
  @kill_ring.append(word, true)
@@ -2039,7 +1895,7 @@ class Reline::LineEditor
2039
1895
 
2040
1896
  private def em_capitol_case(key)
2041
1897
  if current_line.bytesize > @byte_pointer
2042
- byte_size, _, new_str = Reline::Unicode.em_forward_word_with_capitalization(current_line, @byte_pointer)
1898
+ byte_size, new_str = Reline::Unicode.em_forward_word_with_capitalization(current_line, @byte_pointer)
2043
1899
  before = current_line.byteslice(0, @byte_pointer)
2044
1900
  after = current_line.byteslice((@byte_pointer + byte_size)..-1)
2045
1901
  set_current_line(before + new_str + after, @byte_pointer + new_str.bytesize)
@@ -2049,7 +1905,7 @@ class Reline::LineEditor
2049
1905
 
2050
1906
  private def em_lower_case(key)
2051
1907
  if current_line.bytesize > @byte_pointer
2052
- byte_size, = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
1908
+ byte_size = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
2053
1909
  part = current_line.byteslice(@byte_pointer, byte_size).grapheme_clusters.map { |mbchar|
2054
1910
  mbchar =~ /[A-Z]/ ? mbchar.downcase : mbchar
2055
1911
  }.join
@@ -2062,7 +1918,7 @@ class Reline::LineEditor
2062
1918
 
2063
1919
  private def em_upper_case(key)
2064
1920
  if current_line.bytesize > @byte_pointer
2065
- byte_size, = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
1921
+ byte_size = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
2066
1922
  part = current_line.byteslice(@byte_pointer, byte_size).grapheme_clusters.map { |mbchar|
2067
1923
  mbchar =~ /[a-z]/ ? mbchar.upcase : mbchar
2068
1924
  }.join
@@ -2075,7 +1931,7 @@ class Reline::LineEditor
2075
1931
 
2076
1932
  private def em_kill_region(key)
2077
1933
  if @byte_pointer > 0
2078
- byte_size, _ = Reline::Unicode.em_big_backward_word(current_line, @byte_pointer)
1934
+ byte_size = Reline::Unicode.em_big_backward_word(current_line, @byte_pointer)
2079
1935
  line, deleted = byteslice!(current_line, @byte_pointer - byte_size, byte_size)
2080
1936
  set_current_line(line, @byte_pointer - byte_size)
2081
1937
  @kill_ring.append(deleted, true)
@@ -2106,7 +1962,7 @@ class Reline::LineEditor
2106
1962
 
2107
1963
  private def vi_next_word(key, arg: 1)
2108
1964
  if current_line.bytesize > @byte_pointer
2109
- byte_size, _ = Reline::Unicode.vi_forward_word(current_line, @byte_pointer, @drop_terminate_spaces)
1965
+ byte_size = Reline::Unicode.vi_forward_word(current_line, @byte_pointer, @drop_terminate_spaces)
2110
1966
  @byte_pointer += byte_size
2111
1967
  end
2112
1968
  arg -= 1
@@ -2115,7 +1971,7 @@ class Reline::LineEditor
2115
1971
 
2116
1972
  private def vi_prev_word(key, arg: 1)
2117
1973
  if @byte_pointer > 0
2118
- byte_size, _ = Reline::Unicode.vi_backward_word(current_line, @byte_pointer)
1974
+ byte_size = Reline::Unicode.vi_backward_word(current_line, @byte_pointer)
2119
1975
  @byte_pointer -= byte_size
2120
1976
  end
2121
1977
  arg -= 1
@@ -2124,7 +1980,7 @@ class Reline::LineEditor
2124
1980
 
2125
1981
  private def vi_end_word(key, arg: 1, inclusive: false)
2126
1982
  if current_line.bytesize > @byte_pointer
2127
- byte_size, _ = Reline::Unicode.vi_forward_end_word(current_line, @byte_pointer)
1983
+ byte_size = Reline::Unicode.vi_forward_end_word(current_line, @byte_pointer)
2128
1984
  @byte_pointer += byte_size
2129
1985
  end
2130
1986
  arg -= 1
@@ -2139,7 +1995,7 @@ class Reline::LineEditor
2139
1995
 
2140
1996
  private def vi_next_big_word(key, arg: 1)
2141
1997
  if current_line.bytesize > @byte_pointer
2142
- byte_size, _ = Reline::Unicode.vi_big_forward_word(current_line, @byte_pointer)
1998
+ byte_size = Reline::Unicode.vi_big_forward_word(current_line, @byte_pointer)
2143
1999
  @byte_pointer += byte_size
2144
2000
  end
2145
2001
  arg -= 1
@@ -2148,7 +2004,7 @@ class Reline::LineEditor
2148
2004
 
2149
2005
  private def vi_prev_big_word(key, arg: 1)
2150
2006
  if @byte_pointer > 0
2151
- byte_size, _ = Reline::Unicode.vi_big_backward_word(current_line, @byte_pointer)
2007
+ byte_size = Reline::Unicode.vi_big_backward_word(current_line, @byte_pointer)
2152
2008
  @byte_pointer -= byte_size
2153
2009
  end
2154
2010
  arg -= 1
@@ -2157,7 +2013,7 @@ class Reline::LineEditor
2157
2013
 
2158
2014
  private def vi_end_big_word(key, arg: 1, inclusive: false)
2159
2015
  if current_line.bytesize > @byte_pointer
2160
- byte_size, _ = Reline::Unicode.vi_big_forward_end_word(current_line, @byte_pointer)
2016
+ byte_size = Reline::Unicode.vi_big_forward_end_word(current_line, @byte_pointer)
2161
2017
  @byte_pointer += byte_size
2162
2018
  end
2163
2019
  arg -= 1
@@ -2312,7 +2168,7 @@ class Reline::LineEditor
2312
2168
  }
2313
2169
  system("#{ENV['EDITOR']} #{path}")
2314
2170
  @buffer_of_lines = File.read(path).split("\n")
2315
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
2171
+ @buffer_of_lines = [String.new(encoding: encoding)] if @buffer_of_lines.empty?
2316
2172
  @line_index = 0
2317
2173
  finish
2318
2174
  end
@@ -2337,20 +2193,9 @@ class Reline::LineEditor
2337
2193
  end
2338
2194
 
2339
2195
  private def ed_argument_digit(key)
2340
- if @vi_arg.nil?
2341
- if key.chr.to_i.zero?
2342
- if key.anybits?(0b10000000)
2343
- unescaped_key = key ^ 0b10000000
2344
- unless unescaped_key.chr.to_i.zero?
2345
- @vi_arg = unescaped_key.chr.to_i
2346
- end
2347
- end
2348
- else
2349
- @vi_arg = key.chr.to_i
2350
- end
2351
- else
2352
- @vi_arg = @vi_arg * 10 + key.chr.to_i
2353
- end
2196
+ # key is expected to be `ESC digit` or `digit`
2197
+ num = key[/\d/].to_i
2198
+ @vi_arg = (@vi_arg || 0) * 10 + num
2354
2199
  end
2355
2200
 
2356
2201
  private def vi_to_column(key, arg: 0)
@@ -2369,7 +2214,7 @@ class Reline::LineEditor
2369
2214
  before = current_line.byteslice(0, @byte_pointer)
2370
2215
  remaining_point = @byte_pointer + byte_size
2371
2216
  after = current_line.byteslice(remaining_point, current_line.bytesize - remaining_point)
2372
- set_current_line(before + k.chr + after)
2217
+ set_current_line(before + k + after)
2373
2218
  @waiting_proc = nil
2374
2219
  elsif arg > 1
2375
2220
  byte_size = 0
@@ -2379,7 +2224,7 @@ class Reline::LineEditor
2379
2224
  before = current_line.byteslice(0, @byte_pointer)
2380
2225
  remaining_point = @byte_pointer + byte_size
2381
2226
  after = current_line.byteslice(remaining_point, current_line.bytesize - remaining_point)
2382
- replaced = k.chr * arg
2227
+ replaced = k * arg
2383
2228
  set_current_line(before + replaced + after, @byte_pointer + replaced.bytesize)
2384
2229
  @waiting_proc = nil
2385
2230
  end
@@ -2395,11 +2240,6 @@ class Reline::LineEditor
2395
2240
  end
2396
2241
 
2397
2242
  private def search_next_char(key, arg, need_prev_char: false, inclusive: false)
2398
- if key.instance_of?(String)
2399
- inputed_char = key
2400
- else
2401
- inputed_char = key.chr
2402
- end
2403
2243
  prev_total = nil
2404
2244
  total = nil
2405
2245
  found = false
@@ -2410,7 +2250,7 @@ class Reline::LineEditor
2410
2250
  width = Reline::Unicode.get_mbchar_width(mbchar)
2411
2251
  total = [mbchar.bytesize, width]
2412
2252
  else
2413
- if inputed_char == mbchar
2253
+ if key == mbchar
2414
2254
  arg -= 1
2415
2255
  if arg.zero?
2416
2256
  found = true
@@ -2447,11 +2287,6 @@ class Reline::LineEditor
2447
2287
  end
2448
2288
 
2449
2289
  private def search_prev_char(key, arg, need_next_char = false)
2450
- if key.instance_of?(String)
2451
- inputed_char = key
2452
- else
2453
- inputed_char = key.chr
2454
- end
2455
2290
  prev_total = nil
2456
2291
  total = nil
2457
2292
  found = false
@@ -2462,7 +2297,7 @@ class Reline::LineEditor
2462
2297
  width = Reline::Unicode.get_mbchar_width(mbchar)
2463
2298
  total = [mbchar.bytesize, width]
2464
2299
  else
2465
- if inputed_char == mbchar
2300
+ if key == mbchar
2466
2301
  arg -= 1
2467
2302
  if arg.zero?
2468
2303
  found = true
@@ -2514,24 +2349,23 @@ class Reline::LineEditor
2514
2349
  @config.editing_mode = :vi_insert
2515
2350
  end
2516
2351
 
2517
- private def undo(_key)
2518
- @undoing = true
2352
+ private def move_undo_redo(direction)
2353
+ @restoring = true
2354
+ return unless (0..@input_lines.size - 1).cover?(@input_lines_position + direction)
2519
2355
 
2520
- return if @input_lines_position <= 0
2356
+ @input_lines_position += direction
2357
+ buffer_of_lines, byte_pointer, line_index = @input_lines[@input_lines_position]
2358
+ @buffer_of_lines = buffer_of_lines.dup
2359
+ @line_index = line_index
2360
+ @byte_pointer = byte_pointer
2361
+ end
2521
2362
 
2522
- @input_lines_position -= 1
2523
- target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
2524
- set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
2363
+ private def undo(_key)
2364
+ move_undo_redo(-1)
2525
2365
  end
2526
2366
 
2527
2367
  private def redo(_key)
2528
- @undoing = true
2529
-
2530
- return if @input_lines_position >= @input_lines.size - 1
2531
-
2532
- @input_lines_position += 1
2533
- target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
2534
- set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
2368
+ move_undo_redo(+1)
2535
2369
  end
2536
2370
 
2537
2371
  private def prev_action_state_value(type)