PageRenderTime 69ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/IronPython_Main/External.LCA_RESTRICTED/Languages/Ruby/redist-libs/ruby/site_ruby/1.9.1/rbreadline.rb

#
Ruby | 8664 lines | 6081 code | 1132 blank | 1451 comment | 1492 complexity | 1b86031473b7980d86552309ca944a1e MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  1. # rbreadline.rb -- a general facility for reading lines of input
  2. # with emacs style editing and completion.
  3. #
  4. # Inspired by GNU Readline, translation to Ruby
  5. # Copyright (C) 2009 by Park Heesob phasis@gmail.com
  6. #
  7. class Fixnum
  8. def ord; self; end
  9. end
  10. module RbReadline
  11. require 'etc'
  12. RL_LIBRARY_VERSION = "5.2"
  13. RL_READLINE_VERSION = 0x0502
  14. RB_READLINE_VERSION = "0.2.0"
  15. EOF = "\xFF"
  16. ESC = "\C-["
  17. PAGE = "\C-L"
  18. SPACE = "\x20"
  19. RETURN = "\C-M"
  20. ABORT_CHAR = "\C-G"
  21. TAB = "\t"
  22. RUBOUT = "x7f"
  23. NEWLINE = "\n"
  24. DEFAULT_BUFFER_SIZE = 256
  25. DEFAULT_MAX_KILLS = 10
  26. MB_FIND_NONZERO = 1
  27. MB_FIND_ANY = 0
  28. MB_LEN_MAX = 4
  29. DEFAULT_INPUTRC = "~/.inputrc"
  30. SYS_INPUTRC = "/etc/inputrc"
  31. UpCase = 1
  32. DownCase = 2
  33. CapCase = 3
  34. # Possible history errors passed to hist_error.
  35. EVENT_NOT_FOUND = 0
  36. BAD_WORD_SPEC = 1
  37. SUBST_FAILED = 2
  38. BAD_MODIFIER = 3
  39. NO_PREV_SUBST = 4
  40. # Possible definitions for history starting point specification.
  41. ANCHORED_SEARCH = 1
  42. NON_ANCHORED_SEARCH = 0
  43. # Possible definitions for what style of writing the history file we want.
  44. HISTORY_APPEND = 0
  45. HISTORY_OVERWRITE = 1
  46. # Input error; can be returned by (*rl_getc_function) if readline is reading
  47. # a top-level command (RL_ISSTATE (RL_STATE_READCMD)).
  48. READERR = 0xFE.chr
  49. # Definitions available for use by readline clients.
  50. RL_PROMPT_START_IGNORE = 1.chr
  51. RL_PROMPT_END_IGNORE = 2.chr
  52. # Possible values for do_replace argument to rl_filename_quoting_function,
  53. # called by rl_complete_internal.
  54. NO_MATCH = 0
  55. SINGLE_MATCH = 1
  56. MULT_MATCH = 2
  57. # Callback data for reading numeric arguments
  58. NUM_SAWMINUS = 0x01
  59. NUM_SAWDIGITS = 0x02
  60. NUM_READONE = 0x04
  61. # A context for reading key sequences longer than a single character when
  62. # using the callback interface.
  63. KSEQ_DISPATCHED = 0x01
  64. KSEQ_SUBSEQ = 0x02
  65. KSEQ_RECURSIVE = 0x04
  66. # Possible state values for rl_readline_state
  67. RL_STATE_NONE = 0x000000 # no state before first call
  68. RL_STATE_INITIALIZING = 0x000001 # initializing
  69. RL_STATE_INITIALIZED = 0x000002 # initialization done
  70. RL_STATE_TERMPREPPED = 0x000004 # terminal is prepped
  71. RL_STATE_READCMD = 0x000008 # reading a command key
  72. RL_STATE_METANEXT = 0x000010 # reading input after ESC
  73. RL_STATE_DISPATCHING = 0x000020 # dispatching to a command
  74. RL_STATE_MOREINPUT = 0x000040 # reading more input in a command function
  75. RL_STATE_ISEARCH = 0x000080 # doing incremental search
  76. RL_STATE_NSEARCH = 0x000100 # doing non-inc search
  77. RL_STATE_SEARCH = 0x000200 # doing a history search
  78. RL_STATE_NUMERICARG = 0x000400 # reading numeric argument
  79. RL_STATE_MACROINPUT = 0x000800 # getting input from a macro
  80. RL_STATE_MACRODEF = 0x001000 # defining keyboard macro
  81. RL_STATE_OVERWRITE = 0x002000 # overwrite mode
  82. RL_STATE_COMPLETING = 0x004000 # doing completion
  83. RL_STATE_SIGHANDLER = 0x008000 # in readline sighandler
  84. RL_STATE_UNDOING = 0x010000 # doing an undo
  85. RL_STATE_INPUTPENDING = 0x020000 # rl_execute_next called
  86. RL_STATE_TTYCSAVED = 0x040000 # tty special chars saved
  87. RL_STATE_CALLBACK = 0x080000 # using the callback interface
  88. RL_STATE_VIMOTION = 0x100000 # reading vi motion arg
  89. RL_STATE_MULTIKEY = 0x200000 # reading multiple-key command
  90. RL_STATE_VICMDONCE = 0x400000 # entered vi command mode at least once
  91. RL_STATE_DONE = 0x800000 # done accepted line
  92. NO_BELL = 0
  93. AUDIBLE_BELL = 1
  94. VISIBLE_BELL = 2
  95. # The actions that undo knows how to undo. Notice that UNDO_DELETE means
  96. # to insert some text, and UNDO_INSERT means to delete some text. I.e.,
  97. # the code tells undo what to undo, not how to undo it.
  98. UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END = 0,1,2,3
  99. # Definitions used when searching the line for characters.
  100. # NOTE: it is necessary that opposite directions are inverses
  101. FTO = 1 # forward to
  102. BTO = -1 # backward to
  103. FFIND = 2 # forward find
  104. BFIND = -2 # backward find
  105. # Possible values for the found_quote flags word used by the completion
  106. # functions. It says what kind of (shell-like) quoting we found anywhere
  107. # in the line.
  108. RL_QF_SINGLE_QUOTE = 0x01
  109. RL_QF_DOUBLE_QUOTE = 0x02
  110. RL_QF_BACKSLASH = 0x04
  111. RL_QF_OTHER_QUOTE = 0x08
  112. KEYMAP_SIZE = 257
  113. ANYOTHERKEY = KEYMAP_SIZE-1
  114. @hConsoleHandle = nil
  115. @MessageBeep = nil
  116. RL_IM_INSERT = 1
  117. RL_IM_OVERWRITE = 0
  118. RL_IM_DEFAULT = RL_IM_INSERT
  119. @no_mode = -1
  120. @vi_mode = 0
  121. @emacs_mode = 1
  122. ISFUNC = 0
  123. ISKMAP = 1
  124. ISMACR = 2
  125. HISTORY_WORD_DELIMITERS = " \t\n;&()|<>"
  126. HISTORY_QUOTE_CHARACTERS = "\"'`"
  127. RL_SEARCH_ISEARCH = 0x01 # incremental search
  128. RL_SEARCH_NSEARCH = 0x02 # non-incremental search
  129. RL_SEARCH_CSEARCH = 0x04 # intra-line char search
  130. # search flags
  131. SF_REVERSE = 0x01
  132. SF_FOUND = 0x02
  133. SF_FAILED = 0x04
  134. @slashify_in_quotes = "\\`\"$"
  135. @sigint_proc = nil
  136. @sigint_blocked = false
  137. @rl_prep_term_function = :rl_prep_terminal
  138. @rl_deprep_term_function = :rl_deprep_terminal
  139. @_rl_history_saved_point = -1
  140. @rl_max_kills = DEFAULT_MAX_KILLS
  141. @rl_kill_ring = nil
  142. @rl_kill_index = 0
  143. @rl_kill_ring_length = 0
  144. @pending_bytes = ''
  145. @stored_count = 0
  146. @_rl_isearch_terminators = nil
  147. @_rl_iscxt = nil
  148. @last_isearch_string = nil
  149. @last_isearch_string_len = 0
  150. @default_isearch_terminators = "\033\012"
  151. @_rl_history_preserve_point = false
  152. @terminal_prepped = false
  153. @otio = nil
  154. @msg_saved_prompt = false
  155. @_rl_nscxt = nil
  156. @noninc_search_string = nil
  157. @noninc_history_pos = 0
  158. @prev_line_found = nil
  159. rl_history_search_len = 0
  160. rl_history_search_pos = 0
  161. history_search_string = nil
  162. history_string_size = 0
  163. @_rl_tty_chars = Struct.new(:t_eol,:t_eol2,:t_erase,:t_werase,:t_kill,:t_reprint,:t_intr,:t_eof,
  164. :t_quit,:t_susp,:t_dsusp,:t_start,:t_stop,:t_lnext,:t_flush,:t_status).new
  165. @_rl_last_tty_chars = nil
  166. # Variables exported by this file.
  167. # The character that represents the start of a history expansion
  168. # request. This is usually `!'.
  169. @history_expansion_char = ?!
  170. # The character that invokes word substitution if found at the start of
  171. # a line. This is usually `^'.
  172. @history_subst_char = ?^
  173. # During tokenization, if this character is seen as the first character
  174. # of a word, then it, and all subsequent characters upto a newline are
  175. # ignored. For a Bourne shell, this should be '#'. Bash special cases
  176. # the interactive comment character to not be a comment delimiter.
  177. @history_comment_char = ?\0
  178. # The list of characters which inhibit the expansion of text if found
  179. # immediately following history_expansion_char.
  180. @history_no_expand_chars = " \t\n\r="
  181. # If set to a non-zero value, single quotes inhibit history expansion.
  182. # The default is 0.
  183. @history_quotes_inhibit_expansion = 0
  184. # Used to split words by history_tokenize_internal.
  185. @history_word_delimiters = HISTORY_WORD_DELIMITERS
  186. # If set, this points to a function that is called to verify that a
  187. # particular history expansion should be performed.
  188. @history_inhibit_expansion_function = nil
  189. @rl_event_hook = nil
  190. # The visible cursor position. If you print some text, adjust this.
  191. # NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
  192. # supporting multibyte characters, and an absolute cursor position when
  193. # in such a locale. This is an artifact of the donated multibyte support.
  194. # Care must be taken when modifying its value.
  195. @_rl_last_c_pos = 0
  196. @_rl_last_v_pos = 0
  197. @cpos_adjusted = false
  198. @cpos_buffer_position = 0
  199. # Number of lines currently on screen minus 1.
  200. @_rl_vis_botlin = 0
  201. # Variables used only in this file.
  202. # The last left edge of text that was displayed. This is used when
  203. # doing horizontal scrolling. It shifts in thirds of a screenwidth.
  204. @last_lmargin = 0
  205. # The line display buffers. One is the line currently displayed on
  206. # the screen. The other is the line about to be displayed.
  207. @visible_line = nil
  208. @invisible_line = nil
  209. # A buffer for `modeline' messages.
  210. @msg_buf = 0.chr * 128
  211. # Non-zero forces the redisplay even if we thought it was unnecessary.
  212. @forced_display = false
  213. # Default and initial buffer size. Can grow.
  214. @line_size = 1024
  215. # Variables to keep track of the expanded prompt string, which may
  216. # include invisible characters.
  217. @local_prompt = nil
  218. @local_prompt_prefix = nil
  219. @local_prompt_len = 0
  220. @prompt_visible_length = 0
  221. @prompt_prefix_length = 0
  222. # The number of invisible characters in the line currently being
  223. # displayed on the screen.
  224. @visible_wrap_offset = 0
  225. # The number of invisible characters in the prompt string. Static so it
  226. # can be shared between rl_redisplay and update_line
  227. @wrap_offset = 0
  228. @prompt_last_invisible = 0
  229. # The length (buffer offset) of the first line of the last (possibly
  230. # multi-line) buffer displayed on the screen.
  231. @visible_first_line_len = 0
  232. # Number of invisible characters on the first physical line of the prompt.
  233. # Only valid when the number of physical characters in the prompt exceeds
  234. # (or is equal to) _rl_screenwidth.
  235. @prompt_invis_chars_first_line = 0
  236. @prompt_last_screen_line = 0
  237. @prompt_physical_chars = 0
  238. # Variables to save and restore prompt and display information.
  239. # These are getting numerous enough that it's time to create a struct.
  240. @saved_local_prompt = nil
  241. @saved_local_prefix = nil
  242. @saved_last_invisible = 0
  243. @saved_visible_length = 0
  244. @saved_prefix_length = 0
  245. @saved_local_length = 0
  246. @saved_invis_chars_first_line = 0
  247. @saved_physical_chars = 0
  248. @inv_lbreaks = nil
  249. @vis_lbreaks = nil
  250. @_rl_wrapped_line = nil
  251. @term_buffer = nil
  252. @term_string_buffer = nil
  253. @tcap_initialized = false
  254. # While we are editing the history, this is the saved
  255. # version of the original line.
  256. @_rl_saved_line_for_history = nil
  257. # An array of HIST_ENTRY. This is where we store the history.
  258. @the_history = nil
  259. @history_base = 1
  260. # Non-zero means that we have enforced a limit on the amount of
  261. # history that we save.
  262. @history_stifled = false
  263. # If HISTORY_STIFLED is non-zero, then this is the maximum number of
  264. # entries to remember.
  265. @history_max_entries = 0
  266. @max_input_history = 0 # backwards compatibility
  267. # The current location of the interactive history pointer. Just makes
  268. # life easier for outside callers.
  269. @history_offset = 0
  270. # The number of strings currently stored in the history list.
  271. @history_length = 0
  272. @_rl_vi_last_command = 'i' # default `.' puts you in insert mode
  273. # Non-zero means enter insertion mode.
  274. @_rl_vi_doing_insert = 0
  275. # Command keys which do movement for xxx_to commands.
  276. @vi_motion = " hl^$0ftFT;,%wbeWBE|"
  277. # Keymap used for vi replace characters. Created dynamically since
  278. # rarely used.
  279. @vi_replace_map = nil
  280. # The number of characters inserted in the last replace operation.
  281. @vi_replace_count = 0
  282. # If non-zero, we have text inserted after a c[motion] command that put
  283. # us implicitly into insert mode. Some people want this text to be
  284. # attached to the command so that it is `redoable' with `.'.
  285. @vi_continued_command = false
  286. @vi_insert_buffer = nil
  287. @vi_insert_buffer_size = 0
  288. @_rl_vi_last_repeat = 1
  289. @_rl_vi_last_arg_sign = 1
  290. @_rl_vi_last_motion = 0
  291. @_rl_vi_last_search_char = 0
  292. @_rl_vi_last_replacement = 0
  293. @_rl_vi_last_key_before_insert = 0
  294. @vi_redoing = 0
  295. # Text modification commands. These are the `redoable' commands.
  296. @vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"
  297. # Arrays for the saved marks.
  298. @vi_mark_chars = Array.new(26,-1)
  299. @emacs_standard_keymap = {
  300. "\C-@" => :rl_set_mark ,
  301. "\C-a" => :rl_beg_of_line ,
  302. "\C-b" => :rl_backward_char ,
  303. "\C-d" => :rl_delete ,
  304. "\C-e" => :rl_end_of_line ,
  305. "\C-f" => :rl_forward_char ,
  306. "\C-g" => :rl_abort ,
  307. "\C-h" => :rl_rubout ,
  308. "\C-i" => :rl_complete ,
  309. "\C-j" => :rl_newline ,
  310. "\C-k" => :rl_kill_line ,
  311. "\C-l" => :rl_clear_screen ,
  312. "\C-m" => :rl_newline ,
  313. "\C-n" => :rl_get_next_history ,
  314. "\C-p" => :rl_get_previous_history ,
  315. "\C-q" => :rl_quoted_insert ,
  316. "\C-r" => :rl_reverse_search_history ,
  317. "\C-s" => :rl_forward_search_history ,
  318. "\C-t" => :rl_transpose_chars ,
  319. "\C-u" => :rl_unix_line_discard ,
  320. "\C-v" => :rl_quoted_insert ,
  321. "\C-w" => :rl_unix_word_rubout ,
  322. "\C-y" => :rl_yank ,
  323. "\C-]" => :rl_char_search ,
  324. "\C-_" => :rl_undo_command ,
  325. "\x7F" => :rl_rubout ,
  326. "\e\C-g" => :rl_abort ,
  327. "\e\C-h" => :rl_backward_kill_word ,
  328. "\e\C-i" => :rl_tab_insert ,
  329. "\e\C-j" => :rl_vi_editing_mode ,
  330. "\e\C-m" => :rl_vi_editing_mode ,
  331. "\e\C-r" => :rl_revert_line ,
  332. "\e\C-y" => :rl_yank_nth_arg ,
  333. "\e\C-[" => :rl_complete ,
  334. "\e\C-]" => :rl_backward_char_search ,
  335. "\e " => :rl_set_mark ,
  336. "\e#" => :rl_insert_comment ,
  337. "\e&" => :rl_tilde_expand ,
  338. "\e*" => :rl_insert_completions ,
  339. "\e-" => :rl_digit_argument ,
  340. "\e." => :rl_yank_last_arg ,
  341. "\e0" => :rl_digit_argument ,
  342. "\e1" => :rl_digit_argument ,
  343. "\e2" => :rl_digit_argument ,
  344. "\e3" => :rl_digit_argument ,
  345. "\e4" => :rl_digit_argument ,
  346. "\e5" => :rl_digit_argument ,
  347. "\e6" => :rl_digit_argument ,
  348. "\e7" => :rl_digit_argument ,
  349. "\e8" => :rl_digit_argument ,
  350. "\e9" => :rl_digit_argument ,
  351. "\e<" => :rl_beginning_of_history ,
  352. "\e=" => :rl_possible_completions ,
  353. "\e>" => :rl_end_of_history ,
  354. "\e?" => :rl_possible_completions ,
  355. "\eB" => :rl_backward_word ,
  356. "\eC" => :rl_capitalize_word ,
  357. "\eD" => :rl_kill_word ,
  358. "\eF" => :rl_forward_word ,
  359. "\eL" => :rl_downcase_word ,
  360. "\eN" => :rl_noninc_forward_search ,
  361. "\eP" => :rl_noninc_reverse_search ,
  362. "\eR" => :rl_revert_line ,
  363. "\eT" => :rl_transpose_words ,
  364. "\eU" => :rl_upcase_word ,
  365. "\eY" => :rl_yank_pop ,
  366. "\e\\" => :rl_delete_horizontal_space ,
  367. "\e_" => :rl_yank_last_arg ,
  368. "\eb" => :rl_backward_word ,
  369. "\ec" => :rl_capitalize_word ,
  370. "\ed" => :rl_kill_word ,
  371. "\ef" => :rl_forward_word ,
  372. "\el" => :rl_downcase_word ,
  373. "\en" => :rl_noninc_forward_search ,
  374. "\ep" => :rl_noninc_reverse_search ,
  375. "\er" => :rl_revert_line ,
  376. "\et" => :rl_transpose_words ,
  377. "\eu" => :rl_upcase_word ,
  378. "\ey" => :rl_yank_pop ,
  379. "\e~" => :rl_tilde_expand ,
  380. "\377" => :rl_backward_kill_word ,
  381. "\C-x\C-g" => :rl_abort ,
  382. "\C-x\C-r" => :rl_re_read_init_file ,
  383. "\C-x\C-u" => :rl_undo_command ,
  384. "\C-x\C-x" => :rl_exchange_point_and_mark ,
  385. "\C-x(" => :rl_start_kbd_macro ,
  386. "\C-x)" => :rl_end_kbd_macro ,
  387. "\C-xE" => :rl_call_last_kbd_macro ,
  388. "\C-xe" => :rl_call_last_kbd_macro ,
  389. "\C-x\x7F" => :rl_backward_kill_line
  390. }
  391. @vi_movement_keymap = {
  392. "\C-d" => :rl_vi_eof_maybe ,
  393. "\C-e" => :rl_emacs_editing_mode ,
  394. "\C-g" => :rl_abort ,
  395. "\C-h" => :rl_backward_char ,
  396. "\C-j" => :rl_newline ,
  397. "\C-k" => :rl_kill_line ,
  398. "\C-l" => :rl_clear_screen ,
  399. "\C-m" => :rl_newline ,
  400. "\C-n" => :rl_get_next_history ,
  401. "\C-p" => :rl_get_previous_history ,
  402. "\C-q" => :rl_quoted_insert ,
  403. "\C-r" => :rl_reverse_search_history ,
  404. "\C-s" => :rl_forward_search_history ,
  405. "\C-t" => :rl_transpose_chars ,
  406. "\C-u" => :rl_unix_line_discard ,
  407. "\C-v" => :rl_quoted_insert ,
  408. "\C-w" => :rl_unix_word_rubout ,
  409. "\C-y" => :rl_yank ,
  410. "\C-_" => :rl_vi_undo ,
  411. " " => :rl_forward_char ,
  412. "#" => :rl_insert_comment ,
  413. "$" => :rl_end_of_line ,
  414. "%" => :rl_vi_match ,
  415. "&" => :rl_vi_tilde_expand ,
  416. "*" => :rl_vi_complete ,
  417. "+" => :rl_get_next_history ,
  418. "," => :rl_vi_char_search ,
  419. "-" => :rl_get_previous_history ,
  420. "." => :rl_vi_redo ,
  421. "/" => :rl_vi_search ,
  422. "0" => :rl_beg_of_line ,
  423. "1" => :rl_vi_arg_digit ,
  424. "2" => :rl_vi_arg_digit ,
  425. "3" => :rl_vi_arg_digit ,
  426. "4" => :rl_vi_arg_digit ,
  427. "5" => :rl_vi_arg_digit ,
  428. "6" => :rl_vi_arg_digit ,
  429. "7" => :rl_vi_arg_digit ,
  430. "8" => :rl_vi_arg_digit ,
  431. "9" => :rl_vi_arg_digit ,
  432. "" => :rl_vi_char_search ,
  433. "=" => :rl_vi_complete ,
  434. "?" => :rl_vi_search ,
  435. "A" => :rl_vi_append_eol ,
  436. "B" => :rl_vi_prev_word ,
  437. "C" => :rl_vi_change_to ,
  438. "D" => :rl_vi_delete_to ,
  439. "E" => :rl_vi_end_word ,
  440. "F" => :rl_vi_char_search ,
  441. "G" => :rl_vi_fetch_history ,
  442. "I" => :rl_vi_insert_beg ,
  443. "N" => :rl_vi_search_again ,
  444. "P" => :rl_vi_put ,
  445. "R" => :rl_vi_replace ,
  446. "S" => :rl_vi_subst ,
  447. "T" => :rl_vi_char_search ,
  448. "U" => :rl_revert_line ,
  449. "W" => :rl_vi_next_word ,
  450. "X" => :rl_vi_rubout ,
  451. "Y" => :rl_vi_yank_to ,
  452. "\\" => :rl_vi_complete ,
  453. "^" => :rl_vi_first_print ,
  454. "_" => :rl_vi_yank_arg ,
  455. "`" => :rl_vi_goto_mark ,
  456. "a" => :rl_vi_append_mode ,
  457. "b" => :rl_vi_prev_word ,
  458. "c" => :rl_vi_change_to ,
  459. "d" => :rl_vi_delete_to ,
  460. "e" => :rl_vi_end_word ,
  461. "f" => :rl_vi_char_search ,
  462. "h" => :rl_backward_char ,
  463. "i" => :rl_vi_insertion_mode ,
  464. "j" => :rl_get_next_history ,
  465. "k" => :rl_get_previous_history ,
  466. "l" => :rl_forward_char ,
  467. "m" => :rl_vi_set_mark ,
  468. "n" => :rl_vi_search_again ,
  469. "p" => :rl_vi_put ,
  470. "r" => :rl_vi_change_char ,
  471. "s" => :rl_vi_subst ,
  472. "t" => :rl_vi_char_search ,
  473. "u" => :rl_vi_undo ,
  474. "w" => :rl_vi_next_word ,
  475. "x" => :rl_vi_delete ,
  476. "y" => :rl_vi_yank_to ,
  477. "|" => :rl_vi_column ,
  478. "~" => :rl_vi_change_case
  479. }
  480. @vi_insertion_keymap = {
  481. "\C-a" => :rl_insert ,
  482. "\C-b" => :rl_insert ,
  483. "\C-c" => :rl_insert ,
  484. "\C-d" => :rl_vi_eof_maybe ,
  485. "\C-e" => :rl_insert ,
  486. "\C-f" => :rl_insert ,
  487. "\C-g" => :rl_insert ,
  488. "\C-h" => :rl_rubout ,
  489. "\C-i" => :rl_complete ,
  490. "\C-j" => :rl_newline ,
  491. "\C-k" => :rl_insert ,
  492. "\C-l" => :rl_insert ,
  493. "\C-m" => :rl_newline ,
  494. "\C-n" => :rl_insert ,
  495. "\C-o" => :rl_insert ,
  496. "\C-p" => :rl_insert ,
  497. "\C-q" => :rl_insert ,
  498. "\C-r" => :rl_reverse_search_history ,
  499. "\C-s" => :rl_forward_search_history ,
  500. "\C-t" => :rl_transpose_chars ,
  501. "\C-u" => :rl_unix_line_discard ,
  502. "\C-v" => :rl_quoted_insert ,
  503. "\C-w" => :rl_unix_word_rubout ,
  504. "\C-x" => :rl_insert ,
  505. "\C-y" => :rl_yank ,
  506. "\C-z" => :rl_insert ,
  507. "\C-[" => :rl_vi_movement_mode ,
  508. "\C-\\" => :rl_insert ,
  509. "\C-]" => :rl_insert ,
  510. "\C-^" => :rl_insert ,
  511. "\C-_" => :rl_vi_undo ,
  512. "\x7F" => :rl_rubout
  513. }
  514. @rl_library_version = RL_LIBRARY_VERSION
  515. @rl_readline_version = RL_READLINE_VERSION
  516. @rl_readline_name = "other"
  517. @rl_getc_function = :rl_getc
  518. # Non-zero tells rl_delete_text and rl_insert_text to not add to
  519. # the undo list.
  520. @_rl_doing_an_undo = false
  521. # How many unclosed undo groups we currently have.
  522. @_rl_undo_group_level = 0
  523. # The current undo list for THE_LINE.
  524. @rl_undo_list = nil
  525. # Application-specific redisplay function.
  526. @rl_redisplay_function = :rl_redisplay
  527. # Global variables declared here.
  528. # What YOU turn on when you have handled all redisplay yourself.
  529. @rl_display_fixed = false
  530. @_rl_suppress_redisplay = 0
  531. @_rl_want_redisplay = false
  532. # The stuff that gets printed out before the actual text of the line.
  533. # This is usually pointing to rl_prompt.
  534. @rl_display_prompt = nil
  535. # True if this is `real' readline as opposed to some stub substitute.
  536. @rl_gnu_readline_p = true
  537. for i in 32 .. 255
  538. @emacs_standard_keymap[i.chr] = :rl_insert unless @emacs_standard_keymap[i.chr]
  539. @vi_insertion_keymap[i.chr] = :rl_insert unless @vi_insertion_keymap[i.chr]
  540. end
  541. # A pointer to the keymap that is currently in use.
  542. # By default, it is the standard emacs keymap.
  543. @_rl_keymap = @emacs_standard_keymap
  544. # The current style of editing.
  545. @rl_editing_mode = @emacs_mode
  546. # The current insert mode: input (the default) or overwrite
  547. @rl_insert_mode = RL_IM_DEFAULT
  548. # Non-zero if we called this function from _rl_dispatch(). It's present
  549. # so functions can find out whether they were called from a key binding
  550. # or directly from an application.
  551. @rl_dispatching = false
  552. # Non-zero if the previous command was a kill command.
  553. @_rl_last_command_was_kill = false
  554. # The current value of the numeric argument specified by the user.
  555. @rl_numeric_arg = 1
  556. # Non-zero if an argument was typed.
  557. @rl_explicit_arg = false
  558. # Temporary value used while generating the argument.
  559. @rl_arg_sign = 1
  560. # Non-zero means we have been called at least once before.
  561. @rl_initialized = false
  562. # Flags word encapsulating the current readline state.
  563. @rl_readline_state = RL_STATE_NONE
  564. # The current offset in the current input line.
  565. @rl_point = 0
  566. # Mark in the current input line.
  567. @rl_mark = 0
  568. # Length of the current input line.
  569. @rl_end = 0
  570. # Make this non-zero to return the current input_line.
  571. @rl_done = false
  572. # The last function executed by readline.
  573. @rl_last_func = nil
  574. # Top level environment for readline_internal ().
  575. @readline_top_level = nil
  576. # The streams we interact with.
  577. @_rl_in_stream = nil
  578. @_rl_out_stream = nil
  579. # The names of the streams that we do input and output to.
  580. @rl_instream = nil
  581. @rl_outstream = nil
  582. @pop_index = 0
  583. @push_index = 0
  584. @ibuffer = 0.chr * 512
  585. @ibuffer_len = @ibuffer.length - 1
  586. # Non-zero means echo characters as they are read. Defaults to no echo
  587. # set to 1 if there is a controlling terminal, we can get its attributes,
  588. # and the attributes include `echo'. Look at rltty.c:prepare_terminal_settings
  589. # for the code that sets it.
  590. @readline_echoing_p = false
  591. # Current prompt.
  592. @rl_prompt = nil
  593. @rl_visible_prompt_length = 0
  594. # Set to non-zero by calling application if it has already printed rl_prompt
  595. # and does not want readline to do it the first time.
  596. @rl_already_prompted = false
  597. # The number of characters read in order to type this complete command.
  598. @rl_key_sequence_length = 0
  599. # If non-zero, then this is the address of a function to call just
  600. # before readline_internal_setup () prints the first prompt.
  601. @rl_startup_hook = nil
  602. # If non-zero, this is the address of a function to call just before
  603. # readline_internal_setup () returns and readline_internal starts
  604. # reading input characters.
  605. @rl_pre_input_hook = nil
  606. # The character that can generate an EOF. Really read from
  607. # the terminal driver... just defaulted here.
  608. @_rl_eof_char = "\cD"
  609. # Non-zero makes this the next keystroke to read.
  610. @rl_pending_input = 0
  611. # Pointer to a useful terminal name.
  612. @rl_terminal_name = nil
  613. # Non-zero means to always use horizontal scrolling in line display.
  614. @_rl_horizontal_scroll_mode = false
  615. # Non-zero means to display an asterisk at the starts of history lines
  616. # which have been modified.
  617. @_rl_mark_modified_lines = false
  618. # The style of `bell' notification preferred. This can be set to NO_BELL,
  619. # AUDIBLE_BELL, or VISIBLE_BELL.
  620. @_rl_bell_preference = AUDIBLE_BELL
  621. # String inserted into the line by rl_insert_comment ().
  622. @_rl_comment_begin = nil
  623. # Keymap holding the function currently being executed.
  624. @rl_executing_keymap = nil
  625. # Keymap we're currently using to dispatch.
  626. @_rl_dispatching_keymap = nil
  627. # Non-zero means to erase entire line, including prompt, on empty input lines.
  628. @rl_erase_empty_line = false
  629. # Non-zero means to read only this many characters rather than up to a
  630. # character bound to accept-line.
  631. @rl_num_chars_to_read = 0
  632. # Line buffer and maintenence.
  633. @rl_line_buffer = nil
  634. # Key sequence `contexts'
  635. @_rl_kscxt = nil
  636. # Non-zero means do not parse any lines other than comments and
  637. # parser directives.
  638. @_rl_parsing_conditionalized_out = false
  639. # Non-zero means to convert characters with the meta bit set to
  640. # escape-prefixed characters so we can indirect through
  641. # emacs_meta_keymap or vi_escape_keymap.
  642. @_rl_convert_meta_chars_to_ascii = true
  643. # Non-zero means to output characters with the meta bit set directly
  644. # rather than as a meta-prefixed escape sequence.
  645. @_rl_output_meta_chars = false
  646. # Non-zero means to look at the termios special characters and bind
  647. # them to equivalent readline functions at startup.
  648. @_rl_bind_stty_chars = true
  649. @rl_completion_display_matches_hook = nil
  650. XOK = 1
  651. @_rl_term_clreol = nil
  652. @_rl_term_clrpag = nil
  653. @_rl_term_cr = nil
  654. @_rl_term_backspace = nil
  655. @_rl_term_goto = nil
  656. @_rl_term_pc = nil
  657. # Non-zero if we determine that the terminal can do character insertion.
  658. @_rl_terminal_can_insert = false
  659. # How to insert characters.
  660. @_rl_term_im = nil
  661. @_rl_term_ei = nil
  662. @_rl_term_ic = nil
  663. @_rl_term_ip = nil
  664. @_rl_term_IC = nil
  665. # How to delete characters.
  666. @_rl_term_dc = nil
  667. @_rl_term_DC = nil
  668. @_rl_term_forward_char = nil
  669. # How to go up a line.
  670. @_rl_term_up = nil
  671. # A visible bell; char if the terminal can be made to flash the screen.
  672. @_rl_visible_bell = nil
  673. # Non-zero means the terminal can auto-wrap lines.
  674. @_rl_term_autowrap = true
  675. # Non-zero means that this terminal has a meta key.
  676. @term_has_meta = 0
  677. # The sequences to write to turn on and off the meta key, if this
  678. # terminal has one.
  679. @_rl_term_mm = nil
  680. @_rl_term_mo = nil
  681. # The key sequences output by the arrow keys, if this terminal has any.
  682. @_rl_term_ku = nil
  683. @_rl_term_kd = nil
  684. @_rl_term_kr = nil
  685. @_rl_term_kl = nil
  686. # How to initialize and reset the arrow keys, if this terminal has any.
  687. @_rl_term_ks = nil
  688. @_rl_term_ke = nil
  689. # The key sequences sent by the Home and End keys, if any.
  690. @_rl_term_kh = nil
  691. @_rl_term_kH = nil
  692. @_rl_term_at7 = nil
  693. # Delete key
  694. @_rl_term_kD = nil
  695. # Insert key
  696. @_rl_term_kI = nil
  697. # Cursor control
  698. @_rl_term_vs = nil # very visible
  699. @_rl_term_ve = nil # normal
  700. # Variables that hold the screen dimensions, used by the display code.
  701. @_rl_screenwidth = @_rl_screenheight = @_rl_screenchars = 0
  702. # Non-zero means the user wants to enable the keypad.
  703. @_rl_enable_keypad = false
  704. # Non-zero means the user wants to enable a meta key.
  705. @_rl_enable_meta = true
  706. # ****************************************************************
  707. #
  708. # Completion matching, from readline's point of view.
  709. #
  710. # ****************************************************************
  711. # Variables known only to the readline library.
  712. # If non-zero, non-unique completions always show the list of matches.
  713. @_rl_complete_show_all = false
  714. # If non-zero, non-unique completions show the list of matches, unless it
  715. # is not possible to do partial completion and modify the line.
  716. @_rl_complete_show_unmodified = false
  717. # If non-zero, completed directory names have a slash appended.
  718. @_rl_complete_mark_directories = true
  719. # If non-zero, the symlinked directory completion behavior introduced in
  720. # readline-4.2a is disabled, and symlinks that point to directories have
  721. # a slash appended (subject to the value of _rl_complete_mark_directories).
  722. # This is user-settable via the mark-symlinked-directories variable.
  723. @_rl_complete_mark_symlink_dirs = false
  724. # If non-zero, completions are printed horizontally in alphabetical order,
  725. # like `ls -x'.
  726. @_rl_print_completions_horizontally = false
  727. @_rl_completion_case_fold = false
  728. # If non-zero, don't match hidden files (filenames beginning with a `.' on
  729. # Unix) when doing filename completion.
  730. @_rl_match_hidden_files = true
  731. # Global variables available to applications using readline.
  732. # Non-zero means add an additional character to each filename displayed
  733. # during listing completion iff rl_filename_completion_desired which helps
  734. # to indicate the type of file being listed.
  735. @rl_visible_stats = false
  736. # If non-zero, then this is the address of a function to call when
  737. # completing on a directory name. The function is called with
  738. # the address of a string (the current directory name) as an arg.
  739. @rl_directory_completion_hook = nil
  740. @rl_directory_rewrite_hook = nil
  741. # Non-zero means readline completion functions perform tilde expansion.
  742. @rl_complete_with_tilde_expansion = false
  743. # Pointer to the generator function for completion_matches ().
  744. # NULL means to use rl_filename_completion_function (), the default filename
  745. # completer.
  746. @rl_completion_entry_function = nil
  747. # Pointer to alternative function to create matches.
  748. # Function is called with TEXT, START, and END.
  749. # START and END are indices in RL_LINE_BUFFER saying what the boundaries
  750. # of TEXT are.
  751. # If this function exists and returns NULL then call the value of
  752. # rl_completion_entry_function to try to match, otherwise use the
  753. # array of strings returned.
  754. @rl_attempted_completion_function = nil
  755. # Non-zero means to suppress normal filename completion after the
  756. # user-specified completion function has been called.
  757. @rl_attempted_completion_over = false
  758. # Set to a character indicating the type of completion being performed
  759. # by rl_complete_internal, available for use by application completion
  760. # functions.
  761. @rl_completion_type = 0
  762. # Up to this many items will be displayed in response to a
  763. # possible-completions call. After that, we ask the user if
  764. # she is sure she wants to see them all. A negative value means
  765. # don't ask.
  766. @rl_completion_query_items = 100
  767. @_rl_page_completions = 1
  768. # The basic list of characters that signal a break between words for the
  769. # completer routine. The contents of this variable is what breaks words
  770. # in the shell, i.e. " \t\n\"\\'`@$><="
  771. @rl_basic_word_break_characters = " \t\n\"\\'`@$><=|&{(" # })
  772. # List of basic quoting characters.
  773. @rl_basic_quote_characters = "\"'"
  774. # The list of characters that signal a break between words for
  775. # rl_complete_internal. The default list is the contents of
  776. # rl_basic_word_break_characters.
  777. @rl_completer_word_break_characters = nil
  778. # Hook function to allow an application to set the completion word
  779. # break characters before readline breaks up the line. Allows
  780. # position-dependent word break characters.
  781. @rl_completion_word_break_hook = nil
  782. # List of characters which can be used to quote a substring of the line.
  783. # Completion occurs on the entire substring, and within the substring
  784. # rl_completer_word_break_characters are treated as any other character,
  785. # unless they also appear within this list.
  786. @rl_completer_quote_characters = nil
  787. # List of characters that should be quoted in filenames by the completer.
  788. @rl_filename_quote_characters = nil
  789. # List of characters that are word break characters, but should be left
  790. # in TEXT when it is passed to the completion function. The shell uses
  791. # this to help determine what kind of completing to do.
  792. @rl_special_prefixes = nil
  793. # If non-zero, then disallow duplicates in the matches.
  794. @rl_ignore_completion_duplicates = true
  795. # Non-zero means that the results of the matches are to be treated
  796. # as filenames. This is ALWAYS zero on entry, and can only be changed
  797. # within a completion entry finder function.
  798. @rl_filename_completion_desired = false
  799. # Non-zero means that the results of the matches are to be quoted using
  800. # double quotes (or an application-specific quoting mechanism) if the
  801. # filename contains any characters in rl_filename_quote_chars. This is
  802. # ALWAYS non-zero on entry, and can only be changed within a completion
  803. # entry finder function.
  804. @rl_filename_quoting_desired = true
  805. # This function, if defined, is called by the completer when real
  806. # filename completion is done, after all the matching names have been
  807. # generated. It is passed a (char**) known as matches in the code below.
  808. # It consists of a NULL-terminated array of pointers to potential
  809. # matching strings. The 1st element (matches[0]) is the maximal
  810. # substring that is common to all matches. This function can re-arrange
  811. # the list of matches as required, but all elements of the array must be
  812. # free()'d if they are deleted. The main intent of this function is
  813. # to implement FIGNORE a la SunOS csh.
  814. @rl_ignore_some_completions_function = nil
  815. # Set to a function to quote a filename in an application-specific fashion.
  816. # Called with the text to quote, the type of match found (single or multiple)
  817. # and a pointer to the quoting character to be used, which the function can
  818. # reset if desired.
  819. #rl_filename_quoting_function = rl_quote_filename
  820. # Function to call to remove quoting characters from a filename. Called
  821. # before completion is attempted, so the embedded quotes do not interfere
  822. # with matching names in the file system. Readline doesn't do anything
  823. # with this it's set only by applications.
  824. @rl_filename_dequoting_function = nil
  825. # Function to call to decide whether or not a word break character is
  826. # quoted. If a character is quoted, it does not break words for the
  827. # completer.
  828. @rl_char_is_quoted_p = nil
  829. # If non-zero, the completion functions don't append anything except a
  830. # possible closing quote. This is set to 0 by rl_complete_internal and
  831. # may be changed by an application-specific completion function.
  832. @rl_completion_suppress_append = false
  833. # Character appended to completed words when at the end of the line. The
  834. # default is a space.
  835. @rl_completion_append_character = ' '
  836. # If non-zero, the completion functions don't append any closing quote.
  837. # This is set to 0 by rl_complete_internal and may be changed by an
  838. # application-specific completion function.
  839. @rl_completion_suppress_quote = false
  840. # Set to any quote character readline thinks it finds before any application
  841. # completion function is called.
  842. @rl_completion_quote_character = 0
  843. # Set to a non-zero value if readline found quoting anywhere in the word to
  844. # be completed set before any application completion function is called.
  845. @rl_completion_found_quote = false
  846. # If non-zero, a slash will be appended to completed filenames that are
  847. # symbolic links to directory names, subject to the value of the
  848. # mark-directories variable (which is user-settable). This exists so
  849. # that application completion functions can override the user's preference
  850. # (set via the mark-symlinked-directories variable) if appropriate.
  851. # It's set to the value of _rl_complete_mark_symlink_dirs in
  852. # rl_complete_internal before any application-specific completion
  853. # function is called, so without that function doing anything, the user's
  854. # preferences are honored.
  855. @rl_completion_mark_symlink_dirs = false
  856. # If non-zero, inhibit completion (temporarily).
  857. @rl_inhibit_completion = false
  858. # Variables local to this file.
  859. # Local variable states what happened during the last completion attempt.
  860. @completion_changed_buffer = nil
  861. # Non-zero means treat 0200 bit in terminal input as Meta bit.
  862. @_rl_meta_flag = false
  863. # Stack of previous values of parsing_conditionalized_out.
  864. @if_stack = []
  865. @if_stack_depth = 0
  866. # The last key bindings file read.
  867. @last_readline_init_file = nil
  868. # The file we're currently reading key bindings from.
  869. @current_readline_init_file = nil
  870. @current_readline_init_include_level = 0
  871. @current_readline_init_lineno = 0
  872. ENV["HOME"] ||= ENV["HOMEDRIVE"]+ENV["HOMEPATH"]
  873. @directory = nil
  874. @filename = nil
  875. @dirname = nil
  876. @users_dirname = nil
  877. @filename_len = 0
  878. attr_accessor :rl_attempted_completion_function,:rl_deprep_term_function,
  879. :rl_event_hook,:rl_attempted_completion_over,:rl_basic_quote_characters,
  880. :rl_basic_word_break_characters,:rl_completer_quote_characters,
  881. :rl_completer_word_break_characters,:rl_completion_append_character,
  882. :rl_filename_quote_characters,:rl_instream,:rl_library_version,:rl_outstream,
  883. :rl_readline_name,:history_length,:history_base
  884. module_function
  885. # Okay, now we write the entry_function for filename completion. In the
  886. # general case. Note that completion in the shell is a little different
  887. # because of all the pathnames that must be followed when looking up the
  888. # completion for a command.
  889. def rl_filename_completion_function(text, state)
  890. # If we don't have any state, then do some initialization.
  891. if (state == 0)
  892. # If we were interrupted before closing the directory or reading
  893. #all of its contents, close it.
  894. if(@directory)
  895. @directory.close
  896. @directory = nil
  897. end
  898. text.delete!(0.chr)
  899. @filename = text.dup
  900. if text.length == 0
  901. text = "."
  902. end
  903. @dirname = File.dirname(text)
  904. # We aren't done yet. We also support the "~user" syntax.
  905. # Save the version of the directory that the user typed.
  906. @users_dirname = @dirname.dup
  907. if (@dirname[0] == ?~)
  908. @dirname = File.expand_path(@dirname)
  909. end
  910. # The directory completion hook should perform any necessary
  911. # dequoting.
  912. if (@rl_directory_completion_hook && send(rl_directory_completion_hook,@dirname))
  913. @users_dirname = @dirname.dup
  914. elsif (@rl_completion_found_quote && @rl_filename_dequoting_function)
  915. # delete single and double quotes
  916. @temp = send(@rl_filename_dequoting_function,@users_dirname, @rl_completion_quote_character)
  917. @users_dirname = temp
  918. end
  919. @directory = Dir.new(@dirname)
  920. # Now dequote a non-null filename.
  921. if (@filename && @filename.length>0 && @rl_completion_found_quote && @rl_filename_dequoting_function)
  922. # delete single and double quotes
  923. temp = send(@rl_filename_dequoting_function,@filename, @rl_completion_quote_character)
  924. @filename = temp
  925. end
  926. @filename_len = @filename.length
  927. @rl_filename_completion_desired = true
  928. end
  929. # At this point we should entertain the possibility of hacking wildcarded
  930. # filenames, like /usr/man/man<WILD>/te<TAB>. If the directory name
  931. # contains globbing characters, then build an array of directories, and
  932. # then map over that list while completing.
  933. # *** UNIMPLEMENTED ***
  934. # Now that we have some state, we can read the directory.
  935. entry = nil
  936. while(@directory && (entry = @directory.read))
  937. d_name = entry
  938. # Special case for no filename. If the user has disabled the
  939. # `match-hidden-files' variable, skip filenames beginning with `.'.
  940. #All other entries except "." and ".." match.
  941. if (@filename_len == 0)
  942. if (!@_rl_match_hidden_files && d_name[0]==?.)
  943. next
  944. end
  945. if (d_name != '.' && d_name != '..')
  946. break
  947. end
  948. else
  949. # Otherwise, if these match up to the length of filename, then
  950. # it is a match.
  951. if (@_rl_completion_case_fold)
  952. break if d_name =~ /^#{Regexp.escape(@filename)}/i
  953. else
  954. break if d_name =~ /^#{Regexp.escape(@filename)}/
  955. end
  956. end
  957. end
  958. if entry.nil?
  959. if @directory
  960. @directory.close
  961. @directory = nil
  962. end
  963. @dirname = nil
  964. @filename = nil
  965. @users_dirname = nil
  966. return nil
  967. else
  968. if (@dirname != '.')
  969. if (@rl_complete_with_tilde_expansion && @users_dirname[0] == ?~)
  970. temp = @dirname
  971. if(temp[-1] != ?/)
  972. temp += '/'
  973. end
  974. else
  975. temp = @users_dirname
  976. if(temp[-1] != ?/)
  977. temp += '/'
  978. end
  979. end
  980. temp += entry
  981. else
  982. temp = entry.dup
  983. end
  984. return (temp)
  985. end
  986. end
  987. # A completion function for usernames.
  988. # TEXT contains a partial username preceded by a random
  989. # character (usually `~').
  990. def rl_username_completion_function(text, state)
  991. return nil if RUBY_PLATFORM =~ /mswin|mingw/
  992. if (state == 0)
  993. first_char = text[0]
  994. first_char_loc = (text[0] == ?~ ? 1 : 0)
  995. username = text[first_char_loc..-1]
  996. namelen = username.length
  997. Etc.setpwent()
  998. end
  999. while (entry = Etc.getpwent())
  1000. # Null usernames should result in all users as possible completions.
  1001. break if (namelen == 0 || entry.name =~ /^#{username}/ )
  1002. end
  1003. if entry.nil?
  1004. Etc.endpwent()
  1005. return nil
  1006. else
  1007. value = text.dup
  1008. value[first_char_loc..-1] = entry.name
  1009. if (first_char == ?~)
  1010. @rl_filename_completion_desired = true
  1011. end
  1012. return (value)
  1013. end
  1014. end
  1015. #*************************************************************
  1016. #
  1017. # Application-callable completion match generator functions
  1018. #
  1019. #*************************************************************
  1020. # Return an array of (char *) which is a list of completions for TEXT.
  1021. # If there are no completions, return a NULL pointer.
  1022. # The first entry in the returned array is the substitution for TEXT.
  1023. # The remaining entries are the possible completions.
  1024. # The array is terminated with a NULL pointer.
  1025. #
  1026. # ENTRY_FUNCTION is a function of two args, and returns a (char *).
  1027. # The first argument is TEXT.
  1028. # The second is a state argument it should be zero on the first call, and
  1029. # non-zero on subsequent calls. It returns a NULL pointer to the caller
  1030. # when there are no more matches.
  1031. #
  1032. def rl_completion_matches(text, entry_function)
  1033. matches = 0
  1034. match_list_size = 10
  1035. match_list = []
  1036. match_list[1] = nil
  1037. while (string = send(entry_function, text, matches))
  1038. match_list[matches+=1] = string
  1039. match_list[matches+1] = nil
  1040. end
  1041. # If there were any matches, then look through them finding out the
  1042. # lowest common denominator. That then becomes match_list[0].
  1043. if (matches!=0)
  1044. compute_lcd_of_matches(match_list, matches, text)
  1045. else # There were no matches.
  1046. match_list = nil
  1047. end
  1048. return (match_list)
  1049. end
  1050. def _rl_to_lower(char)
  1051. char.nil? ? nil : char.chr.downcase
  1052. end
  1053. # Find the common prefix of the list of matches, and put it into
  1054. # matches[0].
  1055. def compute_lcd_of_matches(match_list, matches, text)
  1056. # If only one match, just use that. Otherwise, compare each
  1057. # member of the list with the next, finding out where they
  1058. # stop matching.
  1059. if (matches == 1)
  1060. match_list[0] = match_list[1]
  1061. match_list[1] = nil
  1062. return 1
  1063. end
  1064. i = 1
  1065. low = 100000
  1066. while(i<matches)
  1067. if (@_rl_completion_case_fold)
  1068. si = 0
  1069. while((c1 = _rl_to_lower(match_list[i][si])) &&
  1070. (c2 = _rl_to_lower(match_list[i + 1][si])))
  1071. if !@rl_byte_oriented
  1072. if(!_rl_compare_chars(match_list[i],si,match_list[i+1],si))
  1073. break
  1074. elsif ((v = _rl_get_char_len(match_list[i][si..-1])) > 1)
  1075. si += v - 1
  1076. end
  1077. else
  1078. break if (c1 != c2)
  1079. end
  1080. si += 1
  1081. end
  1082. else
  1083. si = 0
  1084. while((c1 = match_list[i][si]) &&
  1085. (c2 = match_list[i + 1][si]))
  1086. if !@rl_byte_oriented
  1087. if(!_rl_compare_chars(match_list[i],si,match_list[i+1],si))
  1088. break
  1089. elsif ((v = _rl_get_char_len(match_list[i][si..-1])) > 1)
  1090. si += v - 1
  1091. end
  1092. else
  1093. break if (c1 != c2)
  1094. end
  1095. si += 1
  1096. end
  1097. end
  1098. if (low > si)
  1099. low = si
  1100. end
  1101. i += 1
  1102. end
  1103. # If there were multiple matches, but none matched up to even the
  1104. # first character, and the user typed something, use that as the
  1105. # value of matches[0].
  1106. if (low == 0 && text && text.length>0 )
  1107. match_list[0] = text.dup
  1108. else
  1109. # XXX - this might need changes in the presence of multibyte chars
  1110. # If we are ignoring case, try to preserve the case of the string
  1111. # the user typed in the face of multiple matches differing in case.
  1112. if (@_rl_completion_case_fold)
  1113. # We're making an assumption here:
  1114. # IF we're completing filenames AND
  1115. # the application has defined a filename dequoting function AND
  1116. # we found a quote character AND
  1117. # the application has requested filename quoting
  1118. # THEN
  1119. # we assume that TEXT was dequoted before checking against
  1120. # the file system and needs to be dequoted here before we
  1121. # check against the list of matches
  1122. # FI
  1123. if (@rl_filename_completion_desired &&
  1124. @rl_filename_dequoting_function &&
  1125. @rl_completion_found_quote &&
  1126. @rl_filename_quoting_desired)
  1127. dtext = send(@rl_filename_dequoting_function,text, @rl_completion_quote_character)
  1128. text = dtext
  1129. end
  1130. # sort the list to get consistent answers.
  1131. match_list = [match_list[0]] + match_list[1..-1].sort
  1132. si = text.length
  1133. if (si <= low)
  1134. for i in 1 .. matches
  1135. if match_list[i][0,si] == text
  1136. match_list[0] = match_list[i][0,low]
  1137. break
  1138. end
  1139. # no casematch, use first entry
  1140. if (i > matches)
  1141. match_list[0] = match_list[1][0,low]
  1142. end
  1143. end
  1144. else
  1145. # otherwise, just use the text the user typed.
  1146. match_list[0] = text[0,low]
  1147. end
  1148. else
  1149. match_list[0] = match_list[1][0,low]
  1150. end
  1151. end
  1152. return matches
  1153. end
  1154. def rl_vi_editing_mode(count, key)
  1155. _rl_set_insert_mode(RL_IM_INSERT, 1) # vi mode ignores insert mode
  1156. @rl_editing_mode = @vi_mode
  1157. rl_vi_insertion_mode(1, key)
  1158. 0
  1159. end
  1160. # Switching from one mode to the other really just involves
  1161. # switching keymaps.
  1162. def rl_vi_insertion_mode(count, key)
  1163. @_rl_keymap = @vi_insertion_keymap
  1164. @_rl_vi_last_key_before_insert = key
  1165. 0
  1166. end
  1167. def rl_emacs_editing_mode(count, key)
  1168. @rl_editing_mode = @emacs_mode
  1169. _rl_set_insert_mode(RL_IM_INSERT, 1) # emacs mode default is insert mode
  1170. @_rl_keymap = @emacs_standard_keymap
  1171. 0
  1172. end
  1173. # Function for the rest of the library to use to set insert/overwrite mode.
  1174. def _rl_set_insert_mode(im, force)
  1175. @rl_insert_mode = im
  1176. end
  1177. # Toggle overwrite mode. A positive explicit argument selects overwrite
  1178. # mode. A negative or zero explicit argument selects insert mode.
  1179. def rl_overwrite_mode(count, key)
  1180. if (!@rl_explicit_arg)
  1181. _rl_set_insert_mode(@rl_insert_mode ^ 1, 0)
  1182. elsif (count > 0)
  1183. _rl_set_insert_mode(RL_IM_OVERWRITE, 0)
  1184. else
  1185. _rl_set_insert_mode(RL_IM_INSERT, 0)
  1186. end
  1187. 0
  1188. end
  1189. # A function for simple tilde expansion.
  1190. def rl_tilde_expand(ignore, key)
  1191. _end = @rl_point
  1192. start = _end - 1
  1193. if (@rl_point == @rl_end && @rl_line_buffer[@rl_point] == ?~ )
  1194. homedir = File.expand_path("~")
  1195. _rl_replace_text(homedir, start, _end)
  1196. return (0)
  1197. elsif (@rl_line_buffer[start] != ?~)
  1198. while(!whitespace(@rl_line_buffer[start,1]) && start >= 0)
  1199. start -= 1
  1200. end
  1201. start+=1
  1202. end
  1203. _end = start
  1204. begin
  1205. _end+=1
  1206. end while(!whitespace(@rl_line_buffer[_end,1]) && _end < @rl_end)
  1207. if (whitespace(@rl_line_buffer[_end,1]) || _end >= @rl_end)
  1208. _end-=1
  1209. end
  1210. # If the first character of the current word is a tilde, perform
  1211. #tilde expansion and insert the result. If not a tilde, do
  1212. # nothing.
  1213. if (@rl_line_buffer[start] == ?~)
  1214. len = _end - start + 1
  1215. temp = @rl_line_buffer[start,len]
  1216. homedir = File.expand_path(temp)
  1217. temp = nil
  1218. _rl_replace_text(homedir, start, _end)
  1219. end
  1220. 0
  1221. end
  1222. # Clean up the terminal and readline state after catching a signal, before
  1223. # resending it to the calling application.
  1224. def rl_cleanup_after_signal()
  1225. _rl_clean_up_for_exit()
  1226. if (@rl_deprep_term_function)
  1227. send(@rl_deprep_term_function)
  1228. end
  1229. rl_clear_pending_input()
  1230. rl_clear_signals()
  1231. end
  1232. def _rl_clean_up_for_exit()
  1233. if @readline_echoing_p
  1234. _rl_move_vert(@_rl_vis_botlin)
  1235. @_rl_vis_botlin = 0
  1236. @rl_outstream.flush
  1237. rl_restart_output(1, 0)
  1238. end
  1239. end
  1240. # Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
  1241. # (Well, when we don't have multibyte characters, _rl_last_c_pos is a
  1242. # buffer index.)
  1243. # DATA is the contents of the screen line of interest; i.e., where
  1244. # the movement is being done.
  1245. def _rl_move_cursor_relative(new, data, start=0)
  1246. woff = w_offset(@_rl_last_v_pos, @wrap_offset)
  1247. cpos = @_rl_last_c_pos
  1248. if !@rl_byte_oriented
  1249. dpos = _rl_col_width(data, start, start+new)
  1250. if (dpos > @prompt_last_invisible) # XXX - don't use woff here
  1251. dpos -= woff
  1252. # Since this will be assigned to _rl_last_c_pos at the end (more
  1253. # precisely, _rl_last_c_pos == dpos when this function returns),
  1254. # let the caller know.
  1255. @cpos_adjusted = true
  1256. end
  1257. else
  1258. dpos = new
  1259. end
  1260. # If we don't have to do anything, then return.
  1261. if (cpos == dpos)
  1262. return
  1263. end
  1264. if @hConsoleHandle
  1265. csbi = 0.chr * 24
  1266. @GetConsoleScreenBufferInfo.Call(@hConsoleHandle,csbi)
  1267. x,y = csbi[4,4].unpack('SS')
  1268. x = dpos
  1269. @SetConsoleCursorPosition.Call(@hConsoleHandle,y*65536+x)
  1270. @_rl_last_c_pos = dpos
  1271. return
  1272. end
  1273. # It may be faster to output a CR, and then move forwards instead
  1274. # of moving backwards.
  1275. # i == current physical cursor position.
  1276. if !@rl_byte_oriented
  1277. i = @_rl_last_c_pos
  1278. else
  1279. i = @_rl_last_c_pos - woff
  1280. end
  1281. if (dpos == 0 || cr_faster(dpos, @_rl_last_c_pos) ||
  1282. (@_rl_term_autowrap && i == @_rl_screenwidth))
  1283. @rl_outstream.write(@_rl_term_cr)
  1284. cpos = @_rl_last_c_pos = 0
  1285. end
  1286. if (cpos < dpos)
  1287. # Move the cursor forward. We do it by printing the command
  1288. # to move the cursor forward if there is one, else print that
  1289. # portion of the output buffer again. Which is cheaper?
  1290. # The above comment is left here for posterity. It is faster
  1291. # to print one character (non-control) than to print a control
  1292. # sequence telling the terminal to move forward one character.
  1293. # That kind of control is for people who don't know what the
  1294. # data is underneath the cursor.
  1295. # However, we need a handle on where the current display position is
  1296. # in the buffer for the immediately preceding comment to be true.
  1297. # In multibyte locales, we don't currently have that info available.
  1298. # Without it, we don't know where the data we have to display begins
  1299. # in the buffer and we have to go back to the beginning of the screen
  1300. # line. In this case, we can use the terminal sequence to move forward
  1301. # if it's available.
  1302. if !@rl_byte_oriented
  1303. if (@_rl_term_forward_char)
  1304. @rl_outstream.write(@_rl_term_forward_char * (dpos-cpos))
  1305. else
  1306. @rl_outstream.write(@_rl_term_cr)
  1307. @rl_outstream.write(data[start,new])
  1308. end
  1309. else
  1310. @rl_outstream.write(data[start+cpos,new-cpos])
  1311. end
  1312. elsif (cpos > dpos)
  1313. _rl_backspace(cpos - dpos)
  1314. end
  1315. @_rl_last_c_pos = dpos
  1316. end
  1317. # PWP: move the cursor up or down.
  1318. def _rl_move_vert(to)
  1319. if (@_rl_last_v_pos == to || to > @_rl_screenheight)
  1320. return
  1321. end
  1322. if ((delta = to - @_rl_last_v_pos) > 0)
  1323. @rl_outstream.write("\n"*delta)
  1324. @rl_outstream.write("\r")
  1325. @_rl_last_c_pos = 0
  1326. else
  1327. if(@_rl_term_up)
  1328. @rl_outstream.write(@_rl_term_up*(-delta))
  1329. end
  1330. end
  1331. @_rl_last_v_pos = to # Now TO is here
  1332. end
  1333. def rl_setstate(x)
  1334. (@rl_readline_state |= (x))
  1335. end
  1336. def rl_unsetstate(x)
  1337. (@rl_readline_state &= ~(x))
  1338. end
  1339. def rl_isstate(x)
  1340. (@rl_readline_state & (x))!=0
  1341. end
  1342. # Clear any pending input pushed with rl_execute_next()
  1343. def rl_clear_pending_input()
  1344. @rl_pending_input = 0
  1345. rl_unsetstate(RL_STATE_INPUTPENDING)
  1346. 0
  1347. end
  1348. def rl_restart_output(count, key)
  1349. 0
  1350. end
  1351. def rl_clear_signals()
  1352. if Signal.list['WINCH']
  1353. trap "WINCH",@def_proc
  1354. end
  1355. end
  1356. def rl_set_signals()
  1357. if Signal.list['WINCH']
  1358. @def_proc = trap "WINCH",Proc.new{rl_sigwinch_handler(0)}
  1359. end
  1360. end
  1361. # Current implementation:
  1362. # \001 (^A) start non-visible characters
  1363. # \002 (^B) end non-visible characters
  1364. # all characters except \001 and \002 (following a \001) are copied to
  1365. # the returned string all characters except those between \001 and
  1366. # \002 are assumed to be `visible'.
  1367. def expand_prompt(pmt)
  1368. # Short-circuit if we can.
  1369. if (@rl_byte_oriented && pmt[RL_PROMPT_START_IGNORE].nil?)
  1370. r = pmt.dup
  1371. lp = r.length
  1372. lip = 0
  1373. niflp = 0
  1374. vlp = lp
  1375. return [r,lp,lip,niflp,vlp]
  1376. end
  1377. l = pmt.length
  1378. ret = ''
  1379. invfl = 0 # invisible chars in first line of prompt
  1380. invflset = 0 # we only want to set invfl once
  1381. igstart = 0
  1382. rl = 0
  1383. ignoring = false
  1384. last = ninvis = physchars = 0
  1385. for pi in 0 ... pmt.length
  1386. # This code strips the invisible character string markers
  1387. #RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE
  1388. if (!ignoring && pmt[pi,1] == RL_PROMPT_START_IGNORE) # XXX - check ignoring?
  1389. ignoring = true
  1390. igstart = pi
  1391. next
  1392. elsif (ignoring && pmt[pi,1] == RL_PROMPT_END_IGNORE)
  1393. ignoring = false
  1394. if (pi != (igstart + 1))
  1395. last = ret.length - 1
  1396. end
  1397. next
  1398. else
  1399. if !@rl_byte_oriented
  1400. pind = pi
  1401. ind = _rl_find_next_mbchar(pmt, pind, 1, MB_FIND_NONZERO)
  1402. l = ind - pind
  1403. while (l>0)
  1404. l-=1
  1405. ret << pmt[pi]
  1406. pi += 1
  1407. end
  1408. if (!ignoring)
  1409. rl += ind - pind
  1410. physchars += _rl_col_width(pmt, pind, ind)
  1411. else
  1412. ninvis += ind - pind
  1413. end
  1414. pi-=1 # compensate for later increment
  1415. else
  1416. ret << pmt[pi]
  1417. if (!ignoring)
  1418. rl+=1 # visible length byte counter
  1419. physchars+=1
  1420. else
  1421. ninvis+=1 # invisible chars byte counter
  1422. end
  1423. if (invflset == 0 && rl >= @_rl_screenwidth)
  1424. invfl = ninvis
  1425. invflset = 1
  1426. end
  1427. end
  1428. end
  1429. end
  1430. if (rl < @_rl_screenwidth)
  1431. invfl = ninvis
  1432. end
  1433. lp = rl
  1434. lip = last
  1435. niflp = invfl
  1436. vlp = physchars
  1437. return [ret,lp,lip,niflp,vlp]
  1438. end
  1439. #*
  1440. #* Expand the prompt string into the various display components, if
  1441. #* necessary.
  1442. #*
  1443. #* local_prompt = expanded last line of string in rl_display_prompt
  1444. #* (portion after the final newline)
  1445. #* local_prompt_prefix = portion before last newline of rl_display_prompt,
  1446. #* expanded via expand_prompt
  1447. #* prompt_visible_length = number of visible characters in local_prompt
  1448. #* prompt_prefix_length = number of visible characters in local_prompt_prefix
  1449. #*
  1450. #* This function is called once per call to readline(). It may also be
  1451. #* called arbitrarily to expand the primary prompt.
  1452. #*
  1453. #* The return value is the number of visible characters on the last line
  1454. #* of the (possibly multi-line) prompt.
  1455. #*
  1456. def rl_expand_prompt(prompt)
  1457. @local_prompt = @local_prompt_prefix = nil
  1458. @local_prompt_len = 0
  1459. @prompt_last_invisible = @prompt_invis_chars_first_line = 0
  1460. @prompt_visible_length = @prompt_physical_chars = 0
  1461. if (prompt.nil? || prompt == '')
  1462. return (0)
  1463. end
  1464. pi = prompt.rindex("\n")
  1465. if pi.nil?
  1466. # The prompt is only one logical line, though it might wrap.
  1467. @local_prompt,@prompt_visible_length,@prompt_last_invisible,@prompt_invis_chars_first_line,@prompt_physical_chars =
  1468. expand_prompt(prompt)
  1469. @local_prompt_prefix = nil
  1470. @local_prompt_len = @local_prompt ? @local_prompt.length : 0
  1471. return (@prompt_visible_length)
  1472. else
  1473. # The prompt spans multiple lines.
  1474. pi += 1 if prompt.length!=pi+1
  1475. t = pi
  1476. @local_prompt,@prompt_visible_length,@prompt_last_invisible,_,@prompt_physical_chars = expand_prompt(prompt[pi..-1])
  1477. c = prompt[t]
  1478. prompt[t] = 0.chr
  1479. # The portion of the prompt string up to and including the
  1480. #final newline is now null-terminated.
  1481. @local_prompt_prefix,@prompt_prefix_length,_,@prompt_invis_chars_first_line, = expand_prompt(prompt)
  1482. prompt[t] = c
  1483. @local_prompt_len = @local_prompt ? @local_prompt.length : 0
  1484. return (@prompt_prefix_length)
  1485. end
  1486. end
  1487. # Set up the prompt and expand it. Called from readline() and
  1488. # rl_callback_handler_install ().
  1489. def rl_set_prompt(prompt)
  1490. @rl_prompt = prompt ? prompt.dup : nil
  1491. @rl_display_prompt = @rl_prompt ? @rl_prompt : ""
  1492. @rl_visible_prompt_length = rl_expand_prompt(@rl_prompt)
  1493. 0
  1494. end
  1495. def get_term_capabilities(buffer)
  1496. hash = {}
  1497. `infocmp -C`.split(':').select{|x| x =~ /(.*)=(.*)/ and hash[$1]=$2.gsub('\\E',"\e").gsub(/\^(.)/){($1[0].ord ^ ((?a..?z).include?($1[0]) ? 0x60 : 0x40)).chr}}
  1498. @_rl_term_at7 = hash["@7"]
  1499. @_rl_term_DC = hash["DC"]
  1500. @_rl_term_IC = hash["IC"]
  1501. @_rl_term_clreol = hash["ce"]
  1502. @_rl_term_clrpag = hash["cl"]
  1503. @_rl_term_cr = hash["cr"]
  1504. @_rl_term_dc = hash["dc"]
  1505. @_rl_term_ei = hash["ei"]
  1506. @_rl_term_ic = hash["ic"]
  1507. @_rl_term_im = hash["im"]
  1508. @_rl_term_kD = hash["kD"]
  1509. @_rl_term_kH = hash["kH"]
  1510. @_rl_term_kI = hash["kI"]
  1511. @_rl_term_kd = hash["kd"]
  1512. @_rl_term_ke = hash["ke"]
  1513. @_rl_term_kh = hash["kh"]
  1514. @_rl_term_kl = hash["kl"]
  1515. @_rl_term_kr = hash["kr"]
  1516. @_rl_term_ks = hash["ks"]
  1517. @_rl_term_ku = hash["ku"]
  1518. @_rl_term_backspace = hash["le"]
  1519. @_rl_term_mm = hash["mm"]
  1520. @_rl_term_mo = hash["mo"]
  1521. @_rl_term_forward_char = hash["nd"]
  1522. @_rl_term_pc = hash["pc"]
  1523. @_rl_term_up = hash["up"]
  1524. @_rl_visible_bell = hash["vb"]
  1525. @_rl_term_vs = hash["vs"]
  1526. @_rl_term_ve = hash["ve"]
  1527. @tcap_initialized = true
  1528. end
  1529. # Set the environment variables LINES and COLUMNS to lines and cols,
  1530. # respectively.
  1531. def sh_set_lines_and_columns(lines, cols)
  1532. ENV["LINES"] = lines.to_s
  1533. ENV["COLUMNS"] = cols.to_s
  1534. end
  1535. # Get readline's idea of the screen size. TTY is a file descriptor open
  1536. # to the terminal. If IGNORE_ENV is true, we do not pay attention to the
  1537. # values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being
  1538. # non-null serve to check whether or not we have initialized termcap.
  1539. def _rl_get_screen_size(tty, ignore_env)
  1540. if @hConsoleHandle
  1541. csbi = 0.chr * 24
  1542. @GetConsoleScreenBufferInfo.Call(@hConsoleHandle,csbi)
  1543. wc,wr = csbi[0,4].unpack('SS')
  1544. # wr,wc, = `mode con`.scan(/\d+\n/).map{|x| x.to_i}
  1545. @_rl_screenwidth = wc
  1546. @_rl_screenheight = wr
  1547. else
  1548. wr,wc = `stty size`.split(' ').map{|x| x.to_i}
  1549. @_rl_screenwidth = wc
  1550. @_rl_screenheight = wr
  1551. if ignore_env==0 && ENV['LINES']
  1552. @_rl_screenheight = ENV['LINES'].to_i
  1553. end
  1554. if ignore_env==0 && ENV['COLUMNS']
  1555. @_rl_screenwidth = ENV['COLUMNS'].to_i
  1556. end
  1557. end
  1558. # If all else fails, default to 80x24 terminal.
  1559. if @_rl_screenwidth.nil? || @_rl_screenwidth <= 1
  1560. @_rl_screenwidth = 80
  1561. end
  1562. if @_rl_screenheight.nil? || @_rl_screenheight <= 0
  1563. @_rl_screenheight = 24
  1564. end
  1565. # If we're being compiled as part of bash, set the environment
  1566. # variables $LINES and $COLUMNS to new values. Otherwise, just
  1567. # do a pair of putenv () or setenv () calls.
  1568. sh_set_lines_and_columns(@_rl_screenheight, @_rl_screenwidth)
  1569. if !@_rl_term_autowrap
  1570. @_rl_screenwidth-=1
  1571. end
  1572. @_rl_screenchars = @_rl_screenwidth * @_rl_screenheight
  1573. end
  1574. def tgetflag(name)
  1575. `infocmp -C -r`.scan(/\w{2}/).include?(name)
  1576. end
  1577. # Return the function (or macro) definition which would be invoked via
  1578. # KEYSEQ if executed in MAP. If MAP is NULL, then the current keymap is
  1579. # used. TYPE, if non-NULL, is a pointer to an int which will receive the
  1580. # type of the object pointed to. One of ISFUNC (function), ISKMAP (keymap),
  1581. # or ISMACR (macro).
  1582. def rl_function_of_keyseq(keyseq, map, type)
  1583. map ||= @_rl_keymap
  1584. map[keyseq]
  1585. end
  1586. # Bind the key sequence represented by the string KEYSEQ to
  1587. # the arbitrary pointer DATA. TYPE says what kind of data is
  1588. # pointed to by DATA, right now this can be a function (ISFUNC),
  1589. # a macro (ISMACR), or a keymap (ISKMAP). This makes new keymaps
  1590. # as necessary. The initial place to do bindings is in MAP.
  1591. def rl_generic_bind(type, keyseq, data, map)
  1592. map[keyseq] = data
  1593. 0
  1594. end
  1595. # Bind the key sequence represented by the string KEYSEQ to
  1596. # FUNCTION. This makes new keymaps as necessary. The initial
  1597. # place to do bindings is in MAP.
  1598. def rl_bind_keyseq_in_map(keyseq, function, map)
  1599. rl_generic_bind(ISFUNC, keyseq, function, map)
  1600. end
  1601. # Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. Right
  1602. # now, this is always used to attempt to bind the arrow keys, hence the
  1603. # check for rl_vi_movement_mode.
  1604. def rl_bind_keyseq_if_unbound_in_map(keyseq, default_func, kmap)
  1605. if (keyseq)
  1606. func = rl_function_of_keyseq(keyseq, kmap, nil)
  1607. if (func.nil? || func == :rl_vi_movement_mode)
  1608. return (rl_bind_keyseq_in_map(keyseq, default_func, kmap))
  1609. else
  1610. return 1
  1611. end
  1612. end
  1613. 0
  1614. end
  1615. def rl_bind_keyseq_if_unbound(keyseq, default_func)
  1616. rl_bind_keyseq_if_unbound_in_map(keyseq, default_func, @_rl_keymap)
  1617. end
  1618. # Bind the arrow key sequences from the termcap description in MAP.
  1619. def bind_termcap_arrow_keys(map)
  1620. xkeymap = @_rl_keymap
  1621. @_rl_keymap = map
  1622. rl_bind_keyseq_if_unbound(@_rl_term_ku, :rl_get_previous_history)
  1623. rl_bind_keyseq_if_unbound(@_rl_term_kd, :rl_get_next_history)
  1624. rl_bind_keyseq_if_unbound(@_rl_term_kr, :rl_forward_char)
  1625. rl_bind_keyseq_if_unbound(@_rl_term_kl, :rl_backward_char)
  1626. rl_bind_keyseq_if_unbound(@_rl_term_kh, :rl_beg_of_line) # Home
  1627. rl_bind_keyseq_if_unbound(@_rl_term_at7, :rl_end_of_line) # End
  1628. rl_bind_keyseq_if_unbound(@_rl_term_kD, :rl_delete)
  1629. rl_bind_keyseq_if_unbound(@_rl_term_kI, :rl_overwrite_mode)
  1630. @_rl_keymap = xkeymap
  1631. end
  1632. def _rl_init_terminal_io(terminal_name)
  1633. term = terminal_name ? terminal_name : ENV["TERM"]
  1634. @_rl_term_clrpag = @_rl_term_cr = @_rl_term_clreol = nil
  1635. tty = @rl_instream ? @rl_instream.fileno : 0
  1636. if no_terminal?
  1637. term = "dumb"
  1638. @_rl_bind_stty_chars = false
  1639. end
  1640. @term_string_buffer ||= 0.chr * 2032
  1641. @term_buffer ||= 0.chr * 4080
  1642. buffer = @term_string_buffer
  1643. tgetent_ret = (term != "dumb") ? 1 : -1
  1644. if (tgetent_ret <= 0)
  1645. buffer = @term_buffer = @term_string_buffer = nil
  1646. @_rl_term_autowrap = false # used by _rl_get_screen_size
  1647. # Allow calling application to set default height and width, using
  1648. #rl_set_screen_size
  1649. if (@_rl_screenwidth <= 0 || @_rl_screenheight <= 0)
  1650. _rl_get_screen_size(tty, 0)
  1651. end
  1652. # Defaults.
  1653. if (@_rl_screenwidth <= 0 || @_rl_screenheight <= 0)
  1654. @_rl_screenwidth = 79
  1655. @_rl_screenheight = 24
  1656. end
  1657. # Everything below here is used by the redisplay code (tputs).
  1658. @_rl_screenchars = @_rl_screenwidth * @_rl_screenheight
  1659. @_rl_term_cr = "\r"
  1660. @_rl_term_im = @_rl_term_ei = @_rl_term_ic = @_rl_term_IC = nil
  1661. @_rl_term_up = @_rl_term_dc = @_rl_term_DC = @_rl_visible_bell = nil
  1662. @_rl_term_ku = @_rl_term_kd = @_rl_term_kl = @_rl_term_kr = nil
  1663. @_rl_term_kh = @_rl_term_kH = @_rl_term_kI = @_rl_term_kD = nil
  1664. @_rl_term_ks = @_rl_term_ke = @_rl_term_at7 = nil
  1665. @_rl_term_mm = @_rl_term_mo = nil
  1666. @_rl_term_ve = @_rl_term_vs = nil
  1667. @_rl_term_forward_char = nil
  1668. @_rl_terminal_can_insert = @term_has_meta = false
  1669. # Reasonable defaults for tgoto(). Readline currently only uses
  1670. # tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
  1671. # change that later...
  1672. @_rl_term_backspace = "\b"
  1673. return 0
  1674. end
  1675. get_term_capabilities(buffer)
  1676. @_rl_term_cr ||= "\r"
  1677. @_rl_term_autowrap = !!(tgetflag("am") && tgetflag("xn"))
  1678. # Allow calling application to set default height and width, using
  1679. # rl_set_screen_size
  1680. if (@_rl_screenwidth <= 0 || @_rl_screenheight <= 0)
  1681. _rl_get_screen_size(tty, 0)
  1682. end
  1683. # "An application program can assume that the terminal can do
  1684. # character insertion if *any one of* the capabilities `IC',
  1685. # `im', `ic' or `ip' is provided." But we can't do anything if
  1686. # only `ip' is provided, so...
  1687. @_rl_terminal_can_insert = !!(@_rl_term_IC || @_rl_term_im || @_rl_term_ic)
  1688. # Check to see if this terminal has a meta key and clear the capability
  1689. # variables if there is none.
  1690. @term_has_meta = !!(tgetflag("km") || tgetflag("MT"))
  1691. if !@term_has_meta
  1692. @_rl_term_mm = @_rl_term_mo = nil
  1693. end
  1694. # Attempt to find and bind the arrow keys. Do not override already
  1695. # bound keys in an overzealous attempt, however.
  1696. bind_termcap_arrow_keys(@emacs_standard_keymap)
  1697. bind_termcap_arrow_keys(@vi_movement_keymap)
  1698. bind_termcap_arrow_keys(@vi_insertion_keymap)
  1699. return 0
  1700. end
  1701. # New public way to set the system default editing chars to their readline
  1702. # equivalents.
  1703. def rl_tty_set_default_bindings(kmap)
  1704. h = Hash[*`stty -a`.scan(/(\w+) = ([^;]+);/).flatten]
  1705. h.each {|k,v| v.gsub!(/\^(.)/){($1[0].ord ^ ((?a..?z).include?($1[0]) ? 0x60 : 0x40)).chr}}
  1706. kmap[h['erase']] = :rl_rubout
  1707. kmap[h['kill']] = :rl_unix_line_discard
  1708. kmap[h['werase']] = :rl_unix_word_rubout
  1709. kmap[h['lnext']] = :rl_quoted_insert
  1710. end
  1711. # If this system allows us to look at the values of the regular
  1712. # input editing characters, then bind them to their readline
  1713. # equivalents, iff the characters are not bound to keymaps.
  1714. def readline_default_bindings()
  1715. if @_rl_bind_stty_chars
  1716. rl_tty_set_default_bindings(@_rl_keymap)
  1717. end
  1718. end
  1719. def _rl_init_eightbit()
  1720. end
  1721. # Do key bindings from a file. If FILENAME is NULL it defaults
  1722. # to the first non-null filename from this list:
  1723. # 1. the filename used for the previous call
  1724. # 2. the value of the shell variable `INPUTRC'
  1725. # 3. ~/.inputrc
  1726. # 4. /etc/inputrc
  1727. # If the file existed and could be opened and read, 0 is returned,
  1728. # otherwise errno is returned.
  1729. def rl_read_init_file(filename)
  1730. # Default the filename.
  1731. filename ||= @last_readline_init_file
  1732. filename ||= ENV["INPUTRC"]
  1733. if (filename.nil? || filename == '')
  1734. filename = DEFAULT_INPUTRC
  1735. # Try to read DEFAULT_INPUTRC; fall back to SYS_INPUTRC on failure
  1736. if (_rl_read_init_file(filename, 0) == 0)
  1737. return 0
  1738. end
  1739. filename = SYS_INPUTRC
  1740. end
  1741. if RUBY_PLATFORM =~ /mswin|mingw/
  1742. return 0 if (_rl_read_init_file(filename, 0) == 0)
  1743. filename = "~/_inputrc"
  1744. end
  1745. return (_rl_read_init_file(filename, 0))
  1746. end
  1747. def _rl_read_init_file(filename, include_level)
  1748. @current_readline_init_file = filename
  1749. @current_readline_init_include_level = include_level
  1750. openname = File.expand_path(filename)
  1751. begin
  1752. buffer = File.open(openname).read
  1753. rescue
  1754. return -1
  1755. end
  1756. if (include_level == 0 && filename != @last_readline_init_file)
  1757. @last_readline_init_file = filename.dup
  1758. end
  1759. @currently_reading_init_file = true
  1760. # Loop over the lines in the file. Lines that start with `#' are
  1761. # comments; all other lines are commands for readline initialization.
  1762. @current_readline_init_lineno = 1
  1763. buffer.each_line do |line|
  1764. line.strip!
  1765. next if line =~ /^#/
  1766. next if line == ''
  1767. rl_parse_and_bind(line)
  1768. end
  1769. return 0
  1770. end
  1771. # Push _rl_parsing_conditionalized_out, and set parser state based
  1772. # on ARGS.
  1773. def parser_if(args)
  1774. # Push parser state.
  1775. @if_stack << @_rl_parsing_conditionalized_out
  1776. # If parsing is turned off, then nothing can turn it back on except
  1777. # for finding the matching endif. In that case, return right now.
  1778. if @_rl_parsing_conditionalized_out
  1779. return 0
  1780. end
  1781. args.downcase!
  1782. # Handle "$if term=foo" and "$if mode=emacs" constructs. If this
  1783. # isn't term=foo, or mode=emacs, then check to see if the first
  1784. # word in ARGS is the same as the value stored in rl_readline_name.
  1785. if (@rl_terminal_name && args =~ /^term=/)
  1786. # Terminals like "aaa-60" are equivalent to "aaa".
  1787. tname = @rl_terminal_name.downcase.gsub(/-.*$/,'')
  1788. # Test the `long' and `short' forms of the terminal name so that
  1789. #if someone has a `sun-cmd' and does not want to have bindings
  1790. #that will be executed if the terminal is a `sun', they can put
  1791. #`$if term=sun-cmd' into their .inputrc.
  1792. @_rl_parsing_conditionalized_out = (args[5..-1] != tname && args[5..-1] != @rl_terminal_name.downcase)
  1793. elsif args =~ /^mode=/
  1794. if args[5..-1] == "emacs"
  1795. mode = @emacs_mode
  1796. elsif args[5..-1] == "vi"
  1797. mode = @vi_mode
  1798. else
  1799. mode = @no_mode
  1800. end
  1801. @_rl_parsing_conditionalized_out = (mode != @rl_editing_mode)
  1802. # Check to see if the first word in ARGS is the same as the
  1803. # value stored in rl_readline_name.
  1804. elsif (args == @rl_readline_name)
  1805. @_rl_parsing_conditionalized_out = false
  1806. else
  1807. @_rl_parsing_conditionalized_out = true
  1808. end
  1809. return 0
  1810. end
  1811. # Invert the current parser state if there is anything on the stack.
  1812. def parser_else(args)
  1813. if @if_stack.empty?
  1814. #_rl_init_file_error ("$else found without matching $if")
  1815. return 0
  1816. end
  1817. # Check the previous (n) levels of the stack to make sure that
  1818. # we haven't previously turned off parsing.
  1819. return 0 if @if_stack.detect {|x| x }
  1820. # Invert the state of parsing if at top level.
  1821. @_rl_parsing_conditionalized_out = !@_rl_parsing_conditionalized_out
  1822. return 0
  1823. end
  1824. # Terminate a conditional, popping the value of
  1825. # _rl_parsing_conditionalized_out from the stack.
  1826. def parser_endif(args)
  1827. if (@if_stack.length>0)
  1828. @_rl_parsing_conditionalized_out = @if_stack.pop
  1829. else
  1830. #_rl_init_file_error ("$endif without matching $if")
  1831. end
  1832. 0
  1833. end
  1834. def parser_include(args)
  1835. return 0 if (@_rl_parsing_conditionalized_out)
  1836. old_init_file = @current_readline_init_file
  1837. old_line_number = @current_readline_init_lineno
  1838. old_include_level = @current_readline_init_include_level
  1839. r = _rl_read_init_file(args, old_include_level + 1)
  1840. @current_readline_init_file = old_init_file
  1841. @current_readline_init_lineno = old_line_number
  1842. @current_readline_init_include_level = old_include_level
  1843. return r
  1844. end
  1845. # Handle a parser directive. STATEMENT is the line of the directive
  1846. # without any leading `$'.
  1847. def handle_parser_directive(statement)
  1848. directive,args = statement.split(' ')
  1849. case directive.downcase
  1850. when "if"
  1851. parser_if(args)
  1852. return 0
  1853. when "endif"
  1854. parser_endif(args)
  1855. return 0
  1856. when "else"
  1857. parser_else(args)
  1858. return 0
  1859. when "include"
  1860. parser_include(args)
  1861. return 0
  1862. end
  1863. #_rl_init_file_error("unknown parser directive")
  1864. return 1
  1865. end
  1866. def rl_variable_bind(name,value)
  1867. case name
  1868. when "bind-tty-special-chars"
  1869. @_rl_bind_stty_chars = value.nil? || value=='1' || value == 'on'
  1870. when "blink-matching-paren"
  1871. @rl_blink_matching_paren = value.nil? || value=='1' || value == 'on'
  1872. when "byte-oriented"
  1873. @rl_byte_oriented = value.nil? || value=='1' || value == 'on'
  1874. when "completion-ignore-case"
  1875. @_rl_completion_case_fold = value.nil? || value=='1' || value == 'on'
  1876. when "convert-meta"
  1877. @_rl_convert_meta_chars_to_ascii = value.nil? || value=='1' || value == 'on'
  1878. when "disable-completion"
  1879. @rl_inhibit_completion = value.nil? || value=='1' || value == 'on'
  1880. when "enable-keypad"
  1881. @_rl_enable_keypad = value.nil? || value=='1' || value == 'on'
  1882. when "expand-tilde"
  1883. @rl_complete_with_tilde_expansion = value.nil? || value=='1' || value == 'on'
  1884. when "history-preserve-point"
  1885. @_rl_history_preserve_point = value.nil? || value=='1' || value == 'on'
  1886. when "horizontal-scroll-mode"
  1887. @_rl_horizontal_scroll_mode = value.nil? || value=='1' || value == 'on'
  1888. when "input-meta"
  1889. @_rl_meta_flag = value.nil? || value=='1' || value == 'on'
  1890. when "mark-directories"
  1891. @_rl_complete_mark_directories = value.nil? || value=='1' || value == 'on'
  1892. when "mark-modified-lines"
  1893. @_rl_mark_modified_lines = value.nil? || value=='1' || value == 'on'
  1894. when "mark-symlinked-directories"
  1895. @_rl_complete_mark_symlink_dirs = value.nil? || value=='1' || value == 'on'
  1896. when "match-hidden-files"
  1897. @_rl_match_hidden_files = value.nil? || value=='1' || value == 'on'
  1898. when "meta-flag"
  1899. @_rl_meta_flag = value.nil? || value=='1' || value == 'on'
  1900. when "output-meta"
  1901. @_rl_output_meta_chars = value.nil? || value=='1' || value == 'on'
  1902. when "page-completions"
  1903. @_rl_page_completions = value.nil? || value=='1' || value == 'on'
  1904. when "prefer-visible-bell"
  1905. @_rl_prefer_visible_bell = value.nil? || value=='1' || value == 'on'
  1906. when "print-completions-horizontally"
  1907. @_rl_print_completions_horizontally = value.nil? || value=='1' || value == 'on'
  1908. when "show-all-if-ambiguous"
  1909. @_rl_complete_show_all = value.nil? || value=='1' || value == 'on'
  1910. when "show-all-if-unmodified"
  1911. @_rl_complete_show_unmodified = value.nil? || value=='1' || value == 'on'
  1912. when "visible-stats"
  1913. @rl_visible_stats = value.nil? || value=='1' || value == 'on'
  1914. when "bell-style"
  1915. case value
  1916. when "none","off"
  1917. @_rl_bell_preference = NO_BELL
  1918. when "audible", "on"
  1919. @_rl_bell_preference = AUDIBLE_BELL
  1920. when "visible"
  1921. @_rl_bell_preference = VISIBLE_BELL
  1922. else
  1923. @_rl_bell_preference = AUDIBLE_BELL
  1924. end
  1925. when "comment-begin"
  1926. @_rl_comment_begin = value.dup
  1927. when "completion-query-items"
  1928. @rl_completion_query_items = value.to_i
  1929. when "editing-mode"
  1930. case value
  1931. when "vi"
  1932. @_rl_keymap = @vi_insertion_keymap
  1933. @rl_editing_mode = @vi_mode
  1934. when "emacs"
  1935. @_rl_keymap = @emacs_standard_keymap
  1936. @rl_editing_mode = @emacs_mode
  1937. end
  1938. when "isearch-terminators"
  1939. @_rl_isearch_terminators = instance_eval(value)
  1940. when "keymap"
  1941. case value
  1942. when "emacs","emacs-standard","emacs-meta","emacs-ctlx"
  1943. @_rl_keymap = @emacs_standard_keymap
  1944. when "vi","vi-move","vi-command"
  1945. @_rl_keymap = @vi_movement_keymap
  1946. when "vi-insert"
  1947. @_rl_keymap = @vi_insertion_keymap
  1948. end
  1949. end
  1950. end
  1951. def rl_named_function(name)
  1952. case name
  1953. when "accept-line"
  1954. return :rl_newline
  1955. when "arrow-key-prefix"
  1956. return :rl_arrow_keys
  1957. when "backward-delete-char"
  1958. return :rl_rubout
  1959. when "character-search"
  1960. return :rl_char_search
  1961. when "character-search-backward"
  1962. return :rl_backward_char_search
  1963. when "copy-region-as-kill"
  1964. return :rl_copy_region_to_kill
  1965. when "delete-char"
  1966. return :rl_delete
  1967. when "delete-char-or-list"
  1968. return :rl_delete_or_show_completions
  1969. when "forward-backward-delete-char"
  1970. return :rl_rubout_or_delete
  1971. when "kill-whole-line"
  1972. return :rl_kill_full_line
  1973. when "non-incremental-forward-search-history"
  1974. return :rl_noninc_forward_search
  1975. when "non-incremental-reverse-search-history"
  1976. return :rl_noninc_reverse_search
  1977. when "non-incremental-forward-search-history-again"
  1978. return :rl_noninc_forward_search_again
  1979. when "non-incremental-reverse-search-history-again"
  1980. return :rl_noninc_reverse_search_again
  1981. when "redraw-current-line"
  1982. return :rl_refresh_line
  1983. when "self-insert"
  1984. return :rl_insert
  1985. when "undo"
  1986. return :rl_undo_command
  1987. when "beginning-of-line"
  1988. return :rl_beg_of_line
  1989. else
  1990. if name =~ /^[-a-z]+$/
  1991. return ('rl_'+name.gsub('-','_')).to_sym
  1992. end
  1993. end
  1994. nil
  1995. end
  1996. # Bind KEY to FUNCTION. Returns non-zero if KEY is out of range.
  1997. def rl_bind_key(key, function)
  1998. @_rl_keymap[key] = function
  1999. @rl_binding_keymap = @_rl_keymap
  2000. 0
  2001. end
  2002. # Read the binding command from STRING and perform it.
  2003. # A key binding command looks like: Keyname: function-name\0,
  2004. # a variable binding command looks like: set variable value.
  2005. # A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark.
  2006. def rl_parse_and_bind(string)
  2007. # If this is a parser directive, act on it.
  2008. if (string[0] == ?$)
  2009. handle_parser_directive(string[1..-1])
  2010. return 0
  2011. end
  2012. # If we aren't supposed to be parsing right now, then we're done.
  2013. return 0 if @_rl_parsing_conditionalized_out
  2014. if string =~ /^set/i
  2015. _,var,value = string.downcase.split(' ')
  2016. rl_variable_bind(var, value)
  2017. return 0
  2018. end
  2019. key,funname = string.split(/\s*:\s*/)
  2020. key = instance_eval(key)
  2021. rl_bind_key(key, rl_named_function(funname))
  2022. 0
  2023. end
  2024. def _rl_enable_meta_key()
  2025. if(@term_has_meta && @_rl_term_mm)
  2026. @_rl_out_stream.write(@_rl_term_mm)
  2027. end
  2028. end
  2029. def rl_set_keymap_from_edit_mode()
  2030. if (@rl_editing_mode == @emacs_mode)
  2031. @_rl_keymap = @emacs_standard_keymap
  2032. elsif (@rl_editing_mode == @vi_mode)
  2033. @_rl_keymap = @vi_insertion_keymap
  2034. end
  2035. end
  2036. def rl_get_keymap_name_from_edit_mode()
  2037. if (@rl_editing_mode == @emacs_mode)
  2038. "emacs"
  2039. elsif (@rl_editing_mode == @vi_mode)
  2040. "vi"
  2041. else
  2042. "none"
  2043. end
  2044. end
  2045. # Bind some common arrow key sequences in MAP.
  2046. def bind_arrow_keys_internal(map)
  2047. xkeymap = @_rl_keymap
  2048. @_rl_keymap = map
  2049. if RUBY_PLATFORM =~ /mswin|mingw/
  2050. rl_bind_keyseq_if_unbound("\340H", :rl_get_previous_history) # Up
  2051. rl_bind_keyseq_if_unbound("\340P", :rl_get_next_history) # Down
  2052. rl_bind_keyseq_if_unbound("\340M", :rl_forward_char) # Right
  2053. rl_bind_keyseq_if_unbound("\340K", :rl_backward_char) # Left
  2054. rl_bind_keyseq_if_unbound("\340G", :rl_beg_of_line) # Home
  2055. rl_bind_keyseq_if_unbound("\340O", :rl_end_of_line) # End
  2056. rl_bind_keyseq_if_unbound("\340s", :rl_backward_word) # Ctrl-Left
  2057. rl_bind_keyseq_if_unbound("\340t", :rl_forward_word) # Ctrl-Right
  2058. rl_bind_keyseq_if_unbound("\340S", :rl_delete) # Delete
  2059. rl_bind_keyseq_if_unbound("\340R", :rl_overwrite_mode) # Insert
  2060. else
  2061. rl_bind_keyseq_if_unbound("\033[A", :rl_get_previous_history)
  2062. rl_bind_keyseq_if_unbound("\033[B", :rl_get_next_history)
  2063. rl_bind_keyseq_if_unbound("\033[C", :rl_forward_char)
  2064. rl_bind_keyseq_if_unbound("\033[D", :rl_backward_char)
  2065. rl_bind_keyseq_if_unbound("\033[H", :rl_beg_of_line)
  2066. rl_bind_keyseq_if_unbound("\033[F", :rl_end_of_line)
  2067. rl_bind_keyseq_if_unbound("\033OA", :rl_get_previous_history)
  2068. rl_bind_keyseq_if_unbound("\033OB", :rl_get_next_history)
  2069. rl_bind_keyseq_if_unbound("\033OC", :rl_forward_char)
  2070. rl_bind_keyseq_if_unbound("\033OD", :rl_backward_char)
  2071. rl_bind_keyseq_if_unbound("\033OH", :rl_beg_of_line)
  2072. rl_bind_keyseq_if_unbound("\033OF", :rl_end_of_line)
  2073. end
  2074. @_rl_keymap = xkeymap
  2075. end
  2076. # Try and bind the common arrow key prefixes after giving termcap and
  2077. # the inputrc file a chance to bind them and create `real' keymaps
  2078. # for the arrow key prefix.
  2079. def bind_arrow_keys()
  2080. bind_arrow_keys_internal(@emacs_standard_keymap)
  2081. bind_arrow_keys_internal(@vi_movement_keymap)
  2082. bind_arrow_keys_internal(@vi_insertion_keymap)
  2083. end
  2084. # Initialize the entire state of the world.
  2085. def readline_initialize_everything()
  2086. # Set up input and output if they are not already set up.
  2087. @rl_instream ||= $stdin
  2088. @rl_outstream ||= $stdout
  2089. # Bind _rl_in_stream and _rl_out_stream immediately. These values
  2090. # may change, but they may also be used before readline_internal ()
  2091. # is called.
  2092. @_rl_in_stream = @rl_instream
  2093. @_rl_out_stream = @rl_outstream
  2094. # Allocate data structures.
  2095. @rl_line_buffer ||= 0.chr * DEFAULT_BUFFER_SIZE
  2096. # Initialize the terminal interface.
  2097. @rl_terminal_name ||= ENV["TERM"]
  2098. _rl_init_terminal_io(@rl_terminal_name)
  2099. # Bind tty characters to readline functions.
  2100. readline_default_bindings()
  2101. # Decide whether we should automatically go into eight-bit mode.
  2102. _rl_init_eightbit()
  2103. # Read in the init file.
  2104. rl_read_init_file(nil)
  2105. # XXX
  2106. if (@_rl_horizontal_scroll_mode && @_rl_term_autowrap)
  2107. @_rl_screenwidth -= 1
  2108. @_rl_screenchars -= @_rl_screenheight
  2109. end
  2110. # Override the effect of any `set keymap' assignments in the
  2111. # inputrc file.
  2112. rl_set_keymap_from_edit_mode()
  2113. # Try to bind a common arrow key prefix, if not already bound.
  2114. bind_arrow_keys()
  2115. # Enable the meta key, if this terminal has one.
  2116. if @_rl_enable_meta
  2117. _rl_enable_meta_key()
  2118. end
  2119. # If the completion parser's default word break characters haven't
  2120. # been set yet, then do so now.
  2121. @rl_completer_word_break_characters ||= @rl_basic_word_break_characters
  2122. end
  2123. def _rl_init_line_state()
  2124. @rl_point = @rl_end = @rl_mark = 0
  2125. @rl_line_buffer = 0.chr * @rl_line_buffer.length
  2126. end
  2127. # Set the history pointer back to the last entry in the history.
  2128. def _rl_start_using_history()
  2129. using_history()
  2130. @_rl_saved_line_for_history = nil
  2131. end
  2132. def cr_faster(new, cur)
  2133. (new + 1) < (cur - new)
  2134. end
  2135. #* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
  2136. # buffer index in others. This macro is used when deciding whether the
  2137. # current cursor position is in the middle of a prompt string containing
  2138. # invisible characters.
  2139. def prompt_ending_index()
  2140. if !@rl_byte_oriented
  2141. @prompt_physical_chars
  2142. else
  2143. (@prompt_last_invisible+1)
  2144. end
  2145. end
  2146. # Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
  2147. # arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE
  2148. # and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
  2149. # increased. If the lines have already been allocated, this ensures that
  2150. # they can hold at least MINSIZE characters.
  2151. def init_line_structures(minsize)
  2152. if @invisible_line.nil? # initialize it
  2153. if (@line_size < minsize)
  2154. @line_size = minsize
  2155. end
  2156. @visible_line = 0.chr * @line_size
  2157. @invisible_line = 0.chr * @line_size # 1.chr
  2158. elsif (@line_size < minsize) # ensure it can hold MINSIZE chars
  2159. @line_size *= 2
  2160. if (@line_size < minsize)
  2161. @line_size = minsize
  2162. end
  2163. @visible_line << 0.chr * (@line_size - @visible_line.length)
  2164. @invisible_line << 1.chr * (@line_size - @invisible_line.length)
  2165. end
  2166. @visible_line[minsize,@line_size-minsize] = 0.chr * (@line_size-minsize)
  2167. @invisible_line[minsize,@line_size-minsize] = 1.chr * (@line_size-minsize)
  2168. if @vis_lbreaks.nil?
  2169. @inv_lbreaks = []
  2170. @vis_lbreaks = []
  2171. @_rl_wrapped_line = []
  2172. @inv_lbreaks[0] = @vis_lbreaks[0] = 0
  2173. end
  2174. end
  2175. # Return the history entry at the current position, as determined by
  2176. # history_offset. If there is no entry there, return a NULL pointer.
  2177. def current_history()
  2178. return ((@history_offset == @history_length) || @the_history.nil?) ?
  2179. nil : @the_history[@history_offset]
  2180. end
  2181. def meta_char(c)
  2182. c > "\x7f" && c <= "\xff"
  2183. end
  2184. def ctrl_char(c)
  2185. c < "\x20"
  2186. end
  2187. def isprint(c)
  2188. c >= "\x20" && c < "\x7f"
  2189. end
  2190. def whitespace(c)
  2191. (c == ' ' || c == "\t")
  2192. end
  2193. def w_offset(line, offset)
  2194. ((line) == 0 ? offset : 0)
  2195. end
  2196. def vis_llen(l)
  2197. ((l) > @_rl_vis_botlin ? 0 : (@vis_lbreaks[l+1] - @vis_lbreaks[l]))
  2198. end
  2199. def inv_llen(l)
  2200. (@inv_lbreaks[l+1] - @inv_lbreaks[l])
  2201. end
  2202. def vis_chars(line)
  2203. @visible_line[@vis_lbreaks[line] .. -1]
  2204. end
  2205. def vis_pos(line)
  2206. @vis_lbreaks[line]
  2207. end
  2208. def vis_line(line)
  2209. ((line) > @_rl_vis_botlin) ? "" : vis_chars(line)
  2210. end
  2211. def inv_line(line)
  2212. @invisible_line[@inv_lbreaks[line] .. -1]
  2213. end
  2214. def m_offset(margin, offset)
  2215. ((margin) == 0 ? offset : 0)
  2216. end
  2217. # PWP: update_line() is based on finding the middle difference of each
  2218. # line on the screen; vis:
  2219. #
  2220. # /old first difference
  2221. # /beginning of line | /old last same /old EOL
  2222. # v v v v
  2223. # old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
  2224. # new: eddie> Oh, my little buggy says to me, as lurgid as
  2225. # ^ ^ ^ ^
  2226. # \beginning of line | \new last same \new end of line
  2227. # \new first difference
  2228. #
  2229. # All are character pointers for the sake of speed. Special cases for
  2230. # no differences, as well as for end of line additions must be handled.
  2231. #
  2232. # Could be made even smarter, but this works well enough
  2233. def update_line(old, ostart, new, current_line, omax, nmax, inv_botlin)
  2234. # If we're at the right edge of a terminal that supports xn, we're
  2235. # ready to wrap around, so do so. This fixes problems with knowing
  2236. # the exact cursor position and cut-and-paste with certain terminal
  2237. # emulators. In this calculation, TEMP is the physical screen
  2238. # position of the cursor.
  2239. if @encoding == 'X'
  2240. old.force_encoding('ASCII-8BIT')
  2241. new.force_encoding('ASCII-8BIT')
  2242. end
  2243. if !@rl_byte_oriented
  2244. temp = @_rl_last_c_pos
  2245. else
  2246. temp = @_rl_last_c_pos - w_offset(@_rl_last_v_pos, @visible_wrap_offset)
  2247. end
  2248. if (temp == @_rl_screenwidth && @_rl_term_autowrap && !@_rl_horizontal_scroll_mode &&
  2249. @_rl_last_v_pos == current_line - 1)
  2250. if (!@rl_byte_oriented)
  2251. # This fixes only double-column characters, but if the wrapped
  2252. # character comsumes more than three columns, spaces will be
  2253. # inserted in the string buffer.
  2254. if (@_rl_wrapped_line[current_line] > 0)
  2255. _rl_clear_to_eol(@_rl_wrapped_line[current_line])
  2256. end
  2257. if new[0] != ?\0
  2258. case @encoding
  2259. when 'E'
  2260. wc = new.scan(/./me)[0]
  2261. ret = wc.length
  2262. tempwidth = wc.length
  2263. when 'S'
  2264. wc = new.scan(/./ms)[0]
  2265. ret = wc.length
  2266. tempwidth = wc.length
  2267. when 'U'
  2268. wc = new.scan(/./mu)[0]
  2269. ret = wc.length
  2270. tempwidth = wc.unpack('U').first >= 0x1000 ? 2 : 1
  2271. when 'X'
  2272. wc = new[0..-1].force_encoding(@encoding_name)[0]
  2273. ret = wc.bytesize
  2274. tempwidth = wc.ord >= 0x1000 ? 2 : 1
  2275. else
  2276. ret = 1
  2277. tempwidth = 1
  2278. end
  2279. else
  2280. tempwidth = 0
  2281. end
  2282. if (tempwidth > 0)
  2283. bytes = ret
  2284. @rl_outstream.write(new[0,bytes])
  2285. @_rl_last_c_pos = tempwidth
  2286. @_rl_last_v_pos+=1
  2287. if old[ostart] != ?\0
  2288. case @encoding
  2289. when 'E'
  2290. wc = old[ostart..-1].scan(/./me)[0]
  2291. ret = wc.length
  2292. when 'S'
  2293. wc = old[ostart..-1].scan(/./ms)[0]
  2294. ret = wc.length
  2295. when 'U'
  2296. wc = old[ostart..-1].scan(/./mu)[0]
  2297. ret = wc.length
  2298. when 'X'
  2299. wc = old[ostart..-1].force_encoding(@encoding_name)[0]
  2300. ret = wc.bytesize
  2301. end
  2302. else
  2303. ret = 0
  2304. end
  2305. if (ret != 0 && bytes != 0)
  2306. if ret != bytes
  2307. len = old[ostart..-1].index(0.chr,ret)
  2308. old[ostart+bytes,len-ret] = old[ostart+ret,len-ret]
  2309. end
  2310. old[ostart,bytes] = new[0,bytes]
  2311. end
  2312. else
  2313. @rl_outstream.write(' ')
  2314. @_rl_last_c_pos = 1
  2315. @_rl_last_v_pos+=1
  2316. if (old[ostart] != ?\0 && new[0] != ?\0)
  2317. old[ostart] = new[0]
  2318. end
  2319. end
  2320. else
  2321. if (new[0] != ?\0)
  2322. @rl_outstream.write(new[0,1])
  2323. else
  2324. @rl_outstream.write(' ')
  2325. end
  2326. @_rl_last_c_pos = 1
  2327. @_rl_last_v_pos+=1
  2328. if (old[ostart]!= ?\0 && new[0] != ?\0)
  2329. old[ostart] = new[0]
  2330. end
  2331. end
  2332. end
  2333. # Find first difference.
  2334. if (!@rl_byte_oriented)
  2335. # See if the old line is a subset of the new line, so that the
  2336. # only change is adding characters.
  2337. if (index = old.index(0.chr)) && omax+ostart>index
  2338. omax = index - ostart
  2339. end
  2340. if (index = new.index(0.chr)) && nmax>index
  2341. nmax = index
  2342. end
  2343. temp = (omax < nmax) ? omax : nmax
  2344. if old[ostart,temp]==new[0,temp]
  2345. ofd = temp
  2346. nfd = temp
  2347. else
  2348. if (omax == nmax && new[0,omax]==old[ostart,omax])
  2349. ofd = omax
  2350. nfd = nmax
  2351. else
  2352. new_offset = 0
  2353. old_offset = ostart
  2354. ofd = 0
  2355. nfd = 0
  2356. while(ofd < omax && old[ostart+ofd] != ?\0 &&
  2357. _rl_compare_chars(old, old_offset, new, new_offset))
  2358. old_offset = _rl_find_next_mbchar(old, old_offset, 1, MB_FIND_ANY)
  2359. new_offset = _rl_find_next_mbchar(new, new_offset, 1, MB_FIND_ANY)
  2360. ofd = old_offset - ostart
  2361. nfd = new_offset
  2362. end
  2363. end
  2364. end
  2365. else
  2366. ofd = 0
  2367. nfd = 0
  2368. while(ofd < omax && old[ostart+ofd] != ?\0 && old[ostart+ofd] == new[nfd])
  2369. ofd += 1
  2370. nfd += 1
  2371. end
  2372. end
  2373. # Move to the end of the screen line. ND and OD are used to keep track
  2374. # of the distance between ne and new and oe and old, respectively, to
  2375. # move a subtraction out of each loop.
  2376. oe = old.index(0.chr,ostart+ofd) - ostart
  2377. if oe.nil? || oe>omax
  2378. oe = omax
  2379. end
  2380. ne = new.index(0.chr,nfd)
  2381. if ne.nil? || ne>omax
  2382. ne = nmax
  2383. end
  2384. # If no difference, continue to next line.
  2385. if (ofd == oe && nfd == ne)
  2386. return
  2387. end
  2388. wsatend = true # flag for trailing whitespace
  2389. if (!@rl_byte_oriented)
  2390. ols = _rl_find_prev_mbchar(old, ostart+oe, MB_FIND_ANY) - ostart
  2391. nls = _rl_find_prev_mbchar(new, ne, MB_FIND_ANY)
  2392. while ((ols > ofd) && (nls > nfd))
  2393. if (!_rl_compare_chars(old, ostart+ols, new, nls))
  2394. break
  2395. end
  2396. if (old[ostart+ols] == ?\x20)
  2397. wsatend = false
  2398. end
  2399. ols = _rl_find_prev_mbchar(old, ols+ostart, MB_FIND_ANY) - ostart
  2400. nls = _rl_find_prev_mbchar(new, nls, MB_FIND_ANY)
  2401. end
  2402. else
  2403. ols = oe - 1 # find last same
  2404. nls = ne - 1
  2405. while ((ols > ofd) && (nls > nfd) && old[ostart+ols] == new[nls])
  2406. if (old[ostart+ols] != ?\x20 )
  2407. wsatend = false
  2408. end
  2409. ols-=1
  2410. nls-=1
  2411. end
  2412. end
  2413. if (wsatend)
  2414. ols = oe
  2415. nls = ne
  2416. elsif (!_rl_compare_chars(old, ostart+ols, new, nls))
  2417. if (old[ostart+ols] != ?\0) # don't step past the NUL
  2418. if !@rl_byte_oriented
  2419. ols = _rl_find_next_mbchar(old, ostart+ols, 1, MB_FIND_ANY) - ostart
  2420. else
  2421. ols+=1
  2422. end
  2423. end
  2424. if (new[nls] != ?\0 )
  2425. if !@rl_byte_oriented
  2426. nls = _rl_find_next_mbchar(new, nls, 1, MB_FIND_ANY)
  2427. else
  2428. nls+=1
  2429. end
  2430. end
  2431. end
  2432. # count of invisible characters in the current invisible line.
  2433. current_invis_chars = w_offset(current_line, @wrap_offset)
  2434. if (@_rl_last_v_pos != current_line)
  2435. _rl_move_vert(current_line)
  2436. if (@rl_byte_oriented && current_line == 0 && @visible_wrap_offset!=0)
  2437. @_rl_last_c_pos += @visible_wrap_offset
  2438. end
  2439. end
  2440. # If this is the first line and there are invisible characters in the
  2441. # prompt string, and the prompt string has not changed, and the current
  2442. # cursor position is before the last invisible character in the prompt,
  2443. # and the index of the character to move to is past the end of the prompt
  2444. # string, then redraw the entire prompt string. We can only do this
  2445. # reliably if the terminal supports a `cr' capability.
  2446. # This is not an efficiency hack -- there is a problem with redrawing
  2447. # portions of the prompt string if they contain terminal escape
  2448. # sequences (like drawing the `unbold' sequence without a corresponding
  2449. # `bold') that manifests itself on certain terminals.
  2450. lendiff = @local_prompt_len
  2451. if (current_line == 0 && !@_rl_horizontal_scroll_mode &&
  2452. @_rl_term_cr && lendiff > @prompt_visible_length && @_rl_last_c_pos > 0 &&
  2453. ofd >= lendiff && @_rl_last_c_pos < prompt_ending_index())
  2454. @rl_outstream.write(@_rl_term_cr)
  2455. _rl_output_some_chars(@local_prompt,0,lendiff)
  2456. if !@rl_byte_oriented
  2457. # We take wrap_offset into account here so we can pass correct
  2458. # information to _rl_move_cursor_relative.
  2459. @_rl_last_c_pos = _rl_col_width(@local_prompt, 0, lendiff) - @wrap_offset
  2460. @cpos_adjusted = true
  2461. else
  2462. @_rl_last_c_pos = lendiff
  2463. end
  2464. end
  2465. # When this function returns, _rl_last_c_pos is correct, and an absolute
  2466. # cursor postion in multibyte mode, but a buffer index when not in a
  2467. # multibyte locale.
  2468. _rl_move_cursor_relative(ofd, old, ostart)
  2469. if (current_line == 0 && !@rl_byte_oriented && @_rl_last_c_pos == @prompt_physical_chars)
  2470. @cpos_adjusted = true
  2471. end
  2472. # if (len (new) > len (old))
  2473. # lendiff == difference in buffer
  2474. # col_lendiff == difference on screen
  2475. # When not using multibyte characters, these are equal
  2476. lendiff = (nls - nfd) - (ols - ofd)
  2477. if !@rl_byte_oriented
  2478. col_lendiff = _rl_col_width(new, nfd, nls) - _rl_col_width(old, ostart+ofd, ostart+ols)
  2479. else
  2480. col_lendiff = lendiff
  2481. end
  2482. # If we are changing the number of invisible characters in a line, and
  2483. # the spot of first difference is before the end of the invisible chars,
  2484. # lendiff needs to be adjusted.
  2485. if (current_line == 0 && !@_rl_horizontal_scroll_mode &&
  2486. current_invis_chars != @visible_wrap_offset)
  2487. if !@rl_byte_oriented
  2488. lendiff += @visible_wrap_offset - current_invis_chars
  2489. col_lendiff += @visible_wrap_offset - current_invis_chars
  2490. else
  2491. lendiff += @visible_wrap_offset - current_invis_chars
  2492. col_lendiff = lendiff
  2493. end
  2494. end
  2495. # Insert (diff (len (old), len (new)) ch.
  2496. temp = ne - nfd
  2497. if !@rl_byte_oriented
  2498. col_temp = _rl_col_width(new,nfd,ne)
  2499. else
  2500. col_temp = temp
  2501. end
  2502. if (col_lendiff > 0) # XXX - was lendiff
  2503. # Non-zero if we're increasing the number of lines.
  2504. gl = current_line >= @_rl_vis_botlin && inv_botlin > @_rl_vis_botlin
  2505. # Sometimes it is cheaper to print the characters rather than
  2506. # use the terminal's capabilities. If we're growing the number
  2507. # of lines, make sure we actually cause the new line to wrap
  2508. # around on auto-wrapping terminals.
  2509. if (@_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || @_rl_term_IC) && (!@_rl_term_autowrap || !gl))
  2510. # If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
  2511. # _rl_horizontal_scroll_mode == 1, inserting the characters with
  2512. # _rl_term_IC or _rl_term_ic will screw up the screen because of the
  2513. # invisible characters. We need to just draw them.
  2514. if (old[ostart+ols] != ?\0 && (!@_rl_horizontal_scroll_mode || @_rl_last_c_pos > 0 ||
  2515. lendiff <= @prompt_visible_length || current_invis_chars==0))
  2516. insert_some_chars(new[nfd..-1], lendiff, col_lendiff)
  2517. @_rl_last_c_pos += col_lendiff
  2518. elsif ((@rl_byte_oriented) && old[ostart+ols] == ?\0 && lendiff > 0)
  2519. # At the end of a line the characters do not have to
  2520. # be "inserted". They can just be placed on the screen.
  2521. # However, this screws up the rest of this block, which
  2522. # assumes you've done the insert because you can.
  2523. _rl_output_some_chars(new,nfd, lendiff)
  2524. @_rl_last_c_pos += col_lendiff
  2525. else
  2526. # We have horizontal scrolling and we are not inserting at
  2527. # the end. We have invisible characters in this line. This
  2528. # is a dumb update.
  2529. _rl_output_some_chars(new,nfd, temp)
  2530. @_rl_last_c_pos += col_temp
  2531. return
  2532. end
  2533. # Copy (new) chars to screen from first diff to last match.
  2534. temp = nls - nfd
  2535. if ((temp - lendiff) > 0)
  2536. _rl_output_some_chars(new,(nfd + lendiff),temp - lendiff)
  2537. # XXX -- this bears closer inspection. Fixes a redisplay bug
  2538. # reported against bash-3.0-alpha by Andreas Schwab involving
  2539. # multibyte characters and prompt strings with invisible
  2540. # characters, but was previously disabled.
  2541. @_rl_last_c_pos += _rl_col_width(new,nfd+lendiff, nfd+lendiff+temp-col_lendiff)
  2542. end
  2543. else
  2544. # cannot insert chars, write to EOL
  2545. _rl_output_some_chars(new,nfd, temp)
  2546. @_rl_last_c_pos += col_temp
  2547. # If we're in a multibyte locale and were before the last invisible
  2548. # char in the current line (which implies we just output some invisible
  2549. # characters) we need to adjust _rl_last_c_pos, since it represents
  2550. # a physical character position.
  2551. end
  2552. else # Delete characters from line.
  2553. # If possible and inexpensive to use terminal deletion, then do so.
  2554. if (@_rl_term_dc && (2 * col_temp) >= -col_lendiff)
  2555. # If all we're doing is erasing the invisible characters in the
  2556. # prompt string, don't bother. It screws up the assumptions
  2557. # about what's on the screen.
  2558. if (@_rl_horizontal_scroll_mode && @_rl_last_c_pos == 0 &&
  2559. -lendiff == @visible_wrap_offset)
  2560. col_lendiff = 0
  2561. end
  2562. if (col_lendiff!=0)
  2563. delete_chars(-col_lendiff) # delete (diff) characters
  2564. end
  2565. # Copy (new) chars to screen from first diff to last match
  2566. temp = nls - nfd
  2567. if (temp > 0)
  2568. _rl_output_some_chars(new,nfd, temp)
  2569. @_rl_last_c_pos += _rl_col_width(new,nfd,nfd+temp)
  2570. end
  2571. # Otherwise, print over the existing material.
  2572. else
  2573. if (temp > 0)
  2574. _rl_output_some_chars(new,nfd, temp)
  2575. @_rl_last_c_pos += col_temp # XXX
  2576. end
  2577. lendiff = (oe) - (ne)
  2578. if !@rl_byte_oriented
  2579. col_lendiff = _rl_col_width(old, ostart, ostart+oe) - _rl_col_width(new, 0, ne)
  2580. else
  2581. col_lendiff = lendiff
  2582. end
  2583. if (col_lendiff!=0)
  2584. if (@_rl_term_autowrap && current_line < inv_botlin)
  2585. space_to_eol(col_lendiff)
  2586. else
  2587. _rl_clear_to_eol(col_lendiff)
  2588. end
  2589. end
  2590. end
  2591. end
  2592. end
  2593. # Basic redisplay algorithm.
  2594. def rl_redisplay()
  2595. return if !@readline_echoing_p
  2596. _rl_wrapped_multicolumn = 0
  2597. @rl_display_prompt ||= ""
  2598. if (@invisible_line.nil? || @vis_lbreaks.nil?)
  2599. init_line_structures(0)
  2600. rl_on_new_line()
  2601. end
  2602. # Draw the line into the buffer.
  2603. @cpos_buffer_position = -1
  2604. line = @invisible_line
  2605. out = inv_botlin = 0
  2606. # Mark the line as modified or not. We only do this for history
  2607. # lines.
  2608. modmark = 0
  2609. if (@_rl_mark_modified_lines && current_history() && @rl_undo_list)
  2610. line[out] = '*'
  2611. out += 1
  2612. line[out] = 0.chr
  2613. modmark = 1
  2614. end
  2615. # If someone thought that the redisplay was handled, but the currently
  2616. # visible line has a different modification state than the one about
  2617. # to become visible, then correct the caller's misconception.
  2618. if (@visible_line[0] != @invisible_line[0])
  2619. @rl_display_fixed = false
  2620. end
  2621. # If the prompt to be displayed is the `primary' readline prompt (the
  2622. # one passed to readline()), use the values we have already expanded.
  2623. # If not, use what's already in rl_display_prompt. WRAP_OFFSET is the
  2624. # number of non-visible characters in the prompt string.
  2625. if (@rl_display_prompt == @rl_prompt || @local_prompt)
  2626. if (@local_prompt_prefix && @forced_display)
  2627. _rl_output_some_chars(@local_prompt_prefix,0,@local_prompt_prefix.length)
  2628. end
  2629. if (@local_prompt_len > 0)
  2630. temp = @local_prompt_len + out + 2
  2631. if (temp >= @line_size)
  2632. @line_size = (temp + 1024) - (temp % 1024)
  2633. if @visible_line.length >= @line_size
  2634. @visible_line = @visible_line[0,@line_size]
  2635. else
  2636. @visible_line += 0.chr * (@line_size-@visible_line.length)
  2637. end
  2638. if @invisible_line.length >= @line_size
  2639. @invisible_line = @invisible_line[0,@line_size]
  2640. else
  2641. @invisible_line += 0.chr * (@line_size-@invisible_line.length)
  2642. end
  2643. if @encoding=='X'
  2644. @visible_line.force_encoding('ASCII-8BIT')
  2645. @invisible_line.force_encoding('ASCII-8BIT')
  2646. end
  2647. line = @invisible_line
  2648. end
  2649. line[out,@local_prompt_len] = @local_prompt
  2650. out += @local_prompt_len
  2651. end
  2652. line[out] = 0.chr
  2653. @wrap_offset = @local_prompt_len - @prompt_visible_length
  2654. else
  2655. prompt_this_line = @rl_display_prompt.rindex("\n")
  2656. if prompt_this_line.nil?
  2657. prompt_this_line = 0
  2658. else
  2659. prompt_this_line+=1
  2660. pmtlen = prompt_this_line # temp var
  2661. if (@forced_display)
  2662. _rl_output_some_chars(@rl_display_prompt,0,pmtlen)
  2663. # Make sure we are at column zero even after a newline,
  2664. #regardless of the state of terminal output processing.
  2665. if (pmtlen < 2 || @rl_display_prompt[prompt_this_line-2] != ?\r)
  2666. cr()
  2667. end
  2668. end
  2669. end
  2670. @prompt_physical_chars = pmtlen = @rl_display_prompt.length - prompt_this_line
  2671. temp = pmtlen + out + 2
  2672. if (temp >= @line_size)
  2673. @line_size = (temp + 1024) - (temp % 1024)
  2674. if @visible_line.length >= @line_size
  2675. @visible_line = @visible_line[0,@line_size]
  2676. else
  2677. @visible_line += 0.chr * (@line_size-@visible_line.length)
  2678. end
  2679. if @invisible_line.length >= @line_size
  2680. @invisible_line = @invisible_line[0,@line_size]
  2681. else
  2682. @invisible_line += 0.chr * (@line_size-@invisible_line.length)
  2683. end
  2684. if @encoding=='X'
  2685. @visible_line.force_encoding('ASCII-8BIT')
  2686. @invisible_line.force_encoding('ASCII-8BIT')
  2687. end
  2688. line = @invisible_line
  2689. end
  2690. line[out,pmtlen] = @rl_display_prompt[prompt_this_line,pmtlen]
  2691. out += pmtlen
  2692. line[out] = 0.chr
  2693. @wrap_offset = @prompt_invis_chars_first_line = 0
  2694. end
  2695. # inv_lbreaks[i] is where line i starts in the buffer.
  2696. @inv_lbreaks[newlines = 0] = 0
  2697. lpos = @prompt_physical_chars + modmark
  2698. @_rl_wrapped_line = Array.new(@visible_line.length,0)
  2699. num = 0
  2700. # prompt_invis_chars_first_line is the number of invisible characters in
  2701. # the first physical line of the prompt.
  2702. # wrap_offset - prompt_invis_chars_first_line is the number of invis
  2703. # chars on the second line.
  2704. # what if lpos is already >= _rl_screenwidth before we start drawing the
  2705. # contents of the command line?
  2706. while (lpos >= @_rl_screenwidth)
  2707. # fix from Darin Johnson <darin@acuson.com> for prompt string with
  2708. # invisible characters that is longer than the screen width. The
  2709. # prompt_invis_chars_first_line variable could be made into an array
  2710. # saying how many invisible characters there are per line, but that's
  2711. # probably too much work for the benefit gained. How many people have
  2712. # prompts that exceed two physical lines?
  2713. # Additional logic fix from Edward Catmur <ed@catmur.co.uk>
  2714. if (!@rl_byte_oriented)
  2715. n0 = num
  2716. temp = @local_prompt_len
  2717. while (num < temp)
  2718. z = _rl_col_width(@local_prompt, n0, num)
  2719. if (z > @_rl_screenwidth)
  2720. num = _rl_find_prev_mbchar(@local_prompt, num, MB_FIND_ANY)
  2721. break
  2722. elsif (z == @_rl_screenwidth)
  2723. break
  2724. end
  2725. num+=1
  2726. end
  2727. temp = num
  2728. else
  2729. temp = ((newlines + 1) * @_rl_screenwidth)
  2730. end
  2731. # Now account for invisible characters in the current line.
  2732. temp += (@local_prompt_prefix.nil? ? ((newlines == 0) ? @prompt_invis_chars_first_line :
  2733. ((newlines == 1) ? @wrap_offset : 0)) :
  2734. ((newlines == 0) ? @wrap_offset : 0))
  2735. @inv_lbreaks[newlines+=1] = temp
  2736. if !@rl_byte_oriented
  2737. lpos -= _rl_col_width(@local_prompt, n0, num)
  2738. else
  2739. lpos -= @_rl_screenwidth
  2740. end
  2741. end
  2742. @prompt_last_screen_line = newlines
  2743. # Draw the rest of the line (after the prompt) into invisible_line, keeping
  2744. # track of where the cursor is (cpos_buffer_position), the number of the line containing
  2745. # the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
  2746. # It maintains an array of line breaks for display (inv_lbreaks).
  2747. # This handles expanding tabs for display and displaying meta characters.
  2748. lb_linenum = 0
  2749. _in = 0
  2750. if !@rl_byte_oriented && @rl_end>0
  2751. case @encoding
  2752. when 'E'
  2753. wc = @rl_line_buffer[0,@rl_end].scan(/./me)[0]
  2754. wc_bytes = wc ? wc.length : 1
  2755. when 'S'
  2756. wc = @rl_line_buffer[0,@rl_end].scan(/./ms)[0]
  2757. wc_bytes = wc ? wc.length : 1
  2758. when 'U'
  2759. wc = @rl_line_buffer[0,@rl_end].scan(/./mu)[0]
  2760. wc_bytes = wc ? wc.length : 1
  2761. when 'X'
  2762. wc = @rl_line_buffer[0,@rl_end].force_encoding(@encoding_name)[0]
  2763. wc_bytes = wc ? wc.bytesize : 1
  2764. end
  2765. else
  2766. wc_bytes = 1
  2767. end
  2768. while(_in < @rl_end)
  2769. c = @rl_line_buffer[_in,1]
  2770. if(c == 0.chr)
  2771. @rl_end = _in
  2772. break
  2773. end
  2774. if (!@rl_byte_oriented)
  2775. case @encoding
  2776. when 'U'
  2777. wc_width = wc && wc.unpack('U').first >= 0x1000 ? 2 : 1
  2778. when 'X'
  2779. wc_width = wc && wc.ord > 0x1000 ? 2 : 1
  2780. else
  2781. wc_width = wc ? wc.length : 1
  2782. end
  2783. end
  2784. if (out + 8 >= @line_size) # XXX - 8 for \t
  2785. @line_size *= 2
  2786. if @visible_line.length>=@line_size
  2787. @visible_line = @visible_line[0,@line_size]
  2788. else
  2789. @visible_line += 0.chr * (@line_size-@visible_line.length)
  2790. end
  2791. if @invisible_line.length>=@line_size
  2792. @invisible_line = @invisible_line[0,@line_size]
  2793. else
  2794. @invisible_line += 0.chr * (@line_size-@invisible_line.length)
  2795. end
  2796. line = @invisible_line
  2797. end
  2798. if (_in == @rl_point)
  2799. @cpos_buffer_position = out
  2800. lb_linenum = newlines
  2801. end
  2802. if (false && meta_char(c))
  2803. if (!@_rl_output_meta_chars && false)
  2804. line[out,4] = "\\%03o" % c.ord
  2805. if (lpos + 4 >= @_rl_screenwidth)
  2806. temp = @_rl_screenwidth - lpos
  2807. @inv_lbreaks[newlines+=1] = out + temp
  2808. lpos = 4 - temp
  2809. else
  2810. lpos += 4
  2811. end
  2812. out += 4
  2813. else
  2814. line[out] = c
  2815. out += 1
  2816. lpos+=1
  2817. if (lpos >= @_rl_screenwidth)
  2818. @inv_lbreaks[newlines+=1] = out
  2819. @_rl_wrapped_line[newlines] = _rl_wrapped_multicolumn
  2820. lpos = 0
  2821. end
  2822. end
  2823. elsif (c == "\t")
  2824. newout = out + 8 - lpos % 8
  2825. temp = newout - out
  2826. if (lpos + temp >= @_rl_screenwidth)
  2827. temp2 = @_rl_screenwidth - lpos
  2828. @inv_lbreaks[newlines+=1] = out + temp2
  2829. lpos = temp - temp2
  2830. while (out < newout)
  2831. line[out] = ' '
  2832. out += 1
  2833. end
  2834. else
  2835. while (out < newout)
  2836. line[out] = ' '
  2837. out += 1
  2838. end
  2839. lpos += temp
  2840. end
  2841. elsif (c == "\n" && !@_rl_horizontal_scroll_mode && @_rl_term_up)
  2842. line[out] = 0.chr # XXX - sentinel
  2843. out += 1
  2844. @inv_lbreaks[newlines+=1] = out
  2845. lpos = 0
  2846. elsif (ctrl_char(c) || c == RUBOUT)
  2847. line[out] = '^'
  2848. out += 1
  2849. lpos+=1
  2850. if (lpos >= @_rl_screenwidth)
  2851. @inv_lbreaks[newlines+=1] = out
  2852. @_rl_wrapped_line[newlines] = _rl_wrapped_multicolumn
  2853. lpos = 0
  2854. end
  2855. line[out] = ctrl_char(c) ? (c[0].ord|0x40).chr.upcase : '?'
  2856. out += 1
  2857. lpos+=1
  2858. if (lpos >= @_rl_screenwidth)
  2859. @inv_lbreaks[newlines+=1] = out
  2860. @_rl_wrapped_line[newlines] = _rl_wrapped_multicolumn
  2861. lpos = 0
  2862. end
  2863. else
  2864. if (!@rl_byte_oriented)
  2865. _rl_wrapped_multicolumn = 0
  2866. if (@_rl_screenwidth < lpos + wc_width)
  2867. for i in lpos ... @_rl_screenwidth
  2868. # The space will be removed in update_line()
  2869. line[out] = ' '
  2870. out += 1
  2871. _rl_wrapped_multicolumn+=1
  2872. lpos+=1
  2873. if (lpos >= @_rl_screenwidth)
  2874. @inv_lbreaks[newlines+=1] = out
  2875. @_rl_wrapped_line[newlines] = _rl_wrapped_multicolumn
  2876. lpos = 0
  2877. end
  2878. end
  2879. end
  2880. if (_in == @rl_point)
  2881. @cpos_buffer_position = out
  2882. lb_linenum = newlines
  2883. end
  2884. line[out,wc_bytes] = @rl_line_buffer[_in,wc_bytes]
  2885. out += wc_bytes
  2886. for i in 0 ... wc_width
  2887. lpos+=1
  2888. if (lpos >= @_rl_screenwidth)
  2889. @inv_lbreaks[newlines+=1] = out
  2890. @_rl_wrapped_line[newlines] = _rl_wrapped_multicolumn
  2891. lpos = 0
  2892. end
  2893. end
  2894. else
  2895. line[out] = c
  2896. out += 1
  2897. lpos+=1
  2898. if (lpos >= @_rl_screenwidth)
  2899. @inv_lbreaks[newlines+=1] = out
  2900. @_rl_wrapped_line[newlines] = _rl_wrapped_multicolumn
  2901. lpos = 0
  2902. end
  2903. end
  2904. end
  2905. if (!@rl_byte_oriented)
  2906. _in += wc_bytes
  2907. case @encoding
  2908. when 'E'
  2909. wc = @rl_line_buffer[_in,@rl_end - _in].scan(/./me)[0]
  2910. wc_bytes = wc ? wc.length : 1
  2911. when 'S'
  2912. wc = @rl_line_buffer[_in,@rl_end - _in].scan(/./ms)[0]
  2913. wc_bytes = wc ? wc.length : 1
  2914. when 'U'
  2915. wc = @rl_line_buffer[_in,@rl_end - _in].scan(/./mu)[0]
  2916. wc_bytes = wc ? wc.length : 1
  2917. when 'X'
  2918. wc = @rl_line_buffer[_in,@rl_end - _in].force_encoding(@encoding_name)[0]
  2919. wc_bytes = wc ? wc.bytesize : 1
  2920. end
  2921. else
  2922. _in+=1
  2923. end
  2924. end
  2925. line[out] = 0.chr
  2926. if (@cpos_buffer_position < 0)
  2927. @cpos_buffer_position = out
  2928. lb_linenum = newlines
  2929. end
  2930. inv_botlin = lb_botlin = newlines
  2931. @inv_lbreaks[newlines+1] = out
  2932. cursor_linenum = lb_linenum
  2933. # CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
  2934. # CURSOR_LINENUM == line number where the cursor should be placed.
  2935. # PWP: now is when things get a bit hairy. The visible and invisible
  2936. # line buffers are really multiple lines, which would wrap every
  2937. # (screenwidth - 1) characters. Go through each in turn, finding
  2938. # the changed region and updating it. The line order is top to bottom.
  2939. # If we can move the cursor up and down, then use multiple lines,
  2940. # otherwise, let long lines display in a single terminal line, and
  2941. # horizontally scroll it.
  2942. if (!@_rl_horizontal_scroll_mode && @_rl_term_up)
  2943. if (!@rl_display_fixed || @forced_display)
  2944. @forced_display = false
  2945. # If we have more than a screenful of material to display, then
  2946. # only display a screenful. We should display the last screen,
  2947. # not the first.
  2948. if (out >= @_rl_screenchars)
  2949. if (!@rl_byte_oriented)
  2950. out = _rl_find_prev_mbchar(line, @_rl_screenchars, MB_FIND_ANY)
  2951. else
  2952. out = @_rl_screenchars - 1
  2953. end
  2954. end
  2955. # The first line is at character position 0 in the buffer. The
  2956. # second and subsequent lines start at inv_lbreaks[N], offset by
  2957. # OFFSET (which has already been calculated above).
  2958. # For each line in the buffer, do the updating display.
  2959. for linenum in 0 .. inv_botlin
  2960. # This can lead us astray if we execute a program that changes
  2961. #the locale from a non-multibyte to a multibyte one.
  2962. o_cpos = @_rl_last_c_pos
  2963. @cpos_adjusted = false
  2964. update_line(@visible_line,vis_pos(linenum), inv_line(linenum), linenum,
  2965. vis_llen(linenum), inv_llen(linenum), inv_botlin)
  2966. if (linenum == 0 && !@rl_byte_oriented &&
  2967. !@cpos_adjusted &&
  2968. @_rl_last_c_pos != o_cpos &&
  2969. @_rl_last_c_pos > @wrap_offset &&
  2970. o_cpos < @prompt_last_invisible)
  2971. @_rl_last_c_pos -= @wrap_offset
  2972. end
  2973. # If this is the line with the prompt, we might need to
  2974. # compensate for invisible characters in the new line. Do
  2975. # this only if there is not more than one new line (which
  2976. # implies that we completely overwrite the old visible line)
  2977. # and the new line is shorter than the old. Make sure we are
  2978. # at the end of the new line before clearing.
  2979. if (linenum == 0 &&
  2980. inv_botlin == 0 && @_rl_last_c_pos == out &&
  2981. (@wrap_offset > @visible_wrap_offset) &&
  2982. (@_rl_last_c_pos < @visible_first_line_len))
  2983. if !@rl_byte_oriented
  2984. nleft = @_rl_screenwidth - @_rl_last_c_pos
  2985. else
  2986. nleft = @_rl_screenwidth + @wrap_offset - @_rl_last_c_pos
  2987. end
  2988. if (nleft!=0)
  2989. _rl_clear_to_eol(nleft)
  2990. end
  2991. end
  2992. # Since the new first line is now visible, save its length.
  2993. if (linenum == 0)
  2994. @visible_first_line_len = (inv_botlin > 0) ? @inv_lbreaks[1] : out - @wrap_offset
  2995. end
  2996. end
  2997. # We may have deleted some lines. If so, clear the left over
  2998. # blank ones at the bottom out.
  2999. if (@_rl_vis_botlin > inv_botlin)
  3000. while(linenum <= @_rl_vis_botlin)
  3001. tt = vis_chars(linenum)
  3002. _rl_move_vert(linenum)
  3003. _rl_move_cursor_relative(0, tt)
  3004. _rl_clear_to_eol((linenum == @_rl_vis_botlin) ? tt.length : @_rl_screenwidth)
  3005. linenum += 1
  3006. end
  3007. end
  3008. @_rl_vis_botlin = inv_botlin
  3009. # CHANGED_SCREEN_LINE is set to 1 if we have moved to a
  3010. # different screen line during this redisplay.
  3011. changed_screen_line = @_rl_last_v_pos != cursor_linenum
  3012. if (changed_screen_line)
  3013. _rl_move_vert(cursor_linenum)
  3014. # If we moved up to the line with the prompt using _rl_term_up,
  3015. # the physical cursor position on the screen stays the same,
  3016. # but the buffer position needs to be adjusted to account
  3017. # for invisible characters.
  3018. if (@rl_byte_oriented && cursor_linenum == 0 && @wrap_offset!=0)
  3019. @_rl_last_c_pos += @wrap_offset
  3020. end
  3021. end
  3022. # We have to reprint the prompt if it contains invisible
  3023. # characters, since it's not generally OK to just reprint
  3024. # the characters from the current cursor position. But we
  3025. # only need to reprint it if the cursor is before the last
  3026. # invisible character in the prompt string.
  3027. nleft = @prompt_visible_length + @wrap_offset
  3028. if (cursor_linenum == 0 && @wrap_offset > 0 && @_rl_last_c_pos > 0 &&
  3029. @_rl_last_c_pos < prompt_ending_index() && @local_prompt)
  3030. if (@_rl_term_cr)
  3031. @rl_outstream.write(@_rl_term_cr)
  3032. end
  3033. _rl_output_some_chars(@local_prompt,0,nleft)
  3034. if !@rl_byte_oriented
  3035. @_rl_last_c_pos = _rl_col_width(@local_prompt, 0, nleft) - @wrap_offset
  3036. else
  3037. @_rl_last_c_pos = nleft
  3038. end
  3039. end
  3040. # Where on that line? And where does that line start
  3041. # in the buffer?
  3042. pos = @inv_lbreaks[cursor_linenum]
  3043. # nleft == number of characters in the line buffer between the
  3044. # start of the line and the desired cursor position.
  3045. nleft = @cpos_buffer_position - pos
  3046. # NLEFT is now a number of characters in a buffer. When in a
  3047. # multibyte locale, however, _rl_last_c_pos is an absolute cursor
  3048. # position that doesn't take invisible characters in the prompt
  3049. # into account. We use a fudge factor to compensate.
  3050. # Since _rl_backspace() doesn't know about invisible characters in the
  3051. # prompt, and there's no good way to tell it, we compensate for
  3052. # those characters here and call _rl_backspace() directly.
  3053. if (@wrap_offset!=0 && cursor_linenum == 0 && nleft < @_rl_last_c_pos)
  3054. # TX == new physical cursor position in multibyte locale.
  3055. if !@rl_byte_oriented
  3056. tx = _rl_col_width(@visible_line, pos, pos+nleft) - @visible_wrap_offset
  3057. else
  3058. tx = nleft
  3059. end
  3060. if (@_rl_last_c_pos > tx)
  3061. _rl_backspace(@_rl_last_c_pos - tx) # XXX
  3062. @_rl_last_c_pos = tx
  3063. end
  3064. end
  3065. # We need to note that in a multibyte locale we are dealing with
  3066. # _rl_last_c_pos as an absolute cursor position, but moving to a
  3067. # point specified by a buffer position (NLEFT) that doesn't take
  3068. # invisible characters into account.
  3069. if !@rl_byte_oriented
  3070. _rl_move_cursor_relative(nleft, @invisible_line,pos)
  3071. elsif (nleft != @_rl_last_c_pos)
  3072. _rl_move_cursor_relative(nleft, @invisible_line,pos)
  3073. end
  3074. end
  3075. else # Do horizontal scrolling.
  3076. # Always at top line.
  3077. @_rl_last_v_pos = 0
  3078. # Compute where in the buffer the displayed line should start. This
  3079. # will be LMARGIN.
  3080. # The number of characters that will be displayed before the cursor.
  3081. ndisp = @cpos_buffer_position - @wrap_offset
  3082. nleft = @prompt_visible_length + @wrap_offset
  3083. # Where the new cursor position will be on the screen. This can be
  3084. # longer than SCREENWIDTH; if it is, lmargin will be adjusted.
  3085. phys_c_pos = @cpos_buffer_position - (@last_lmargin!=0 ? @last_lmargin : @wrap_offset)
  3086. t = @_rl_screenwidth / 3
  3087. # If the number of characters had already exceeded the screenwidth,
  3088. #last_lmargin will be > 0.
  3089. # If the number of characters to be displayed is more than the screen
  3090. # width, compute the starting offset so that the cursor is about
  3091. # two-thirds of the way across the screen.
  3092. if (phys_c_pos > @_rl_screenwidth - 2)
  3093. lmargin = @cpos_buffer_position - (2 * t)
  3094. if (lmargin < 0)
  3095. lmargin = 0
  3096. end
  3097. # If the left margin would be in the middle of a prompt with
  3098. # invisible characters, don't display the prompt at all.
  3099. if (@wrap_offset!=0 && lmargin > 0 && lmargin < nleft)
  3100. lmargin = nleft
  3101. end
  3102. elsif (ndisp < @_rl_screenwidth - 2) # XXX - was -1
  3103. lmargin = 0
  3104. elsif (phys_c_pos < 1)
  3105. # If we are moving back towards the beginning of the line and
  3106. # the last margin is no longer correct, compute a new one.
  3107. lmargin = ((@cpos_buffer_position - 1) / t) * t # XXX
  3108. if (@wrap_offset!=0 && lmargin > 0 && lmargin < nleft)
  3109. lmargin = nleft
  3110. end
  3111. else
  3112. lmargin = @last_lmargin
  3113. end
  3114. # If the first character on the screen isn't the first character
  3115. #in the display line, indicate this with a special character.
  3116. if (lmargin > 0)
  3117. line[lmargin] = '<'
  3118. end
  3119. # If SCREENWIDTH characters starting at LMARGIN do not encompass
  3120. # the whole line, indicate that with a special character at the
  3121. # right edge of the screen. If LMARGIN is 0, we need to take the
  3122. # wrap offset into account.
  3123. t = lmargin + m_offset(lmargin, @wrap_offset) + @_rl_screenwidth
  3124. if (t < out)
  3125. line[t - 1] = '>'
  3126. end
  3127. if (!@rl_display_fixed || @forced_display || lmargin != @last_lmargin)
  3128. @forced_display = false
  3129. update_line(@visible_line,@last_lmargin,@invisible_line[lmargin..-1],
  3130. 0,
  3131. @_rl_screenwidth + @visible_wrap_offset,
  3132. @_rl_screenwidth + (lmargin ? 0 : @wrap_offset),
  3133. 0)
  3134. # If the visible new line is shorter than the old, but the number
  3135. # of invisible characters is greater, and we are at the end of
  3136. # the new line, we need to clear to eol.
  3137. t = @_rl_last_c_pos - m_offset(lmargin, @wrap_offset)
  3138. if ((m_offset(lmargin, @wrap_offset) > @visible_wrap_offset) &&
  3139. (@_rl_last_c_pos == out) &&
  3140. t < @visible_first_line_len)
  3141. nleft = @_rl_screenwidth - t
  3142. _rl_clear_to_eol(nleft)
  3143. end
  3144. @visible_first_line_len = out - lmargin - m_offset(lmargin, @wrap_offset)
  3145. if (@visible_first_line_len > @_rl_screenwidth)
  3146. @visible_first_line_len = @_rl_screenwidth
  3147. end
  3148. _rl_move_cursor_relative(@cpos_buffer_position - lmargin, @invisible_line ,lmargin)
  3149. @last_lmargin = lmargin
  3150. end
  3151. end
  3152. @rl_outstream.flush
  3153. # Swap visible and non-visible lines.
  3154. @visible_line,@invisible_line = @invisible_line,@visible_line
  3155. @vis_lbreaks,@inv_lbreaks = @inv_lbreaks,@vis_lbreaks
  3156. @rl_display_fixed = false
  3157. # If we are displaying on a single line, and last_lmargin is > 0, we
  3158. # are not displaying any invisible characters, so set visible_wrap_offset
  3159. # to 0.
  3160. if (@_rl_horizontal_scroll_mode && @last_lmargin!=0)
  3161. @visible_wrap_offset = 0
  3162. else
  3163. @visible_wrap_offset = @wrap_offset
  3164. end
  3165. end
  3166. # Tell the update routines that we have moved onto a new (empty) line.
  3167. def rl_on_new_line()
  3168. if (@visible_line)
  3169. @visible_line[0] = 0.chr
  3170. end
  3171. @_rl_last_c_pos = @_rl_last_v_pos = 0
  3172. @_rl_vis_botlin = @last_lmargin = 0
  3173. if (@vis_lbreaks)
  3174. @vis_lbreaks[0] = @vis_lbreaks[1] = 0
  3175. end
  3176. @visible_wrap_offset = 0
  3177. 0
  3178. end
  3179. def rl_reset_line_state()
  3180. rl_on_new_line()
  3181. @rl_display_prompt = @rl_prompt ? @rl_prompt : ""
  3182. @forced_display = true
  3183. 0
  3184. end
  3185. def _rl_vi_initialize_line
  3186. rl_unsetstate(RL_STATE_VICMDONCE)
  3187. end
  3188. # Initialize readline (and terminal if not already).
  3189. def rl_initialize()
  3190. # If we have never been called before, initialize the
  3191. # terminal and data structures.
  3192. if (!@rl_initialized)
  3193. rl_setstate(RL_STATE_INITIALIZING)
  3194. readline_initialize_everything()
  3195. rl_unsetstate(RL_STATE_INITIALIZING)
  3196. @rl_initialized = true
  3197. rl_setstate(RL_STATE_INITIALIZED)
  3198. end
  3199. # Initalize the current line information.
  3200. _rl_init_line_state()
  3201. # We aren't done yet. We haven't even gotten started yet!
  3202. @rl_done = false
  3203. rl_unsetstate(RL_STATE_DONE)
  3204. # Tell the history routines what is going on.
  3205. _rl_start_using_history()
  3206. # Make the display buffer match the state of the line.
  3207. rl_reset_line_state()
  3208. # No such function typed yet.
  3209. @rl_last_func = nil
  3210. # Parsing of key-bindings begins in an enabled state.
  3211. @_rl_parsing_conditionalized_out = 0
  3212. if (@rl_editing_mode == @vi_mode)
  3213. _rl_vi_initialize_line()
  3214. end
  3215. # Each line starts in insert mode (the default).
  3216. _rl_set_insert_mode(RL_IM_DEFAULT, 1)
  3217. return 0
  3218. end
  3219. def _rl_strip_prompt(pmt)
  3220. return expand_prompt(pmt).first
  3221. end
  3222. def _rl_col_width(string,start,_end)
  3223. return 0 if _end <= start
  3224. index = string.index(0.chr)
  3225. str = index ? string[0,index] : string
  3226. width = 0
  3227. case @encoding
  3228. when 'N'
  3229. return (_end - start)
  3230. when 'U'
  3231. str[start ... _end].scan(/./mu).each {|s| width += s.unpack('U').first >= 0x1000 ? 2 : 1 }
  3232. when 'S'
  3233. str[start ... _end].scan(/./ms).each {|s| width += s.length }
  3234. when 'E'
  3235. str[start ... _end].scan(/./me).each {|s| width += s.length }
  3236. when 'X'
  3237. str[start ... _end].force_encoding(@encoding_name).codepoints.each {|s| width += s > 0x1000 ? 2 : 1 }
  3238. end
  3239. width
  3240. end
  3241. # Write COUNT characters from STRING to the output stream.
  3242. def _rl_output_some_chars(string,start,count)
  3243. @_rl_out_stream.write(string[start,count])
  3244. end
  3245. # Tell the update routines that we have moved onto a new line with the
  3246. # prompt already displayed. Code originally from the version of readline
  3247. # distributed with CLISP. rl_expand_prompt must have already been called
  3248. # (explicitly or implicitly). This still doesn't work exactly right.
  3249. def rl_on_new_line_with_prompt()
  3250. # Initialize visible_line and invisible_line to ensure that they can hold
  3251. # the already-displayed prompt.
  3252. prompt_size = @rl_prompt.length + 1
  3253. init_line_structures(prompt_size)
  3254. # Make sure the line structures hold the already-displayed prompt for
  3255. # redisplay.
  3256. lprompt = @local_prompt ? @local_prompt : @rl_prompt
  3257. @visible_line[0,lprompt.length] = lprompt
  3258. @invisible_line[0,lprompt.length] = lprompt
  3259. # If the prompt contains newlines, take the last tail.
  3260. prompt_last_line = rl_prompt.rindex("\n")
  3261. if prompt_last_line.nil?
  3262. prompt_last_line = @rl_prompt
  3263. else
  3264. prompt_last_line = @rl_prompt[prompt_last_line..-1]
  3265. end
  3266. l = prompt_last_line.length
  3267. if !@rl_byte_oriented
  3268. @_rl_last_c_pos = _rl_col_width(prompt_last_line, 0, l)
  3269. else
  3270. @_rl_last_c_pos = l
  3271. end
  3272. # Dissect prompt_last_line into screen lines. Note that here we have
  3273. # to use the real screenwidth. Readline's notion of screenwidth might be
  3274. # one less, see terminal.c.
  3275. real_screenwidth = @_rl_screenwidth + (@_rl_term_autowrap ? 0 : 1)
  3276. @_rl_last_v_pos = l / real_screenwidth
  3277. # If the prompt length is a multiple of real_screenwidth, we don't know
  3278. # whether the cursor is at the end of the last line, or already at the
  3279. # beginning of the next line. Output a newline just to be safe.
  3280. if (l > 0 && (l % real_screenwidth) == 0)
  3281. _rl_output_some_chars("\n",0,1)
  3282. end
  3283. @last_lmargin = 0
  3284. newlines = 0
  3285. i = 0
  3286. while (i <= l)
  3287. @_rl_vis_botlin = newlines
  3288. @vis_lbreaks[newlines] = i
  3289. newlines += 1
  3290. i += real_screenwidth
  3291. end
  3292. @vis_lbreaks[newlines] = l
  3293. @visible_wrap_offset = 0
  3294. @rl_display_prompt = @rl_prompt # XXX - make sure it's set
  3295. return 0
  3296. end
  3297. def readline_internal_setup()
  3298. @_rl_in_stream = @rl_instream
  3299. @_rl_out_stream = @rl_outstream
  3300. if (@rl_startup_hook)
  3301. send(@rl_startup_hook)
  3302. end
  3303. # If we're not echoing, we still want to at least print a prompt, because
  3304. # rl_redisplay will not do it for us. If the calling application has a
  3305. # custom redisplay function, though, let that function handle it.
  3306. if (!@readline_echoing_p && @rl_redisplay_function == :rl_redisplay)
  3307. if (@rl_prompt && !@rl_already_prompted)
  3308. nprompt = _rl_strip_prompt(@rl_prompt)
  3309. @_rl_out_stream.write(nprompt)
  3310. @_rl_out_stream.flush
  3311. end
  3312. else
  3313. if (@rl_prompt && @rl_already_prompted)
  3314. rl_on_new_line_with_prompt()
  3315. else
  3316. rl_on_new_line()
  3317. end
  3318. send(@rl_redisplay_function)
  3319. end
  3320. if (@rl_editing_mode == @vi_mode)
  3321. rl_vi_insertion_mode(1, 'i')
  3322. end
  3323. if (@rl_pre_input_hook)
  3324. send(@rl_pre_input_hook)
  3325. end
  3326. end
  3327. # Create a default argument.
  3328. def _rl_reset_argument()
  3329. @rl_numeric_arg = @rl_arg_sign = 1
  3330. @rl_explicit_arg = false
  3331. @_rl_argcxt = 0
  3332. end
  3333. # Ring the terminal bell.
  3334. def rl_ding()
  3335. if @MessageBeep
  3336. @MessageBeep.Call(0)
  3337. elsif @readline_echoing_p
  3338. if @_rl_bell_preference == VISIBLE_BELL
  3339. if (@_rl_visible_bell)
  3340. @_rl_out_stream.write(@_rl_visible_bell.chr)
  3341. else
  3342. $stderr.write("\007")
  3343. $stderr.flush
  3344. end
  3345. elsif @_rl_bell_preference == AUDIBLE_BELL
  3346. $stderr.write("\007")
  3347. $stderr.flush
  3348. end
  3349. return 0
  3350. end
  3351. return -1
  3352. end
  3353. def _rl_search_getchar(cxt)
  3354. # Read a key and decide how to proceed.
  3355. rl_setstate(RL_STATE_MOREINPUT)
  3356. c = cxt.lastc = rl_read_key()
  3357. rl_unsetstate(RL_STATE_MOREINPUT)
  3358. if !@rl_byte_oriented
  3359. cxt.mb = ""
  3360. c = cxt.lastc = _rl_read_mbstring(cxt.lastc, cxt.mb, MB_LEN_MAX)
  3361. end
  3362. c
  3363. end
  3364. def endsrch_char(c)
  3365. ((ctrl_char(c) || meta_char(c) || (c) == RUBOUT) && ((c) != "\C-G"))
  3366. end
  3367. # Process just-read character C according to isearch context CXT. Return
  3368. # -1 if the caller should just free the context and return, 0 if we should
  3369. # break out of the loop, and 1 if we should continue to read characters.
  3370. def _rl_isearch_dispatch(cxt, c)
  3371. f = nil
  3372. # Translate the keys we do something with to opcodes.
  3373. if (c && @_rl_keymap[c])
  3374. f = @_rl_keymap[c]
  3375. if (f == :rl_reverse_search_history)
  3376. cxt.lastc = (cxt.sflags & SF_REVERSE)!=0 ? -1 : -2
  3377. elsif (f == :rl_forward_search_history)
  3378. cxt.lastc = (cxt.sflags & SF_REVERSE)!=0 ? -2 : -1
  3379. elsif (f == :rl_rubout)
  3380. cxt.lastc = -3
  3381. elsif (c == "\C-G")
  3382. cxt.lastc = -4
  3383. elsif (c == "\C-W") # XXX
  3384. cxt.lastc = -5
  3385. elsif (c == "\C-Y") # XXX
  3386. cxt.lastc = -6
  3387. end
  3388. end
  3389. # The characters in isearch_terminators (set from the user-settable
  3390. # variable isearch-terminators) are used to terminate the search but
  3391. # not subsequently execute the character as a command. The default
  3392. # value is "\033\012" (ESC and C-J).
  3393. if (cxt.search_terminators.include?(cxt.lastc))
  3394. # ESC still terminates the search, but if there is pending
  3395. #input or if input arrives within 0.1 seconds (on systems
  3396. #with select(2)) it is used as a prefix character
  3397. #with rl_execute_next. WATCH OUT FOR THIS! This is intended
  3398. #to allow the arrow keys to be used like ^F and ^B are used
  3399. #to terminate the search and execute the movement command.
  3400. #XXX - since _rl_input_available depends on the application-
  3401. #settable keyboard timeout value, this could alternatively
  3402. #use _rl_input_queued(100000)
  3403. if (cxt.lastc == ESC && _rl_input_available())
  3404. rl_execute_next(ESC)
  3405. end
  3406. return (0)
  3407. end
  3408. if !@rl_byte_oriented
  3409. if (cxt.lastc.class == String && (cxt.mb.length == 1) && endsrch_char(cxt.lastc))
  3410. # This sets rl_pending_input to c; it will be picked up the next
  3411. # time rl_read_key is called.
  3412. rl_execute_next(cxt.lastc)
  3413. return (0)
  3414. end
  3415. elsif (cxt.lastc.class == String && endsrch_char(cxt.lastc))
  3416. # This sets rl_pending_input to LASTC; it will be picked up the next
  3417. # time rl_read_key is called.
  3418. rl_execute_next(cxt.lastc)
  3419. return (0)
  3420. end
  3421. # Now dispatch on the character. `Opcodes' affect the search string or
  3422. # state. Other characters are added to the string.
  3423. case (cxt.lastc)
  3424. # search again
  3425. when -1
  3426. if (cxt.search_string_index == 0)
  3427. if (last_isearch_string)
  3428. cxt.search_string_size = 64 + last_isearch_string_len
  3429. cxt.search_string = last_isearch_string.dup
  3430. cxt.search_string_index = last_isearch_string_len
  3431. rl_display_search(cxt.search_string, (cxt.sflags & SF_REVERSE)!=0, -1)
  3432. else
  3433. return (1)
  3434. end
  3435. elsif (cxt.sflags & SF_REVERSE)!=0
  3436. cxt.sline_index-=1
  3437. elsif (cxt.sline_index != cxt.sline_len)
  3438. cxt.sline_index+=1
  3439. else
  3440. rl_ding()
  3441. end
  3442. # switch directions
  3443. when -2
  3444. cxt.direction = -cxt.direction
  3445. if (cxt.direction < 0)
  3446. cxt.sflags |= SF_REVERSE
  3447. else
  3448. cxt.sflags &= ~SF_REVERSE
  3449. end
  3450. # delete character from search string.
  3451. when -3 # C-H, DEL
  3452. # This is tricky. To do this right, we need to keep a
  3453. # stack of search positions for the current search, with
  3454. # sentinels marking the beginning and end. But this will
  3455. # do until we have a real isearch-undo.
  3456. if (cxt.search_string_index == 0)
  3457. rl_ding()
  3458. else
  3459. cxt.search_string[cxt.search_string_index-=1] = 0.chr
  3460. end
  3461. when -4 # C-G, abort
  3462. rl_replace_line(cxt.lines[cxt.save_line], false)
  3463. @rl_point = cxt.save_point
  3464. @rl_mark = cxt.save_mark
  3465. rl_restore_prompt()
  3466. rl_clear_message()
  3467. return -1
  3468. when -5 # C-W
  3469. # skip over portion of line we already matched and yank word
  3470. wstart = @rl_point + cxt.search_string_index
  3471. if (wstart >= @rl_end)
  3472. rl_ding()
  3473. else
  3474. # if not in a word, move to one.
  3475. cval = _rl_char_value(@rl_line_buffer, wstart)
  3476. if (!_rl_walphabetic(cval))
  3477. rl_ding()
  3478. else
  3479. if !@rl_byte_oriented
  3480. n = _rl_find_next_mbchar(@rl_line_buffer, wstart, 1, MB_FIND_NONZERO)
  3481. else
  3482. n = wstart+1
  3483. end
  3484. while (n < @rl_end)
  3485. cval = _rl_char_value(@rl_line_buffer, n)
  3486. break if !_rl_walphabetic(cval)
  3487. if !@rl_byte_oriented
  3488. n = _rl_find_next_mbchar(@rl_line_buffer, n, 1, MB_FIND_NONZERO)
  3489. else
  3490. n = n+1
  3491. end
  3492. end
  3493. wlen = n - wstart + 1
  3494. if (cxt.search_string_index + wlen + 1 >= cxt.search_string_size)
  3495. cxt.search_string_size += wlen + 1
  3496. end
  3497. cxt.search_string[cxt.search_string_index..-1] = @rl_line_buffer[wstart,wlen]
  3498. cxt.search_string_index += wlen
  3499. end
  3500. end
  3501. when -6 # C-Y
  3502. # skip over portion of line we already matched and yank rest
  3503. wstart = @rl_point + cxt.search_string_index
  3504. if (wstart >= @rl_end)
  3505. rl_ding()
  3506. else
  3507. n = @rl_end - wstart + 1
  3508. if (cxt.search_string_index + n + 1 >= cxt.search_string_size)
  3509. cxt.search_string_size += n + 1
  3510. end
  3511. cxt.search_string[cxt.search_string_index..-1] = @rl_line_buffer[wstart,n]
  3512. end
  3513. # Add character to search string and continue search.
  3514. else
  3515. if (cxt.search_string_index + 2 >= cxt.search_string_size)
  3516. cxt.search_string_size += 128
  3517. end
  3518. if !@rl_byte_oriented
  3519. for j in 0 ... cxt.mb.length
  3520. cxt.search_string << cxt.mb[j,1]
  3521. cxt.search_string_index += 1
  3522. end
  3523. else
  3524. cxt.search_string << c
  3525. cxt.search_string_index += 1
  3526. end
  3527. end
  3528. while (cxt.sflags &= ~(SF_FOUND|SF_FAILED))!=0
  3529. limit = cxt.sline_len - cxt.search_string_index + 1
  3530. # Search the current line.
  3531. while ((cxt.sflags & SF_REVERSE)!=0 ? (cxt.sline_index >= 0) : (cxt.sline_index < limit))
  3532. if (cxt.search_string[0,cxt.search_string_index] == cxt.sline[cxt.sline_index,cxt.search_string_index])
  3533. cxt.sflags |= SF_FOUND
  3534. break
  3535. else
  3536. cxt.sline_index += cxt.direction
  3537. end
  3538. end
  3539. break if (cxt.sflags & SF_FOUND)!=0
  3540. # Move to the next line, but skip new copies of the line
  3541. # we just found and lines shorter than the string we're
  3542. # searching for.
  3543. begin
  3544. # Move to the next line.
  3545. cxt.history_pos += cxt.direction
  3546. # At limit for direction?
  3547. if ((cxt.sflags & SF_REVERSE)!=0 ? (cxt.history_pos < 0) : (cxt.history_pos == cxt.hlen))
  3548. cxt.sflags |= SF_FAILED
  3549. break
  3550. end
  3551. # We will need these later.
  3552. cxt.sline = cxt.lines[cxt.history_pos]
  3553. cxt.sline_len = cxt.sline.length
  3554. end while ((cxt.prev_line_found && cxt.prev_line_found == cxt.lines[cxt.history_pos]) ||
  3555. (cxt.search_string_index > cxt.sline_len))
  3556. break if (cxt.sflags & SF_FAILED)!=0
  3557. # Now set up the line for searching...
  3558. cxt.sline_index = (cxt.sflags & SF_REVERSE)!=0 ? cxt.sline_len - cxt.search_string_index : 0
  3559. end
  3560. if (cxt.sflags & SF_FAILED)!=0
  3561. # We cannot find the search string. Ding the bell.
  3562. rl_ding()
  3563. cxt.history_pos = cxt.last_found_line
  3564. return 1
  3565. end
  3566. # We have found the search string. Just display it. But don't
  3567. # actually move there in the history list until the user accepts
  3568. # the location.
  3569. if (cxt.sflags & SF_FOUND)!=0
  3570. cxt.prev_line_found = cxt.lines[cxt.history_pos]
  3571. rl_replace_line(cxt.lines[cxt.history_pos], false)
  3572. @rl_point = cxt.sline_index
  3573. cxt.last_found_line = cxt.history_pos
  3574. rl_display_search(cxt.search_string, (cxt.sflags & SF_REVERSE)!=0, (cxt.history_pos == cxt.save_line) ? -1 : cxt.history_pos)
  3575. end
  3576. 1
  3577. end
  3578. # How to clear things from the "echo-area".
  3579. def rl_clear_message()
  3580. @rl_display_prompt = @rl_prompt
  3581. if (@msg_saved_prompt)
  3582. rl_restore_prompt()
  3583. @msg_saved_prompt = nil
  3584. end
  3585. send(@rl_redisplay_function)
  3586. 0
  3587. end
  3588. def _rl_isearch_fini(cxt)
  3589. # First put back the original state.
  3590. @rl_line_buffer = cxt.lines[cxt.save_line].dup
  3591. rl_restore_prompt()
  3592. # Save the search string for possible later use.
  3593. @last_isearch_string = cxt.search_string
  3594. @last_isearch_string_len = cxt.search_string_index
  3595. cxt.search_string = nil
  3596. if (cxt.last_found_line < cxt.save_line)
  3597. rl_get_previous_history(cxt.save_line - cxt.last_found_line, 0)
  3598. else
  3599. rl_get_next_history(cxt.last_found_line - cxt.save_line, 0)
  3600. end
  3601. # If the string was not found, put point at the end of the last matching
  3602. # line. If last_found_line == orig_line, we didn't find any matching
  3603. # history lines at all, so put point back in its original position.
  3604. if (cxt.sline_index < 0)
  3605. if (cxt.last_found_line == cxt.save_line)
  3606. cxt.sline_index = cxt.save_point
  3607. else
  3608. cxt.sline_index = @rl_line_buffer.delete(0.chr).length
  3609. end
  3610. @rl_mark = cxt.save_mark
  3611. end
  3612. @rl_point = cxt.sline_index
  3613. # Don't worry about where to put the mark here; rl_get_previous_history
  3614. # and rl_get_next_history take care of it.
  3615. rl_clear_message()
  3616. end
  3617. def _rl_isearch_cleanup(cxt, r)
  3618. if (r >= 0)
  3619. _rl_isearch_fini(cxt)
  3620. end
  3621. ctx = nil
  3622. @_rl_iscxt = nil
  3623. rl_unsetstate(RL_STATE_ISEARCH)
  3624. r != 0
  3625. end
  3626. # Do the command associated with KEY in MAP.
  3627. # If the associated command is really a keymap, then read
  3628. # another key, and dispatch into that map.
  3629. def _rl_dispatch(key, map)
  3630. @_rl_dispatching_keymap = map
  3631. return _rl_dispatch_subseq(key, map, false)
  3632. end
  3633. def _rl_dispatch_subseq(key, map, got_subseq)
  3634. func = map[key]
  3635. if (func)
  3636. @rl_executing_keymap = map
  3637. @rl_dispatching = true
  3638. rl_setstate(RL_STATE_DISPATCHING)
  3639. send(map[key],@rl_numeric_arg * @rl_arg_sign, key)
  3640. rl_unsetstate(RL_STATE_DISPATCHING)
  3641. @rl_dispatching = false
  3642. if (@rl_pending_input == 0 && map[key] != :rl_digit_argument)
  3643. @rl_last_func = map[key]
  3644. end
  3645. else
  3646. if(map.keys.detect{|x| x =~ /^#{Regexp.escape(key)}/})
  3647. key += _rl_subseq_getchar(key)
  3648. return _rl_dispatch_subseq(key,map,got_subseq)
  3649. elsif(key.length>1 && key[1] < ?\x7F)
  3650. _rl_abort_internal()
  3651. return -1
  3652. else
  3653. @rl_dispatching = true
  3654. rl_setstate(RL_STATE_DISPATCHING)
  3655. send(:rl_insert,@rl_numeric_arg * @rl_arg_sign, key)
  3656. rl_unsetstate(RL_STATE_DISPATCHING)
  3657. @rl_dispatching = false
  3658. end
  3659. end
  3660. 0
  3661. end
  3662. # Add KEY to the buffer of characters to be read. Returns 1 if the
  3663. # character was stuffed correctly; 0 otherwise.
  3664. def rl_stuff_char(key)
  3665. return 0 if (ibuffer_space() == 0)
  3666. if (key == EOF)
  3667. key = NEWLINE
  3668. @rl_pending_input = EOF
  3669. rl_setstate(RL_STATE_INPUTPENDING)
  3670. end
  3671. @ibuffer[@push_index] = key
  3672. @push_index += 1
  3673. if (@push_index >= @ibuffer_len)
  3674. @push_index = 0
  3675. end
  3676. return 1
  3677. end
  3678. begin
  3679. # Cygwin will look like Windows, but we want to treat it like a Posix OS:
  3680. raise LoadError, "Cygwin is a Posix OS." if RUBY_PLATFORM =~ /\bcygwin\b/i
  3681. raise LoadError, "Not Windows" if RUBY_PLATFORM !~ /mswin|mingw/
  3682. if RUBY_VERSION < '1.9.1' or defined?(IRONRUBY_VERSION)
  3683. require 'Win32API'
  3684. else
  3685. require 'dl'
  3686. class Win32API
  3687. DLL = {}
  3688. TYPEMAP = {"0" => DL::TYPE_VOID, "S" => DL::TYPE_VOIDP, "I" => DL::TYPE_LONG}
  3689. def initialize(dllname, func, import, export = "0")
  3690. @proto = [import].join.tr("VPpNnLlIi", "0SSI").sub(/^(.)0*$/, '\1')
  3691. handle = DLL[dllname] ||= DL.dlopen(dllname)
  3692. @func = DL::CFunc.new(handle[func], TYPEMAP[export.tr("VPpNnLlIi", "0SSI")], func)
  3693. end
  3694. def call(*args)
  3695. import = @proto.split("")
  3696. args.each_with_index do |x, i|
  3697. args[i], = [x == 0 ? nil : x].pack("p").unpack("l!*") if import[i] == "S"
  3698. args[i], = [x].pack("I").unpack("i") if import[i] == "I"
  3699. end
  3700. ret, = @func.call(args)
  3701. return ret || 0
  3702. end
  3703. alias Call call
  3704. end
  3705. end
  3706. STD_OUTPUT_HANDLE = -11
  3707. STD_INPUT_HANDLE = -10
  3708. KEY_EVENT = 1
  3709. VK_SHIFT = 0x10
  3710. VK_MENU = 0x12
  3711. VK_LMENU = 0xA4
  3712. VK_RMENU = 0xA5
  3713. LEFT_CTRL_PRESSED = 0x0008
  3714. RIGHT_CTRL_PRESSED = 0x0004
  3715. LEFT_ALT_PRESSED = 0x0002
  3716. RIGHT_ALT_PRESSED = 0x0001
  3717. @getch = Win32API.new("msvcrt", "_getch", [], 'I')
  3718. @kbhit = Win32API.new("msvcrt", "_kbhit", [], 'I')
  3719. @GetStdHandle = Win32API.new("kernel32","GetStdHandle",['L'],'L')
  3720. @SetConsoleCursorPosition = Win32API.new("kernel32","SetConsoleCursorPosition",['L','L'],'L')
  3721. @GetConsoleScreenBufferInfo = Win32API.new("kernel32","GetConsoleScreenBufferInfo",['L','P'],'L')
  3722. @FillConsoleOutputCharacter = Win32API.new("kernel32","FillConsoleOutputCharacter",['L','L','L','L','P'],'L')
  3723. @ReadConsoleInput = Win32API.new( "kernel32", "ReadConsoleInput", ['L', 'P', 'L', 'P'], 'L' )
  3724. @MessageBeep = Win32API.new("user32","MessageBeep",['L'],'L')
  3725. @GetKeyboardState = Win32API.new("user32","GetKeyboardState",['P'],'L')
  3726. @GetKeyState = Win32API.new("user32","GetKeyState",['L'],'L')
  3727. @hConsoleHandle = @GetStdHandle.Call(STD_OUTPUT_HANDLE)
  3728. @hConsoleInput = @GetStdHandle.Call(STD_INPUT_HANDLE)
  3729. @pending_count = 0
  3730. @pending_key = nil
  3731. begin
  3732. case `chcp`.scan(/\d+$/).first.to_i
  3733. when 936,949,950,51932,51936,50225
  3734. @encoding = "E"
  3735. when 932,50220,50221,20222
  3736. @encoding = "S"
  3737. when 65001
  3738. @encoding = "U"
  3739. else
  3740. @encoding = "N"
  3741. end
  3742. rescue
  3743. @encoding = "N"
  3744. end
  3745. def rl_getc(stream)
  3746. c = @getch.Call
  3747. alt = (@GetKeyState.call(VK_LMENU) & 0x80) != 0
  3748. if c==0 || c==0xE0
  3749. r = c.chr + @getch.Call.chr
  3750. else
  3751. r = c.chr
  3752. end
  3753. r = "\e"+r if alt
  3754. r
  3755. end
  3756. def rl_gather_tyi()
  3757. chars_avail = @kbhit.Call
  3758. return 0 if(chars_avail<=0)
  3759. k = send(@rl_getc_function,@rl_instream)
  3760. rl_stuff_char(k)
  3761. return 1
  3762. end
  3763. rescue LoadError # If we're not on Windows try...
  3764. if ENV["LANG"] =~ /\.UTF-8/
  3765. @encoding = "U"
  3766. elsif ENV["LANG"] =~ /\.EUC/
  3767. @encoding = "E"
  3768. elsif ENV["LANG"] =~ /\.SHIFT/
  3769. @encoding = "S"
  3770. else
  3771. @encoding = "N"
  3772. end
  3773. def rl_getc(stream)
  3774. begin
  3775. c = stream.read(1)
  3776. rescue Errno::EINTR
  3777. c = rl_getc(stream)
  3778. end
  3779. return c ? c : EOF
  3780. end
  3781. def rl_gather_tyi()
  3782. chars_avail = 0
  3783. result = select([@rl_instream],nil,nil,0.1)
  3784. return 0 if result.nil?
  3785. k = send(@rl_getc_function,@rl_instream)
  3786. rl_stuff_char(k)
  3787. return 1
  3788. end
  3789. end
  3790. if defined? ''.getbyte
  3791. @encoding = "X" # ruby 1.9.x or greater
  3792. @encoding_name = Encoding.default_external.to_s
  3793. end
  3794. @rl_byte_oriented = @encoding == "N"
  3795. # Read a key, including pending input.
  3796. def rl_read_key()
  3797. @rl_key_sequence_length+=1
  3798. if (@rl_pending_input!=0)
  3799. c = @rl_pending_input
  3800. rl_clear_pending_input()
  3801. else
  3802. # If the user has an event function, then call it periodically.
  3803. if (@rl_event_hook)
  3804. while (@rl_event_hook && (c=rl_get_char()).nil?)
  3805. send(@rl_event_hook)
  3806. if (@rl_done) # XXX - experimental
  3807. return ("\n")
  3808. end
  3809. if (rl_gather_tyi() < 0) # XXX - EIO
  3810. @rl_done = true
  3811. return ("\n")
  3812. end
  3813. end
  3814. else
  3815. if (c=rl_get_char()).nil?
  3816. c = send(@rl_getc_function,@rl_instream)
  3817. end
  3818. end
  3819. end
  3820. return (c)
  3821. end
  3822. # Return the amount of space available in the buffer for stuffing
  3823. # characters.
  3824. def ibuffer_space()
  3825. if (@pop_index > @push_index)
  3826. return (@pop_index - @push_index - 1)
  3827. else
  3828. return (@ibuffer_len - (@push_index - @pop_index))
  3829. end
  3830. end
  3831. # Get a key from the buffer of characters to be read.
  3832. # Return the key in KEY.
  3833. # Result is KEY if there was a key, or 0 if there wasn't.
  3834. def rl_get_char()
  3835. if (@push_index == @pop_index)
  3836. return nil
  3837. end
  3838. key = @ibuffer[@pop_index]
  3839. @pop_index += 1
  3840. if (@pop_index >= @ibuffer_len)
  3841. @pop_index = 0
  3842. end
  3843. return key
  3844. end
  3845. # Stuff KEY into the *front* of the input buffer.
  3846. # Returns non-zero if successful, zero if there is
  3847. # no space left in the buffer.
  3848. def _rl_unget_char(key)
  3849. if (ibuffer_space()!=0)
  3850. @pop_index-=1
  3851. if (@pop_index < 0)
  3852. @pop_index = @ibuffer_len - 1
  3853. end
  3854. @ibuffer[@pop_index] = key
  3855. return (1)
  3856. end
  3857. return (0)
  3858. end
  3859. def _rl_subseq_getchar(key)
  3860. if (key == ESC)
  3861. rl_setstate(RL_STATE_METANEXT)
  3862. end
  3863. rl_setstate(RL_STATE_MOREINPUT)
  3864. k = rl_read_key()
  3865. rl_unsetstate(RL_STATE_MOREINPUT)
  3866. if (key == ESC)
  3867. rl_unsetstate(RL_STATE_METANEXT)
  3868. end
  3869. return k
  3870. end
  3871. # Clear to the end of the line. COUNT is the minimum
  3872. # number of character spaces to clear,
  3873. def _rl_clear_to_eol(count)
  3874. if (@_rl_term_clreol)
  3875. @rl_outstream.write(@_rl_term_clreol)
  3876. elsif (count!=0)
  3877. space_to_eol(count)
  3878. end
  3879. end
  3880. # Clear to the end of the line using spaces. COUNT is the minimum
  3881. # number of character spaces to clear,
  3882. def space_to_eol(count)
  3883. if @hConsoleHandle
  3884. csbi = 0.chr * 24
  3885. @GetConsoleScreenBufferInfo.Call(@hConsoleHandle,csbi)
  3886. cursor_pos = csbi[4,4].unpack('L').first
  3887. written = 0.chr * 4
  3888. @FillConsoleOutputCharacter.Call(@hConsoleHandle,0x20,count,cursor_pos,written)
  3889. else
  3890. @rl_outstream.write(' ' * count)
  3891. end
  3892. @_rl_last_c_pos += count
  3893. end
  3894. def _rl_clear_screen()
  3895. if (@_rl_term_clrpag)
  3896. @rl_outstream.write(@_rl_tirberm_clrpag)
  3897. else
  3898. rl_crlf()
  3899. end
  3900. end
  3901. # Move the cursor back.
  3902. def _rl_backspace(count)
  3903. if (@_rl_term_backspace)
  3904. @_rl_out_stream.write(@_rl_term_backspace * count)
  3905. else
  3906. @_rl_out_stream.write("\b"*count)
  3907. end
  3908. 0
  3909. end
  3910. # Move to the start of the next line.
  3911. def rl_crlf()
  3912. if (@_rl_term_cr)
  3913. @_rl_out_stream.write(@_rl_term_cr)
  3914. end
  3915. @_rl_out_stream.write("\n")
  3916. return 0
  3917. end
  3918. # Move to the start of the current line.
  3919. def cr()
  3920. if (@_rl_term_cr)
  3921. @_rl_out_stream.write(@_rl_term_cr)
  3922. @_rl_last_c_pos = 0
  3923. end
  3924. end
  3925. def _rl_erase_entire_line()
  3926. cr()
  3927. _rl_clear_to_eol(0)
  3928. cr()
  3929. @rl_outstream.flush
  3930. end
  3931. def _rl_internal_char_cleanup()
  3932. # In vi mode, when you exit insert mode, the cursor moves back
  3933. # over the previous character. We explicitly check for that here.
  3934. if (@rl_editing_mode == @vi_mode && @_rl_keymap == @vi_movement_keymap)
  3935. rl_vi_check()
  3936. end
  3937. if (@rl_num_chars_to_read!=0 && @rl_end >= @rl_num_chars_to_read)
  3938. send(@rl_redisplay_function)
  3939. @_rl_want_redisplay = false
  3940. rl_newline(1, "\n")
  3941. end
  3942. if (!@rl_done)
  3943. send(@rl_redisplay_function)
  3944. @_rl_want_redisplay = false
  3945. end
  3946. # If the application writer has told us to erase the entire line if
  3947. # the only character typed was something bound to rl_newline, do so.
  3948. if (@rl_erase_empty_line && @rl_done && @rl_last_func == :rl_newline &&
  3949. @rl_point == 0 && @rl_end == 0)
  3950. _rl_erase_entire_line()
  3951. end
  3952. end
  3953. def readline_internal_charloop()
  3954. lastc = -1
  3955. eof_found = false
  3956. while (!@rl_done)
  3957. lk = @_rl_last_command_was_kill
  3958. # send(rl_redisplay_function)
  3959. # @_rl_want_redisplay = false
  3960. if (@rl_pending_input == 0)
  3961. # Then initialize the argument and number of keys read.
  3962. _rl_reset_argument()
  3963. @rl_key_sequence_length = 0
  3964. end
  3965. rl_setstate(RL_STATE_READCMD)
  3966. c = rl_read_key()
  3967. rl_unsetstate(RL_STATE_READCMD)
  3968. # look at input.c:rl_getc() for the circumstances under which this will
  3969. #be returned; punt immediately on read error without converting it to
  3970. #a newline.
  3971. if (c == READERR)
  3972. eof_found = true
  3973. break
  3974. end
  3975. # EOF typed to a non-blank line is a <NL>.
  3976. if (c == EOF && @rl_end!=0)
  3977. c = NEWLINE
  3978. end
  3979. # The character _rl_eof_char typed to blank line, and not as the
  3980. #previous character is interpreted as EOF.
  3981. if (((c == @_rl_eof_char && lastc != c) || c == EOF) && @rl_end==0)
  3982. eof_found = true
  3983. break
  3984. end
  3985. lastc = c
  3986. if _rl_dispatch(c, @_rl_keymap)== -1
  3987. next
  3988. end
  3989. # If there was no change in _rl_last_command_was_kill, then no kill
  3990. #has taken place. Note that if input is pending we are reading
  3991. #a prefix command, so nothing has changed yet.
  3992. if (@rl_pending_input == 0 && lk == @_rl_last_command_was_kill)
  3993. @_rl_last_command_was_kill = false
  3994. end
  3995. _rl_internal_char_cleanup()
  3996. end
  3997. eof_found
  3998. end
  3999. # How to abort things.
  4000. def _rl_abort_internal()
  4001. rl_ding()
  4002. rl_clear_message()
  4003. _rl_reset_argument()
  4004. rl_clear_pending_input()
  4005. rl_unsetstate(RL_STATE_MACRODEF)
  4006. @rl_last_func = nil
  4007. #throw :readline_top_level
  4008. send(@rl_redisplay_function)
  4009. @_rl_want_redisplay = false
  4010. 0
  4011. end
  4012. def rl_abort(count, key)
  4013. _rl_abort_internal()
  4014. end
  4015. def rl_vi_check()
  4016. if (@rl_point!=0 && @rl_point == @rl_end)
  4017. @rl_point-=1
  4018. end
  4019. 0
  4020. end
  4021. def readline_internal_teardown(eof)
  4022. # Restore the original of this history line, iff the line that we
  4023. # are editing was originally in the history, AND the line has changed.
  4024. entry = current_history()
  4025. if (entry && @rl_undo_list)
  4026. temp = @rl_line_buffer.delete(0.chr).dup
  4027. rl_revert_line(1, 0)
  4028. entry = replace_history_entry(where_history(), @rl_line_buffer, nil)
  4029. entry = nil
  4030. @rl_line_buffer = temp+0.chr
  4031. temp = nil
  4032. end
  4033. # At any rate, it is highly likely that this line has an undo list. Get
  4034. # rid of it now.
  4035. if (@rl_undo_list)
  4036. rl_free_undo_list()
  4037. end
  4038. # Restore normal cursor, if available.
  4039. _rl_set_insert_mode(RL_IM_INSERT, 0)
  4040. (eof ? nil : @rl_line_buffer.delete(0.chr))
  4041. end
  4042. # Read a line of input from the global rl_instream, doing output on
  4043. # the global rl_outstream.
  4044. # If rl_prompt is non-null, then that is our prompt.
  4045. def readline_internal()
  4046. readline_internal_setup()
  4047. eof = readline_internal_charloop()
  4048. readline_internal_teardown(eof)
  4049. end
  4050. # Read a line of input. Prompt with PROMPT. An empty PROMPT means
  4051. # none. A return value of NULL means that EOF was encountered.
  4052. def readline(prompt)
  4053. # If we are at EOF return a NULL string.
  4054. if (@rl_pending_input == EOF)
  4055. rl_clear_pending_input()
  4056. return nil
  4057. end
  4058. rl_set_prompt(prompt)
  4059. rl_initialize()
  4060. @readline_echoing_p = true
  4061. if (@rl_prep_term_function)
  4062. send(@rl_prep_term_function,@_rl_meta_flag)
  4063. end
  4064. rl_set_signals()
  4065. value = readline_internal()
  4066. if(@rl_deprep_term_function)
  4067. send(@rl_deprep_term_function)
  4068. end
  4069. rl_clear_signals()
  4070. value
  4071. end
  4072. # Increase the size of RL_LINE_BUFFER until it has enough space to hold
  4073. # LEN characters.
  4074. def rl_extend_line_buffer(len)
  4075. while (len >= @rl_line_buffer.length)
  4076. @rl_line_buffer << 0.chr * DEFAULT_BUFFER_SIZE
  4077. end
  4078. @the_line = @rl_line_buffer
  4079. end
  4080. # Insert a string of text into the line at point. This is the only
  4081. # way that you should do insertion. _rl_insert_char () calls this
  4082. # function. Returns the number of characters inserted.
  4083. def rl_insert_text(string)
  4084. string.delete!(0.chr)
  4085. l = string.length
  4086. return 0 if (l == 0)
  4087. if (@rl_end + l >= @rl_line_buffer.length)
  4088. rl_extend_line_buffer(@rl_end + l)
  4089. end
  4090. @rl_line_buffer[@rl_point,0] = string
  4091. # Remember how to undo this if we aren't undoing something.
  4092. if (!@_rl_doing_an_undo)
  4093. # If possible and desirable, concatenate the undos.
  4094. if ((l == 1) &&
  4095. @rl_undo_list &&
  4096. (@rl_undo_list.what == UNDO_INSERT) &&
  4097. (@rl_undo_list.end == @rl_point) &&
  4098. (@rl_undo_list.end - @rl_undo_list.start < 20))
  4099. @rl_undo_list.end+=1
  4100. else
  4101. rl_add_undo(UNDO_INSERT, @rl_point, @rl_point + l, nil)
  4102. end
  4103. end
  4104. @rl_point += l
  4105. @rl_end += l
  4106. if @rl_line_buffer.length <= @rl_end
  4107. @rl_line_buffer << 0.chr * (@rl_end - @rl_line_buffer.length + 1)
  4108. else
  4109. @rl_line_buffer[@rl_end] = "\0"
  4110. end
  4111. l
  4112. end
  4113. def alloc_undo_entry(what, start, _end, text)
  4114. temp = Struct.new(:what,:start,:end,:text,:next).new
  4115. temp.what = what
  4116. temp.start = start
  4117. temp.end = _end
  4118. temp.text = text
  4119. temp.next = nil
  4120. temp
  4121. end
  4122. #* Remember how to undo something. Concatenate some undos if that
  4123. # seems right.
  4124. def rl_add_undo(what, start, _end, text)
  4125. temp = alloc_undo_entry(what, start, _end, text)
  4126. temp.next = @rl_undo_list
  4127. @rl_undo_list = temp
  4128. end
  4129. # Delete the string between FROM and TO. FROM is inclusive, TO is not.
  4130. # Returns the number of characters deleted.
  4131. def rl_delete_text(from, to)
  4132. # Fix it if the caller is confused.
  4133. if (from > to)
  4134. from,to = to,from
  4135. end
  4136. # fix boundaries
  4137. if (to > @rl_end)
  4138. to = @rl_end
  4139. if (from > to)
  4140. from = to
  4141. end
  4142. end
  4143. if (from < 0)
  4144. from = 0
  4145. end
  4146. text = rl_copy_text(from, to)
  4147. diff = to - from
  4148. @rl_line_buffer[from...to] = ''
  4149. @rl_line_buffer << 0.chr * diff
  4150. # Remember how to undo this delete.
  4151. if (!@_rl_doing_an_undo)
  4152. rl_add_undo(UNDO_DELETE, from, to, text)
  4153. else
  4154. text = nil
  4155. end
  4156. @rl_end -= diff
  4157. @rl_line_buffer[@rl_end] = 0.chr
  4158. return (diff)
  4159. end
  4160. def rl_copy_text(from, to)
  4161. return @rl_line_buffer[from...to]
  4162. end
  4163. # Fix up point so that it is within the line boundaries after killing
  4164. # text. If FIX_MARK_TOO is non-zero, the mark is forced within line
  4165. # boundaries also.
  4166. def __rl_fix_point(x)
  4167. if (x > @rl_end)
  4168. @rl_end
  4169. elsif (x < 0)
  4170. 0
  4171. else
  4172. x
  4173. end
  4174. end
  4175. def _rl_fix_point(fix_mark_too)
  4176. @rl_point = __rl_fix_point(@rl_point)
  4177. if (fix_mark_too)
  4178. @rl_mark = __rl_fix_point(@rl_mark)
  4179. end
  4180. end
  4181. # Begin a group. Subsequent undos are undone as an atomic operation.
  4182. def rl_begin_undo_group()
  4183. rl_add_undo(UNDO_BEGIN, 0, 0, nil)
  4184. @_rl_undo_group_level+=1
  4185. 0
  4186. end
  4187. # End an undo group started with rl_begin_undo_group ().
  4188. def rl_end_undo_group()
  4189. rl_add_undo(UNDO_END, 0, 0, nil)
  4190. @_rl_undo_group_level-=1
  4191. 0
  4192. end
  4193. def rl_free_undo_list()
  4194. replace_history_data(-1, @rl_undo_list, nil)
  4195. @rl_undo_list = nil
  4196. end
  4197. # Replace the contents of the line buffer between START and END with
  4198. # TEXT. The operation is undoable. To replace the entire line in an
  4199. # undoable mode, use _rl_replace_text(text, 0, rl_end)
  4200. def _rl_replace_text(text, start, _end)
  4201. rl_begin_undo_group()
  4202. rl_delete_text(start, _end + 1)
  4203. @rl_point = start
  4204. n = rl_insert_text(text)
  4205. rl_end_undo_group()
  4206. n
  4207. end
  4208. # Replace the current line buffer contents with TEXT. If CLEAR_UNDO is
  4209. # non-zero, we free the current undo list.
  4210. def rl_replace_line(text, clear_undo)
  4211. len = text.delete(0.chr).length
  4212. @rl_line_buffer = text.dup + 0.chr
  4213. @rl_end = len
  4214. if (clear_undo)
  4215. rl_free_undo_list()
  4216. end
  4217. _rl_fix_point(true)
  4218. end
  4219. # Replace the DATA in the specified history entries, replacing OLD with
  4220. # NEW. WHICH says which one(s) to replace: WHICH == -1 means to replace
  4221. # all of the history entries where entry->data == OLD; WHICH == -2 means
  4222. # to replace the `newest' history entry where entry->data == OLD; and
  4223. # WHICH >= 0 means to replace that particular history entry's data, as
  4224. # long as it matches OLD.
  4225. def replace_history_data(which,old, new)
  4226. new = new.dup if new
  4227. if (which < -2 || which >= @history_length || @history_length == 0 || @the_history.nil?)
  4228. return
  4229. end
  4230. if (which >= 0)
  4231. entry = @the_history[which]
  4232. if (entry && entry.data == old)
  4233. entry.data = new
  4234. end
  4235. return
  4236. end
  4237. last = -1
  4238. for i in 0 ... @history_length
  4239. entry = @the_history[i]
  4240. if entry.nil?
  4241. next
  4242. end
  4243. if (entry.data == old)
  4244. last = i
  4245. if (which == -1)
  4246. entry.data = new
  4247. end
  4248. end
  4249. end
  4250. if (which == -2 && last >= 0)
  4251. entry = @the_history[last]
  4252. entry.data = new # XXX - we don't check entry->old
  4253. end
  4254. end
  4255. # Move forward COUNT bytes.
  4256. def rl_forward_byte(count, key)
  4257. if (count < 0)
  4258. return (rl_backward_byte(-count, key))
  4259. end
  4260. if (count > 0)
  4261. _end = @rl_point + count
  4262. lend = @rl_end > 0 ? @rl_end - ((@rl_editing_mode == @vi_mode)?1:0) : @rl_end
  4263. if (_end > lend)
  4264. @rl_point = lend
  4265. rl_ding()
  4266. else
  4267. @rl_point = _end
  4268. end
  4269. end
  4270. if (@rl_end < 0)
  4271. @rl_end = 0
  4272. end
  4273. return 0
  4274. end
  4275. # Move forward COUNT characters.
  4276. def rl_forward_char(count, key)
  4277. if @rl_byte_oriented
  4278. return (rl_forward_byte(count, key))
  4279. end
  4280. if (count < 0)
  4281. return (rl_backward_char(-count, key))
  4282. end
  4283. if (count > 0)
  4284. point = _rl_find_next_mbchar(@rl_line_buffer, @rl_point, count, MB_FIND_NONZERO)
  4285. if (@rl_end <= point && @rl_editing_mode == @vi_mode)
  4286. point = _rl_find_prev_mbchar(@rl_line_buffer, @rl_end, MB_FIND_NONZERO)
  4287. end
  4288. if (@rl_point == point)
  4289. rl_ding()
  4290. end
  4291. @rl_point = point
  4292. if (@rl_end < 0)
  4293. @rl_end = 0
  4294. end
  4295. end
  4296. 0
  4297. end
  4298. # Backwards compatibility.
  4299. def rl_forward(count, key)
  4300. rl_forward_char(count, key)
  4301. end
  4302. # Move backward COUNT bytes.
  4303. def rl_backward_byte(count, key)
  4304. if (count < 0)
  4305. return (rl_forward_byte(-count, key))
  4306. end
  4307. if (count > 0)
  4308. if (@rl_point < count)
  4309. @rl_point = 0
  4310. rl_ding()
  4311. else
  4312. @rl_point -= count
  4313. end
  4314. end
  4315. if (@rl_point < 0)
  4316. @rl_point = 0
  4317. end
  4318. 0
  4319. end
  4320. # Move backward COUNT characters.
  4321. def rl_backward_char(count, key)
  4322. if @rl_byte_oriented
  4323. return (rl_backward_byte(count, key))
  4324. end
  4325. if (count < 0)
  4326. return (rl_forward_char(-count, key))
  4327. end
  4328. if (count > 0)
  4329. point = @rl_point
  4330. while (count > 0 && point > 0)
  4331. point = _rl_find_prev_mbchar(@rl_line_buffer, point, MB_FIND_NONZERO)
  4332. count-=1
  4333. end
  4334. if (count > 0)
  4335. @rl_point = 0
  4336. rl_ding()
  4337. else
  4338. @rl_point = point
  4339. end
  4340. end
  4341. 0
  4342. end
  4343. # Backwards compatibility.
  4344. def rl_backward(count, key)
  4345. rl_backward_char(count, key)
  4346. end
  4347. # Move to the beginning of the line.
  4348. def rl_beg_of_line(count, key)
  4349. @rl_point = 0
  4350. 0
  4351. end
  4352. # Move to the end of the line.
  4353. def rl_end_of_line(count, key)
  4354. @rl_point = @rl_end
  4355. 0
  4356. end
  4357. def _rl_char_value(buf,ind)
  4358. buf[ind,1]
  4359. end
  4360. @_rl_allow_pathname_alphabetic_chars = false
  4361. @pathname_alphabetic_chars = '/-_=~.#$'
  4362. def rl_alphabetic(c)
  4363. if c =~ /\w/
  4364. return true
  4365. end
  4366. return !!(@_rl_allow_pathname_alphabetic_chars &&
  4367. @pathname_alphabetic_chars[c])
  4368. end
  4369. def _rl_walphabetic(c)
  4370. rl_alphabetic(c)
  4371. end
  4372. # Move forward a word. We do what Emacs does. Handles multibyte chars.
  4373. def rl_forward_word(count, key)
  4374. if (count < 0)
  4375. return (rl_backward_word(-count, key))
  4376. end
  4377. while (count>0)
  4378. return 0 if (@rl_point == @rl_end)
  4379. # If we are not in a word, move forward until we are in one.
  4380. # Then, move forward until we hit a non-alphabetic character.
  4381. c = _rl_char_value(@rl_line_buffer, @rl_point)
  4382. if (!_rl_walphabetic(c))
  4383. if !@rl_byte_oriented
  4384. @rl_point = _rl_find_next_mbchar(@rl_line_buffer, @rl_point, 1, MB_FIND_NONZERO)
  4385. else
  4386. @rl_point += 1
  4387. end
  4388. while (@rl_point < @rl_end)
  4389. c = _rl_char_value(@rl_line_buffer, @rl_point)
  4390. if (_rl_walphabetic(c))
  4391. break
  4392. end
  4393. if !@rl_byte_oriented
  4394. @rl_point = _rl_find_next_mbchar(@rl_line_buffer, @rl_point, 1, MB_FIND_NONZERO)
  4395. else
  4396. @rl_point += 1
  4397. end
  4398. end
  4399. end
  4400. return 0 if (@rl_point == @rl_end)
  4401. if !@rl_byte_oriented
  4402. @rl_point = _rl_find_next_mbchar(@rl_line_buffer, @rl_point, 1, MB_FIND_NONZERO)
  4403. else
  4404. @rl_point += 1
  4405. end
  4406. while (@rl_point < @rl_end)
  4407. c = _rl_char_value(@rl_line_buffer, @rl_point)
  4408. if (!_rl_walphabetic(c))
  4409. break
  4410. end
  4411. if !@rl_byte_oriented
  4412. @rl_point = _rl_find_next_mbchar(@rl_line_buffer, @rl_point, 1, MB_FIND_NONZERO)
  4413. else
  4414. @rl_point += 1
  4415. end
  4416. end
  4417. count -= 1
  4418. end
  4419. 0
  4420. end
  4421. # Move backward a word. We do what Emacs does. Handles multibyte chars.
  4422. def rl_backward_word(count, key)
  4423. if (count < 0)
  4424. return (rl_forward_word(-count, key))
  4425. end
  4426. while (count>0)
  4427. return 0 if (@rl_point == 0)
  4428. # Like rl_forward_word (), except that we look at the characters
  4429. # just before point.
  4430. _p = !@rl_byte_oriented ? _rl_find_prev_mbchar(@rl_line_buffer, @rl_point, MB_FIND_NONZERO):(@rl_point-1)
  4431. c = _rl_char_value(@rl_line_buffer, _p)
  4432. if (!_rl_walphabetic(c))
  4433. @rl_point = _p
  4434. while (@rl_point > 0)
  4435. _p = !@rl_byte_oriented ? _rl_find_prev_mbchar(@rl_line_buffer, @rl_point, MB_FIND_NONZERO):(@rl_point-1)
  4436. c = _rl_char_value(@rl_line_buffer, _p)
  4437. if (_rl_walphabetic(c))
  4438. break
  4439. end
  4440. @rl_point = _p
  4441. end
  4442. end
  4443. while (@rl_point>0)
  4444. _p = !@rl_byte_oriented ? _rl_find_prev_mbchar(@rl_line_buffer, @rl_point, MB_FIND_NONZERO):(@rl_point-1)
  4445. c = _rl_char_value(@rl_line_buffer, _p)
  4446. if (!_rl_walphabetic(c))
  4447. break
  4448. else
  4449. @rl_point = _p
  4450. end
  4451. end
  4452. count -= 1
  4453. end
  4454. 0
  4455. end
  4456. # return the `current display line' of the cursor -- the number of lines to
  4457. # move up to get to the first screen line of the current readline line.
  4458. def _rl_current_display_line()
  4459. # Find out whether or not there might be invisible characters in the
  4460. # editing buffer.
  4461. if (@rl_display_prompt == @rl_prompt)
  4462. nleft = @_rl_last_c_pos - @_rl_screenwidth - @rl_visible_prompt_length
  4463. else
  4464. nleft = @_rl_last_c_pos - @_rl_screenwidth
  4465. end
  4466. if (nleft > 0)
  4467. ret = 1 + nleft / @_rl_screenwidth
  4468. else
  4469. ret = 0
  4470. end
  4471. ret
  4472. end
  4473. # Actually update the display, period.
  4474. def rl_forced_update_display()
  4475. if (@visible_line)
  4476. @visible_line.gsub!(/[^\x00]/,0.chr)
  4477. end
  4478. rl_on_new_line()
  4479. @forced_display=true if !@forced_display
  4480. send(@rl_redisplay_function)
  4481. 0
  4482. end
  4483. # Clear the current line. Numeric argument to C-l does this.
  4484. def rl_refresh_line(ignore1, ignore2)
  4485. curr_line = _rl_current_display_line()
  4486. _rl_move_vert(curr_line)
  4487. _rl_move_cursor_relative(0, @rl_line_buffer) # XXX is this right
  4488. _rl_clear_to_eol(0) # arg of 0 means to not use spaces
  4489. rl_forced_update_display()
  4490. @rl_display_fixed = true
  4491. 0
  4492. end
  4493. # C-l typed to a line without quoting clears the screen, and then reprints
  4494. # the prompt and the current input line. Given a numeric arg, redraw only
  4495. # the current line.
  4496. def rl_clear_screen(count, key)
  4497. if (@rl_explicit_arg)
  4498. rl_refresh_line(count, key)
  4499. return 0
  4500. end
  4501. _rl_clear_screen() # calls termcap function to clear screen
  4502. rl_forced_update_display()
  4503. @rl_display_fixed = true
  4504. 0
  4505. end
  4506. # Restore the _rl_saved_line_for_history if there is one.
  4507. def rl_maybe_unsave_line()
  4508. if (@_rl_saved_line_for_history)
  4509. # Can't call with `1' because rl_undo_list might point to an undo
  4510. # list from a history entry, as in rl_replace_from_history() below.
  4511. rl_replace_line(@_rl_saved_line_for_history.line, false)
  4512. @rl_undo_list = @_rl_saved_line_for_history.data
  4513. @_rl_saved_line_for_history = nil
  4514. @rl_point = @rl_end # rl_replace_line sets rl_end
  4515. else
  4516. rl_ding()
  4517. end
  4518. 0
  4519. end
  4520. # Save the current line in _rl_saved_line_for_history.
  4521. def rl_maybe_save_line()
  4522. if @_rl_saved_line_for_history.nil?
  4523. @_rl_saved_line_for_history = Struct.new(:line,:timestamp,:data).new
  4524. @_rl_saved_line_for_history.line = @rl_line_buffer.dup
  4525. @_rl_saved_line_for_history.timestamp = nil
  4526. @_rl_saved_line_for_history.data = @rl_undo_list
  4527. end
  4528. 0
  4529. end
  4530. # Returns the magic number which says what history element we are
  4531. # looking at now. In this implementation, it returns history_offset.
  4532. def where_history()
  4533. @history_offset
  4534. end
  4535. # Make the history entry at WHICH have LINE and DATA. This returns
  4536. # the old entry so you can dispose of the data. In the case of an
  4537. # invalid WHICH, a NULL pointer is returned.
  4538. def replace_history_entry (which, line, data)
  4539. if (which < 0 || which >= @history_length)
  4540. return nil
  4541. end
  4542. temp = Struct.new(:line,:timestamp,:data).new
  4543. old_value = @the_history[which]
  4544. temp.line = line.delete(0.chr)
  4545. temp.data = data
  4546. temp.timestamp = old_value.timestamp.dup
  4547. @the_history[which] = temp
  4548. old_value
  4549. end
  4550. # Perhaps put back the current line if it has changed.
  4551. def rl_maybe_replace_line()
  4552. temp = current_history()
  4553. # If the current line has changed, save the changes.
  4554. if (temp && temp.data != @rl_undo_list)
  4555. temp = replace_history_entry(where_history(), @rl_line_buffer, @rl_undo_list)
  4556. end
  4557. 0
  4558. end
  4559. # Back up history_offset to the previous history entry, and return
  4560. # a pointer to that entry. If there is no previous entry then return
  4561. # a NULL pointer.
  4562. def previous_history()
  4563. @history_offset!=0 ? @the_history[@history_offset-=1] : nil
  4564. end
  4565. # Move history_offset forward to the next history entry, and return
  4566. # a pointer to that entry. If there is no next entry then return a
  4567. # NULL pointer.
  4568. def next_history()
  4569. (@history_offset == @history_length) ? nil : @the_history[@history_offset+=1]
  4570. end
  4571. # Get the previous item out of our interactive history, making it the current
  4572. # line. If there is no previous history, just ding.
  4573. def rl_get_previous_history(count, key)
  4574. if (count < 0)
  4575. return (rl_get_next_history(-count, key))
  4576. end
  4577. if (count == 0)
  4578. return 0
  4579. end
  4580. # either not saved by rl_newline or at end of line, so set appropriately.
  4581. if (@_rl_history_saved_point == -1 && (@rl_point!=0 || @rl_end!=0))
  4582. @_rl_history_saved_point = (@rl_point == @rl_end) ? -1 : @rl_point
  4583. end
  4584. # If we don't have a line saved, then save this one.
  4585. rl_maybe_save_line()
  4586. # If the current line has changed, save the changes.
  4587. rl_maybe_replace_line()
  4588. temp = old_temp = nil
  4589. while (count>0)
  4590. temp = previous_history()
  4591. if temp.nil?
  4592. break
  4593. end
  4594. old_temp = temp
  4595. count -= 1
  4596. end
  4597. # If there was a large argument, and we moved back to the start of the
  4598. # history, that is not an error. So use the last value found.
  4599. if (temp.nil? && old_temp)
  4600. temp = old_temp
  4601. end
  4602. if temp.nil?
  4603. rl_ding()
  4604. else
  4605. rl_replace_from_history(temp, 0)
  4606. _rl_history_set_point()
  4607. end
  4608. 0
  4609. end
  4610. def _rl_history_set_point ()
  4611. @rl_point = (@_rl_history_preserve_point && @_rl_history_saved_point != -1) ?
  4612. @_rl_history_saved_point : @rl_end
  4613. if (@rl_point > @rl_end)
  4614. @rl_point = @rl_end
  4615. end
  4616. if (@rl_editing_mode == @vi_mode && @_rl_keymap != @vi_insertion_keymap)
  4617. @rl_point = 0
  4618. end
  4619. if (@rl_editing_mode == @emacs_mode)
  4620. @rl_mark = (@rl_point == @rl_end ? 0 : @rl_end)
  4621. end
  4622. end
  4623. # Move down to the next history line.
  4624. def rl_get_next_history(count, key)
  4625. if (count < 0)
  4626. return (rl_get_previous_history(-count, key))
  4627. end
  4628. if (count == 0)
  4629. return 0
  4630. end
  4631. rl_maybe_replace_line()
  4632. # either not saved by rl_newline or at end of line, so set appropriately.
  4633. if (@_rl_history_saved_point == -1 && (@rl_point!=0 || @rl_end!=0))
  4634. @_rl_history_saved_point = (@rl_point == @rl_end) ? -1 : @rl_point
  4635. end
  4636. temp = nil
  4637. while (count>0)
  4638. temp = next_history()
  4639. if temp.nil?
  4640. break
  4641. end
  4642. count -= 1
  4643. end
  4644. if temp.nil?
  4645. rl_maybe_unsave_line()
  4646. else
  4647. rl_replace_from_history(temp, 0)
  4648. _rl_history_set_point()
  4649. end
  4650. 0
  4651. end
  4652. def rl_arrow_keys(count, c)
  4653. rl_setstate(RL_STATE_MOREINPUT)
  4654. ch = rl_read_key()
  4655. rl_unsetstate(RL_STATE_MOREINPUT)
  4656. case (ch.upcase)
  4657. when 'A'
  4658. rl_get_previous_history(count, ch)
  4659. when 'B'
  4660. rl_get_next_history(count, ch)
  4661. when 'C'
  4662. rl_forward_byte(count, ch)
  4663. when 'D'
  4664. rl_backward_byte(count, ch)
  4665. else
  4666. rl_ding()
  4667. end
  4668. 0
  4669. end
  4670. def _rl_any_typein()
  4671. return (@push_index != @pop_index)
  4672. end
  4673. def _rl_insert_typein(c)
  4674. string = c
  4675. while ((key = rl_get_char()) &&
  4676. @_rl_keymap[key] == :rl_insert)
  4677. string << key
  4678. end
  4679. if (key)
  4680. _rl_unget_char(key)
  4681. end
  4682. rl_insert_text(string)
  4683. end
  4684. # Insert the character C at the current location, moving point forward.
  4685. # If C introduces a multibyte sequence, we read the whole sequence and
  4686. # then insert the multibyte char into the line buffer.
  4687. def _rl_insert_char(count, c)
  4688. return 0 if (count <= 0)
  4689. incoming = ''
  4690. if @rl_byte_oriented
  4691. incoming << c
  4692. incoming_length = 1
  4693. else
  4694. @pending_bytes << c
  4695. if _rl_get_char_len(@pending_bytes) == -2
  4696. return 1
  4697. else
  4698. incoming = @pending_bytes
  4699. @pending_bytes = ''
  4700. incoming_length = incoming.length
  4701. end
  4702. end
  4703. if(count>1)
  4704. string = incoming * count
  4705. rl_insert_text(string)
  4706. string = nil
  4707. return 0
  4708. end
  4709. if @rl_byte_oriented
  4710. # We are inserting a single character.
  4711. #If there is pending input, then make a string of all of the
  4712. #pending characters that are bound to rl_insert, and insert
  4713. #them all.
  4714. if (_rl_any_typein())
  4715. _rl_insert_typein(c)
  4716. else
  4717. rl_insert_text(c)
  4718. end
  4719. else
  4720. rl_insert_text(incoming)
  4721. end
  4722. return 0
  4723. end
  4724. # Overwrite the character at point (or next COUNT characters) with C.
  4725. # If C introduces a multibyte character sequence, read the entire sequence
  4726. # before starting the overwrite loop.
  4727. def _rl_overwrite_char(count, c)
  4728. # Read an entire multibyte character sequence to insert COUNT times.
  4729. if (count > 0 && !@rl_byte_oriented)
  4730. mbkey = ''
  4731. k = _rl_read_mbstring(c, mbkey, MB_LEN_MAX)
  4732. end
  4733. rl_begin_undo_group()
  4734. count.times do
  4735. if !@rl_byte_oriented
  4736. rl_insert_text(mbkey)
  4737. else
  4738. _rl_insert_char(1, c)
  4739. end
  4740. if (@rl_point < @rl_end)
  4741. rl_delete(1, c)
  4742. end
  4743. end
  4744. rl_end_undo_group()
  4745. return 0
  4746. end
  4747. def rl_insert(count, c)
  4748. ((@rl_insert_mode == RL_IM_INSERT) ? _rl_insert_char(count, c) :
  4749. _rl_overwrite_char(count, c))
  4750. end
  4751. # Insert the next typed character verbatim.
  4752. def _rl_insert_next(count)
  4753. rl_setstate(RL_STATE_MOREINPUT)
  4754. c = rl_read_key()
  4755. rl_unsetstate(RL_STATE_MOREINPUT)
  4756. _rl_insert_char(count, c)
  4757. end
  4758. def rl_quoted_insert(count, key)
  4759. _rl_insert_next(count)
  4760. end
  4761. # Insert a tab character.
  4762. def rl_tab_insert(count, key)
  4763. _rl_insert_char(count, "\t")
  4764. end
  4765. def _rl_vi_save_insert(up)
  4766. if (up.nil? || up.what != UNDO_INSERT)
  4767. if (@vi_insert_buffer_size >= 1)
  4768. @vi_insert_buffer[0] = 0.chr
  4769. end
  4770. return
  4771. end
  4772. start = up.start
  4773. _end = up.end
  4774. len = _end - start + 1
  4775. @vi_insert_buffer = @rl_line_buffer[start,len-1]
  4776. end
  4777. def _rl_vi_done_inserting()
  4778. if (@_rl_vi_doing_insert)
  4779. # The `C', `s', and `S' commands set this.
  4780. rl_end_undo_group()
  4781. # Now, the text between rl_undo_list->next->start and
  4782. # rl_undo_list->next->end is what was inserted while in insert
  4783. # mode. It gets copied to VI_INSERT_BUFFER because it depends
  4784. # on absolute indices into the line which may change (though they
  4785. # probably will not).
  4786. @_rl_vi_doing_insert = 0
  4787. _rl_vi_save_insert(@rl_undo_list.next)
  4788. @vi_continued_command = 1
  4789. else
  4790. if ((@_rl_vi_last_key_before_insert == 'i' || @_rl_vi_last_key_before_insert == 'a') && @rl_undo_list)
  4791. _rl_vi_save_insert(@rl_undo_list)
  4792. # XXX - Other keys probably need to be checked.
  4793. elsif (@_rl_vi_last_key_before_insert == 'C')
  4794. rl_end_undo_group()
  4795. end
  4796. while (@_rl_undo_group_level > 0)
  4797. rl_end_undo_group()
  4798. end
  4799. @vi_continued_command = 0
  4800. end
  4801. end
  4802. # Is the command C a VI mode text modification command?
  4803. def _rl_vi_textmod_command(c)
  4804. return @vi_textmod[c]
  4805. end
  4806. def _rl_vi_reset_last()
  4807. @_rl_vi_last_command = 'i'
  4808. @_rl_vi_last_repeat = 1
  4809. @_rl_vi_last_arg_sign = 1
  4810. @_rl_vi_last_motion = 0
  4811. end
  4812. def _rl_update_final()
  4813. full_lines = false
  4814. # If the cursor is the only thing on an otherwise-blank last line,
  4815. # compensate so we don't print an extra CRLF.
  4816. if (@_rl_vis_botlin && @_rl_last_c_pos == 0 &&
  4817. @visible_line[@vis_lbreaks[@_rl_vis_botlin]] == ?\0 )
  4818. @_rl_vis_botlin-=1
  4819. full_lines = true
  4820. end
  4821. _rl_move_vert(@_rl_vis_botlin)
  4822. # If we've wrapped lines, remove the final xterm line-wrap flag.
  4823. if (full_lines && @_rl_term_autowrap && (vis_llen(@_rl_vis_botlin) == @_rl_screenwidth))
  4824. last_line = @visible_line[@vis_lbreaks[@_rl_vis_botlin]..-1]
  4825. @cpos_buffer_position = -1 # don't know where we are in buffer
  4826. _rl_move_cursor_relative(@_rl_screenwidth - 1, last_line) # XXX
  4827. _rl_clear_to_eol(0)
  4828. @rl_outstream.write(last_line[@_rl_screenwidth - 1,1])
  4829. end
  4830. @_rl_vis_botlin = 0
  4831. rl_crlf()
  4832. @rl_outstream.flush
  4833. @rl_display_fixed = true if !@rl_display_fixed
  4834. end
  4835. # What to do when a NEWLINE is pressed. We accept the whole line.
  4836. # KEY is the key that invoked this command. I guess it could have
  4837. # meaning in the future.
  4838. def rl_newline(count, key)
  4839. @rl_done = true
  4840. if (@_rl_history_preserve_point)
  4841. @_rl_history_saved_point = (@rl_point == @rl_end) ? 1 : @rl_point
  4842. end
  4843. rl_setstate(RL_STATE_DONE)
  4844. if (@rl_editing_mode == @vi_mode)
  4845. _rl_vi_done_inserting()
  4846. if (_rl_vi_textmod_command(@_rl_vi_last_command).nil?) # XXX
  4847. _rl_vi_reset_last()
  4848. end
  4849. end
  4850. # If we've been asked to erase empty lines, suppress the final update,
  4851. # since _rl_update_final calls rl_crlf().
  4852. if (@rl_erase_empty_line && @rl_point == 0 && @rl_end == 0)
  4853. return 0
  4854. end
  4855. if @readline_echoing_p
  4856. _rl_update_final()
  4857. end
  4858. 0
  4859. end
  4860. # What to do for some uppercase characters, like meta characters,
  4861. # and some characters appearing in emacs_ctlx_keymap. This function
  4862. # is just a stub, you bind keys to it and the code in _rl_dispatch ()
  4863. # is special cased.
  4864. def rl_do_lowercase_version(ignore1, ignore2)
  4865. 0
  4866. end
  4867. def rl_character_len(c, pos)
  4868. if (meta_char(c))
  4869. return ((!@_rl_output_meta_chars) ? 4 : 1)
  4870. end
  4871. if (c == "\t")
  4872. return (((pos | 7) + 1) - pos)
  4873. end
  4874. if (ctrl_char(c) || c == RUBOUT)
  4875. return (2)
  4876. end
  4877. return ((isprint(c)) ? 1 : 2)
  4878. end
  4879. # This is different from what vi does, so the code's not shared. Emacs
  4880. # rubout in overwrite mode has one oddity: it replaces a control
  4881. # character that's displayed as two characters (^X) with two spaces.
  4882. def _rl_overwrite_rubout(count, key)
  4883. if (@rl_point == 0)
  4884. rl_ding()
  4885. return 1
  4886. end
  4887. opoint = @rl_point
  4888. # L == number of spaces to insert
  4889. l = 0
  4890. count.times do
  4891. rl_backward_char(1, key)
  4892. l += rl_character_len(@rl_line_buffer[@rl_point,1], @rl_point) # not exactly right
  4893. end
  4894. rl_begin_undo_group()
  4895. if (count > 1 || @rl_explicit_arg)
  4896. rl_kill_text(opoint, @rl_point)
  4897. else
  4898. rl_delete_text(opoint, @rl_point)
  4899. end
  4900. # Emacs puts point at the beginning of the sequence of spaces.
  4901. if (@rl_point < @rl_end)
  4902. opoint = @rl_point
  4903. _rl_insert_char(l, ' ')
  4904. @rl_point = opoint
  4905. end
  4906. rl_end_undo_group()
  4907. 0
  4908. end
  4909. # Rubout the character behind point.
  4910. def rl_rubout(count, key)
  4911. if (count < 0)
  4912. return (rl_delete(-count, key))
  4913. end
  4914. if (@rl_point==0)
  4915. rl_ding()
  4916. return -1
  4917. end
  4918. if (@rl_insert_mode == RL_IM_OVERWRITE)
  4919. return (_rl_overwrite_rubout(count, key))
  4920. end
  4921. _rl_rubout_char(count, key)
  4922. end
  4923. # Quick redisplay hack when erasing characters at the end of the line.
  4924. def _rl_erase_at_end_of_line(l)
  4925. _rl_backspace(l)
  4926. @rl_outstream.write(' '*l)
  4927. _rl_backspace(l)
  4928. @_rl_last_c_pos -= l
  4929. @visible_line[@_rl_last_c_pos,l] = 0.chr * l
  4930. @rl_display_fixed = true if !@rl_display_fixed
  4931. end
  4932. def _rl_rubout_char(count, key)
  4933. # Duplicated code because this is called from other parts of the library.
  4934. if (count < 0)
  4935. return (rl_delete(-count, key))
  4936. end
  4937. if (@rl_point == 0)
  4938. rl_ding()
  4939. return -1
  4940. end
  4941. orig_point = @rl_point
  4942. if (count > 1 || @rl_explicit_arg)
  4943. rl_backward_char(count, key)
  4944. rl_kill_text(orig_point, @rl_point)
  4945. elsif (@rl_byte_oriented)
  4946. c = @rl_line_buffer[@rl_point-=1,1]
  4947. rl_delete_text(@rl_point, orig_point)
  4948. # The erase-at-end-of-line hack is of questionable merit now.
  4949. if (@rl_point == @rl_end && isprint(c) && @_rl_last_c_pos!=0)
  4950. l = rl_character_len(c, @rl_point)
  4951. _rl_erase_at_end_of_line(l)
  4952. end
  4953. else
  4954. @rl_point = _rl_find_prev_mbchar(@rl_line_buffer, @rl_point, MB_FIND_NONZERO)
  4955. rl_delete_text(@rl_point, orig_point)
  4956. end
  4957. 0
  4958. end
  4959. # Delete the character under the cursor. Given a numeric argument,
  4960. # kill that many characters instead.
  4961. def rl_delete(count, key)
  4962. if (count < 0)
  4963. return (_rl_rubout_char(-count, key))
  4964. end
  4965. if (@rl_point == @rl_end)
  4966. rl_ding()
  4967. return -1
  4968. end
  4969. if (count > 1 || @rl_explicit_arg)
  4970. xpoint = @rl_point
  4971. rl_forward_byte(count, key)
  4972. rl_kill_text(xpoint, @rl_point)
  4973. @rl_point = xpoint
  4974. else
  4975. if !@rl_byte_oriented
  4976. xpoint =_rl_find_next_mbchar(@rl_line_buffer, @rl_point, 1, MB_FIND_NONZERO)
  4977. else
  4978. xpoint = @rl_point + 1
  4979. end
  4980. rl_delete_text(@rl_point, xpoint)
  4981. end
  4982. 0
  4983. end
  4984. # Add TEXT to the kill ring, allocating a new kill ring slot as necessary.
  4985. # This uses TEXT directly, so the caller must not free it. If APPEND is
  4986. # non-zero, and the last command was a kill, the text is appended to the
  4987. # current kill ring slot, otherwise prepended.
  4988. def _rl_copy_to_kill_ring(text, append)
  4989. # First, find the slot to work with.
  4990. if (!@_rl_last_command_was_kill)
  4991. # Get a new slot.
  4992. if @rl_kill_ring.nil?
  4993. # If we don't have any defined, then make one.
  4994. @rl_kill_ring_length = 1
  4995. @rl_kill_ring = Array.new(@rl_kill_ring_length+1)
  4996. @rl_kill_ring[slot = 0] = nil
  4997. else
  4998. # We have to add a new slot on the end, unless we have
  4999. # exceeded the max limit for remembering kills.
  5000. slot = @rl_kill_ring_length
  5001. if (slot == @rl_max_kills)
  5002. @rl_kill_ring[0,slot] = @rl_kill_ring[1,slot]
  5003. else
  5004. slot = @rl_kill_ring_length += 1
  5005. end
  5006. @rl_kill_ring[slot-=1] = nil
  5007. end
  5008. else
  5009. slot = @rl_kill_ring_length - 1
  5010. end
  5011. # If the last command was a kill, prepend or append.
  5012. if (@_rl_last_command_was_kill && @rl_editing_mode != @vi_mode)
  5013. old = @rl_kill_ring[slot]
  5014. if (append)
  5015. new = old + text
  5016. else
  5017. new = text + old
  5018. end
  5019. old = nil
  5020. text = nil
  5021. @rl_kill_ring[slot] = new
  5022. else
  5023. @rl_kill_ring[slot] = text
  5024. end
  5025. @rl_kill_index = slot
  5026. 0
  5027. end
  5028. # The way to kill something. This appends or prepends to the last
  5029. # kill, if the last command was a kill command. if FROM is less
  5030. # than TO, then the text is appended, otherwise prepended. If the
  5031. # last command was not a kill command, then a new slot is made for
  5032. # this kill.
  5033. def rl_kill_text(from, to)
  5034. # Is there anything to kill?
  5035. if (from == to)
  5036. @_rl_last_command_was_kill = true if !@_rl_last_command_was_kill
  5037. return 0
  5038. end
  5039. text = rl_copy_text(from, to)
  5040. # Delete the copied text from the line.
  5041. rl_delete_text(from, to)
  5042. _rl_copy_to_kill_ring(text, from < to)
  5043. @_rl_last_command_was_kill = true if !@_rl_last_command_was_kill
  5044. 0
  5045. end
  5046. # This does what C-w does in Unix. We can't prevent people from
  5047. # using behaviour that they expect.
  5048. def rl_unix_word_rubout(count, key)
  5049. if (@rl_point == 0)
  5050. rl_ding()
  5051. else
  5052. orig_point = @rl_point
  5053. if (count <= 0)
  5054. count = 1
  5055. end
  5056. while (count>0)
  5057. while (@rl_point>0 && whitespace(@rl_line_buffer[@rl_point - 1,1]))
  5058. @rl_point-=1
  5059. end
  5060. while (@rl_point>0 && !whitespace(@rl_line_buffer[@rl_point - 1,1]))
  5061. @rl_point-=1
  5062. end
  5063. count -= 1
  5064. end
  5065. rl_kill_text(orig_point, @rl_point)
  5066. if (@rl_editing_mode == @emacs_mode)
  5067. @rl_mark = @rl_point
  5068. end
  5069. end
  5070. 0
  5071. end
  5072. # This deletes one filename component in a Unix pathname. That is, it
  5073. # deletes backward to directory separator (`/') or whitespace.
  5074. def rl_unix_filename_rubout(count, key)
  5075. if (@rl_point == 0)
  5076. rl_ding()
  5077. else
  5078. orig_point = @rl_point
  5079. if (count <= 0)
  5080. count = 1
  5081. end
  5082. while (count>0)
  5083. c = @rl_line_buffer[@rl_point - 1,1]
  5084. while (@rl_point>0 && (whitespace(c) || c == '/'))
  5085. @rl_point-=1
  5086. c = @rl_line_buffer[@rl_point - 1,1]
  5087. end
  5088. while (@rl_point>0 && !whitespace(c) && c != '/')
  5089. @rl_point-=1
  5090. c = @rl_line_buffer[@rl_point - 1,1]
  5091. end
  5092. count -= 1
  5093. end
  5094. rl_kill_text(orig_point, @rl_point)
  5095. if (@rl_editing_mode == @emacs_mode)
  5096. @rl_mark = @rl_point
  5097. end
  5098. end
  5099. 0
  5100. end
  5101. # Delete the character under the cursor, unless the insertion
  5102. # point is at the end of the line, in which case the character
  5103. # behind the cursor is deleted. COUNT is obeyed and may be used
  5104. # to delete forward or backward that many characters.
  5105. def rl_rubout_or_delete(count, key)
  5106. if (@rl_end != 0 && @rl_point == @rl_end)
  5107. return (_rl_rubout_char(count, key))
  5108. else
  5109. return (rl_delete(count, key))
  5110. end
  5111. end
  5112. # Delete all spaces and tabs around point.
  5113. def rl_delete_horizontal_space(count, ignore)
  5114. start = @rl_point
  5115. while (@rl_point!=0 && whitespace(@rl_line_buffer[@rl_point - 1]))
  5116. @rl_point-=1
  5117. end
  5118. start = @rl_point
  5119. while (@rl_point < @rl_end && whitespace(@rl_line_buffer[@rl_point]))
  5120. @rl_point+=1
  5121. end
  5122. if (start != @rl_point)
  5123. rl_delete_text(start, @rl_point)
  5124. @rl_point = start
  5125. end
  5126. if (@rl_point < 0)
  5127. @rl_point = 0
  5128. end
  5129. 0
  5130. end
  5131. # List the possible completions. See description of rl_complete ().
  5132. def rl_possible_completions(ignore, invoking_key)
  5133. rl_complete_internal('?')
  5134. end
  5135. # Like the tcsh editing function delete-char-or-list. The eof character
  5136. # is caught before this is invoked, so this really does the same thing as
  5137. # delete-char-or-list-or-eof, as long as it's bound to the eof character.
  5138. def rl_delete_or_show_completions(count, key)
  5139. if (@rl_end != 0 && @rl_point == @rl_end)
  5140. return (rl_possible_completions(count, key))
  5141. else
  5142. return (rl_delete(count, key))
  5143. end
  5144. end
  5145. # Turn the current line into a comment in shell history.
  5146. # A K*rn shell style function.
  5147. def rl_insert_comment(count, key)
  5148. rl_beg_of_line(1, key)
  5149. @rl_comment_text = @_rl_comment_begin ? @_rl_comment_begin : '#'
  5150. if (!@rl_explicit_arg)
  5151. rl_insert_text(@rl_comment_text)
  5152. else
  5153. @rl_comment_len = @rl_comment_text.length
  5154. if @rl_comment_text[0,@rl_comment_len] == @rl_line_buffer[0,@rl_comment_len]
  5155. rl_delete_text(@rl_point, @rl_point + @rl_comment_len)
  5156. else
  5157. rl_insert_text(@rl_comment_text)
  5158. end
  5159. end
  5160. send(@rl_redisplay_function)
  5161. rl_newline(1, "\n")
  5162. 0
  5163. end
  5164. def alloc_history_entry(string, ts)
  5165. temp = Struct.new(:line,:data,:timestamp).new
  5166. temp.line = string ? string.delete(0.chr) : string
  5167. temp.data = nil
  5168. temp.timestamp = ts
  5169. return temp
  5170. end
  5171. def hist_inittime()
  5172. t = Time.now.to_i
  5173. ts = "X%u" % t
  5174. ret = ts.dup
  5175. ret[0] = @history_comment_char
  5176. ret
  5177. end
  5178. # Place STRING at the end of the history list. The data field
  5179. # is set to NULL.
  5180. def add_history(string)
  5181. if (@history_stifled && (@history_length == @history_max_entries))
  5182. # If the history is stifled, and history_length is zero,
  5183. # and it equals history_max_entries, we don't save items.
  5184. return if (@history_length == 0)
  5185. @the_history.shift
  5186. else
  5187. if @the_history.nil?
  5188. @the_history = []
  5189. @history_length = 1
  5190. else
  5191. @history_length+=1
  5192. end
  5193. end
  5194. temp = alloc_history_entry(string, hist_inittime())
  5195. @the_history[@history_length] = nil
  5196. @the_history[@history_length - 1] = temp
  5197. end
  5198. def using_history()
  5199. @history_offset = @history_length
  5200. end
  5201. # Set default values for readline word completion. These are the variables
  5202. # that application completion functions can change or inspect.
  5203. def set_completion_defaults(what_to_do)
  5204. # Only the completion entry function can change these.
  5205. @rl_filename_completion_desired = false
  5206. @rl_filename_quoting_desired = true
  5207. @rl_completion_type = what_to_do
  5208. @rl_completion_suppress_append = @rl_completion_suppress_quote = false
  5209. # The completion entry function may optionally change this.
  5210. @rl_completion_mark_symlink_dirs = @_rl_complete_mark_symlink_dirs
  5211. end
  5212. def _rl_find_completion_word()
  5213. _end = @rl_point
  5214. found_quote = 0
  5215. delimiter = 0.chr
  5216. quote_char = 0.chr
  5217. brkchars = nil
  5218. if @rl_completion_word_break_hook
  5219. brkchars = send(@rl_completion_word_break_hook)
  5220. end
  5221. if brkchars.nil?
  5222. brkchars = @rl_completer_word_break_characters
  5223. end
  5224. if (@rl_completer_quote_characters)
  5225. # We have a list of characters which can be used in pairs to
  5226. # quote substrings for the completer. Try to find the start
  5227. # of an unclosed quoted substring.
  5228. # FOUND_QUOTE is set so we know what kind of quotes we found.
  5229. scan = 0
  5230. pass_next = false
  5231. while scan < _end
  5232. if (pass_next)
  5233. pass_next = false
  5234. next
  5235. end
  5236. # Shell-like semantics for single quotes -- don't allow backslash
  5237. # to quote anything in single quotes, especially not the closing
  5238. # quote. If you don't like this, take out the check on the value
  5239. # of quote_char.
  5240. if (quote_char != "'" && @rl_line_buffer[scan] == ?\\)
  5241. pass_next = true
  5242. found_quote |= RL_QF_BACKSLASH
  5243. next
  5244. end
  5245. if (quote_char != 0.chr)
  5246. # Ignore everything until the matching close quote char.
  5247. if (@rl_line_buffer[scan,1] == quote_char)
  5248. # Found matching close. Abandon this substring.
  5249. quote_char = 0.chr
  5250. @rl_point = _end
  5251. end
  5252. elsif (@rl_completer_quote_characters.include?(@rl_line_buffer[scan,1]))
  5253. # Found start of a quoted substring.
  5254. quote_char = @rl_line_buffer[scan,1]
  5255. @rl_point = scan + 1
  5256. # Shell-like quoting conventions.
  5257. if (quote_char == "'")
  5258. found_quote |= RL_QF_SINGLE_QUOTE
  5259. elsif (quote_char == '"')
  5260. found_quote |= RL_QF_DOUBLE_QUOTE
  5261. else
  5262. found_quote |= RL_QF_OTHER_QUOTE
  5263. end
  5264. end
  5265. if !@rl_byte_oriented
  5266. scan = _rl_find_next_mbchar(@rl_line_buffer, scan, 1, MB_FIND_ANY)
  5267. else
  5268. scan += 1
  5269. end
  5270. end
  5271. end
  5272. if (@rl_point == _end && quote_char == 0.chr)
  5273. # We didn't find an unclosed quoted substring upon which to do
  5274. # completion, so use the word break characters to find the
  5275. # substring on which to complete.
  5276. while (@rl_point = !@rl_byte_oriented ?
  5277. _rl_find_prev_mbchar(@rl_line_buffer, @rl_point, MB_FIND_ANY):(@rl_point-1))>0
  5278. scan = @rl_line_buffer[@rl_point,1]
  5279. if !brkchars.include?(scan)
  5280. next
  5281. end
  5282. # Call the application-specific function to tell us whether
  5283. # this word break character is quoted and should be skipped.
  5284. if (@rl_char_is_quoted_p && found_quote!=0 &&
  5285. send(@rl_char_is_quoted_p,@rl_line_buffer, @rl_point))
  5286. next
  5287. end
  5288. # Convoluted code, but it avoids an n^2 algorithm with calls
  5289. # to char_is_quoted.
  5290. break
  5291. end
  5292. end
  5293. # If we are at an unquoted word break, then advance past it.
  5294. scan = @rl_line_buffer[@rl_point,1]
  5295. # If there is an application-specific function to say whether or not
  5296. # a character is quoted and we found a quote character, let that
  5297. # function decide whether or not a character is a word break, even
  5298. # if it is found in rl_completer_word_break_characters. Don't bother
  5299. # if we're at the end of the line, though.
  5300. if (scan != 0.chr)
  5301. if (@rl_char_is_quoted_p)
  5302. isbrk = (found_quote == 0 ||
  5303. !send(@rl_char_is_quoted_p,@rl_line_buffer, @rl_point)) &&
  5304. brkchars.include?(scan)
  5305. else
  5306. isbrk = brkchars.include?(scan)
  5307. end
  5308. if (isbrk)
  5309. # If the character that caused the word break was a quoting
  5310. # character, then remember it as the delimiter.
  5311. if (@rl_basic_quote_characters &&
  5312. @rl_basic_quote_characters.include?(scan) &&
  5313. (_end - @rl_point) > 1)
  5314. delimiter = scan
  5315. end
  5316. # If the character isn't needed to determine something special
  5317. # about what kind of completion to perform, then advance past it.
  5318. if (@rl_special_prefixes.nil? || !@rl_special_prefixes.include?(scan) )
  5319. @rl_point+=1
  5320. end
  5321. end
  5322. end
  5323. return [quote_char,found_quote!=0,delimiter]
  5324. end
  5325. def gen_completion_matches(text, start, _end, our_func, found_quote, quote_char)
  5326. @rl_completion_found_quote = found_quote
  5327. @rl_completion_quote_character = quote_char
  5328. # If the user wants to TRY to complete, but then wants to give
  5329. # up and use the default completion function, they set the
  5330. # variable rl_attempted_completion_function.
  5331. if (@rl_attempted_completion_function)
  5332. matches = Readline.send(@rl_attempted_completion_function,text, start, _end)
  5333. if (matches || @rl_attempted_completion_over)
  5334. @rl_attempted_completion_over = false
  5335. return (matches)
  5336. end
  5337. end
  5338. # XXX -- filename dequoting moved into rl_filename_completion_function
  5339. matches = rl_completion_matches(text, our_func)
  5340. matches
  5341. end
  5342. # Filter out duplicates in MATCHES. This frees up the strings in
  5343. # MATCHES.
  5344. def remove_duplicate_matches(matches)
  5345. # Sort the items.
  5346. # Sort the array without matches[0], since we need it to
  5347. # stay in place no matter what.
  5348. if matches.length>0
  5349. matches[1..-2] = matches[1..-2].sort.uniq
  5350. end
  5351. matches
  5352. end
  5353. def postprocess_matches(matchesp, matching_filenames)
  5354. matches = matchesp
  5355. return 0 if matches.nil?
  5356. # It seems to me that in all the cases we handle we would like
  5357. # to ignore duplicate possiblilities. Scan for the text to
  5358. # insert being identical to the other completions.
  5359. if (@rl_ignore_completion_duplicates)
  5360. remove_duplicate_matches(matches)
  5361. end
  5362. # If we are matching filenames, then here is our chance to
  5363. # do clever processing by re-examining the list. Call the
  5364. # ignore function with the array as a parameter. It can
  5365. # munge the array, deleting matches as it desires.
  5366. if (@rl_ignore_some_completions_function && matching_filenames)
  5367. nmatch = matches.length
  5368. send(@rl_ignore_some_completions_function,matches)
  5369. if (matches.nil? || matches[0].nil?)
  5370. matches = nil
  5371. return 0
  5372. else
  5373. # If we removed some matches, recompute the common prefix.
  5374. i = matches.length
  5375. if (i > 1 && i < nmatch)
  5376. t = matches[0]
  5377. compute_lcd_of_matches(matches, i - 1, t)
  5378. end
  5379. end
  5380. end
  5381. matchesp = matches
  5382. 1
  5383. end
  5384. def insert_all_matches(matches, point, qc)
  5385. rl_begin_undo_group()
  5386. # remove any opening quote character; make_quoted_replacement will add
  5387. # it back.
  5388. if (qc && qc.length>0 && point>0 && @rl_line_buffer[point - 1,1] == qc)
  5389. point-=1
  5390. end
  5391. rl_delete_text(point, @rl_point)
  5392. @rl_point = point
  5393. if (matches[1])
  5394. i = 1
  5395. while(matches[i])
  5396. rp = make_quoted_replacement(matches[i], SINGLE_MATCH, qc)
  5397. rl_insert_text(rp)
  5398. rl_insert_text(" ")
  5399. if (rp != matches[i])
  5400. rp = nil
  5401. end
  5402. i += 1
  5403. end
  5404. else
  5405. rp = make_quoted_replacement(matches[0], SINGLE_MATCH, qc)
  5406. rl_insert_text(rp)
  5407. rl_insert_text(" ")
  5408. if (rp != matches[0])
  5409. rp = nil
  5410. end
  5411. end
  5412. rl_end_undo_group()
  5413. end
  5414. def make_quoted_replacement(match, mtype, qc)
  5415. # If we are doing completion on quoted substrings, and any matches
  5416. # contain any of the completer_word_break_characters, then auto-
  5417. # matically prepend the substring with a quote character (just pick
  5418. # the first one from the list of such) if it does not already begin
  5419. # with a quote string. FIXME: Need to remove any such automatically
  5420. # inserted quote character when it no longer is necessary, such as
  5421. # if we change the string we are completing on and the new set of
  5422. # matches don't require a quoted substring.
  5423. replacement = match
  5424. should_quote = match && @rl_completer_quote_characters &&
  5425. @rl_filename_completion_desired &&
  5426. @rl_filename_quoting_desired
  5427. if (should_quote)
  5428. should_quote = should_quote && (qc.nil? || qc == 0.chr ||
  5429. (@rl_completer_quote_characters && @rl_completer_quote_characters.include?(qc)))
  5430. end
  5431. if (should_quote)
  5432. # If there is a single match, see if we need to quote it.
  5433. # This also checks whether the common prefix of several
  5434. # matches needs to be quoted.
  5435. should_quote = @rl_filename_quote_characters ?
  5436. !!match[@rl_filename_quote_characters] :
  5437. false
  5438. do_replace = should_quote ? mtype : NO_MATCH
  5439. # Quote the replacement, since we found an embedded
  5440. # word break character in a potential match.
  5441. if (do_replace != NO_MATCH && @rl_filename_quoting_function)
  5442. replacement = send(@rl_filename_quoting_function,match, do_replace, qc)
  5443. end
  5444. end
  5445. replacement
  5446. end
  5447. def insert_match(match, start, mtype, qc)
  5448. oqc = qc
  5449. replacement = make_quoted_replacement(match, mtype, qc)
  5450. # Now insert the match.
  5451. if (replacement)
  5452. # Don't double an opening quote character.
  5453. if (qc && qc.length>0 && start!=0 && @rl_line_buffer[start - 1,1] == qc &&
  5454. replacement[0,1] == qc)
  5455. start-=1
  5456. # If make_quoted_replacement changed the quoting character, remove
  5457. # the opening quote and insert the (fully-quoted) replacement.
  5458. elsif (qc && (qc != oqc) && start!=0 && @rl_line_buffer[start - 1,1] == oqc &&
  5459. replacement[0,1] != oqc)
  5460. start-=1
  5461. end
  5462. _rl_replace_text(replacement, start, @rl_point - 1)
  5463. if (replacement != match)
  5464. replacement = nil
  5465. end
  5466. end
  5467. end
  5468. # Return the portion of PATHNAME that should be output when listing
  5469. # possible completions. If we are hacking filename completion, we
  5470. # are only interested in the basename, the portion following the
  5471. # final slash. Otherwise, we return what we were passed. Since
  5472. # printing empty strings is not very informative, if we're doing
  5473. # filename completion, and the basename is the empty string, we look
  5474. # for the previous slash and return the portion following that. If
  5475. # there's no previous slash, we just return what we were passed.
  5476. def printable_part(pathname)
  5477. if (!@rl_filename_completion_desired) # don't need to do anything
  5478. return (pathname)
  5479. end
  5480. temp = pathname.rindex('/')
  5481. return pathname if temp.nil?
  5482. File.basename(pathname)
  5483. end
  5484. def fnprint(to_print)
  5485. printed_len = 0
  5486. case @encoding
  5487. when 'E'
  5488. arr = to_print.scan(/./me)
  5489. when 'S'
  5490. arr = to_print.scan(/./ms)
  5491. when 'U'
  5492. arr = to_print.scan(/./mu)
  5493. when 'X'
  5494. arr = to_print.dup.force_encoding(@encoding_name).chars
  5495. else
  5496. arr = to_print.scan(/./m)
  5497. end
  5498. arr.each do |s|
  5499. if(ctrl_char(s))
  5500. @rl_outstream.write('^'+(s[0].ord|0x40).chr.upcase)
  5501. printed_len += 2
  5502. elsif s == RUBOUT
  5503. @rl_outstream.write('^?')
  5504. printed_len += 2
  5505. else
  5506. @rl_outstream.write(s)
  5507. if @encoding=='U'
  5508. printed_len += s.unpack('U').first >= 0x1000 ? 2 : 1
  5509. elsif @encoding=='X'
  5510. printed_len += s.ord >= 0x1000 ? 2 : 1
  5511. else
  5512. printed_len += s.length
  5513. end
  5514. end
  5515. end
  5516. printed_len
  5517. end
  5518. def _rl_internal_pager(lines)
  5519. @rl_outstream.puts "--More--"
  5520. @rl_outstream.flush
  5521. i = get_y_or_n(1)
  5522. _rl_erase_entire_line()
  5523. if (i == 0)
  5524. return -1
  5525. elsif (i == 2)
  5526. return (lines - 1)
  5527. else
  5528. return 0
  5529. end
  5530. end
  5531. def path_isdir(filename)
  5532. return File.directory?(filename)
  5533. end
  5534. # Return the character which best describes FILENAME.
  5535. # `@' for symbolic links
  5536. # `/' for directories
  5537. # `*' for executables
  5538. # `=' for sockets
  5539. # `|' for FIFOs
  5540. # `%' for character special devices
  5541. # `#' for block special devices
  5542. def stat_char(filename)
  5543. return nil if !File.exists?(filename)
  5544. return '/' if File.directory?(filename)
  5545. return '%' if File.chardev?(filename)
  5546. return '#' if File.blockdev?(filename)
  5547. return '@' if File.symlink?(filename)
  5548. return '=' if File.socket?(filename)
  5549. return '|' if File.pipe?(filename)
  5550. return '*' if File.executable?(filename)
  5551. nil
  5552. end
  5553. # Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we
  5554. # are using it, check for and output a single character for `special'
  5555. # filenames. Return the number of characters we output.
  5556. def print_filename(to_print, full_pathname)
  5557. extension_char = 0.chr
  5558. printed_len = fnprint(to_print)
  5559. if (@rl_filename_completion_desired && (@rl_visible_stats || @_rl_complete_mark_directories))
  5560. # If to_print != full_pathname, to_print is the basename of the
  5561. # path passed. In this case, we try to expand the directory
  5562. # name before checking for the stat character.
  5563. if (to_print != full_pathname)
  5564. if full_pathname.nil? || full_pathname.length==0
  5565. dn = "/"
  5566. else
  5567. dn = File.dirname(full_pathname)
  5568. end
  5569. s = File.expand_path(dn)
  5570. if (@rl_directory_completion_hook)
  5571. send(@rl_directory_completion_hook,s)
  5572. end
  5573. slen = s.length
  5574. tlen = to_print.length
  5575. new_full_pathname = s.dup
  5576. if (s[-1] == ?/ )
  5577. slen-=1
  5578. else
  5579. new_full_pathname[slen] = ?/
  5580. end
  5581. new_full_pathname[slen .. -1] = '/' + to_print
  5582. if (@rl_visible_stats)
  5583. extension_char = stat_char(new_full_pathname)
  5584. else
  5585. if (path_isdir(new_full_pathname))
  5586. extension_char = '/'
  5587. end
  5588. end
  5589. new_full_pathname = nil
  5590. else
  5591. s = File.expand_path(full_pathname)
  5592. if (@rl_visible_stats)
  5593. extension_char = stat_char(s)
  5594. else
  5595. if (path_isdir(s))
  5596. extension_char = '/'
  5597. end
  5598. end
  5599. end
  5600. s = nil
  5601. if (extension_char)
  5602. @rl_outstream.write(extension_char)
  5603. printed_len+=1
  5604. end
  5605. end
  5606. printed_len
  5607. end
  5608. # The user must press "y" or "n". Non-zero return means "y" pressed.
  5609. def get_y_or_n(for_pager)
  5610. while(true)
  5611. rl_setstate(RL_STATE_MOREINPUT)
  5612. c = rl_read_key()
  5613. rl_unsetstate(RL_STATE_MOREINPUT)
  5614. if (c == 'y' || c == 'Y' || c == ' ')
  5615. return (1)
  5616. end
  5617. if (c == 'n' || c == 'N' || c == RUBOUT)
  5618. return (0)
  5619. end
  5620. if (c == ABORT_CHAR)
  5621. _rl_abort_internal()
  5622. end
  5623. if (for_pager && (c == NEWLINE || c == RETURN))
  5624. return (2)
  5625. end
  5626. if (for_pager && (c == 'q' || c == 'Q'))
  5627. return (0)
  5628. end
  5629. rl_ding()
  5630. end
  5631. end
  5632. # Compute width of STRING when displayed on screen by print_filename
  5633. def fnwidth(string)
  5634. left = string.length + 1
  5635. width = pos = 0
  5636. while (string[pos] && string[pos] != ?\0)
  5637. if (ctrl_char(string[0,1]) || string[0,1] == RUBOUT)
  5638. width += 2
  5639. pos+=1
  5640. else
  5641. case @encoding
  5642. when 'E'
  5643. wc = string[pos,left-pos].scan(/./me)[0]
  5644. bytes = wc.length
  5645. tempwidth = wc.length
  5646. when 'S'
  5647. wc = string[pos,left-pos].scan(/./ms)[0]
  5648. bytes = wc.length
  5649. tempwidth = wc.length
  5650. when 'U'
  5651. wc = string[pos,left-pos].scan(/./mu)[0]
  5652. bytes = wc.length
  5653. tempwidth = wc.unpack('U').first >= 0x1000 ? 2 : 1
  5654. when 'X'
  5655. wc = string[pos,left-pos].force_encoding(@encoding_name)[0]
  5656. bytes = wc.bytesize
  5657. tempwidth = wc.ord >= 0x1000 ? 2 : 1
  5658. else
  5659. wc = string[pos,left-pos].scan(/./m)[0]
  5660. bytes = wc.length
  5661. tempwidth = wc.length
  5662. end
  5663. clen = bytes
  5664. pos += clen
  5665. w = tempwidth
  5666. width += (w >= 0) ? w : 1
  5667. end
  5668. end
  5669. width
  5670. end
  5671. # Display MATCHES, a list of matching filenames in argv format. This
  5672. # handles the simple case -- a single match -- first. If there is more
  5673. # than one match, we compute the number of strings in the list and the
  5674. # length of the longest string, which will be needed by the display
  5675. # function. If the application wants to handle displaying the list of
  5676. # matches itself, it sets RL_COMPLETION_DISPLAY_MATCHES_HOOK to the
  5677. # address of a function, and we just call it. If we're handling the
  5678. # display ourselves, we just call rl_display_match_list. We also check
  5679. # that the list of matches doesn't exceed the user-settable threshold,
  5680. # and ask the user if he wants to see the list if there are more matches
  5681. # than RL_COMPLETION_QUERY_ITEMS.
  5682. def display_matches(matches)
  5683. # Move to the last visible line of a possibly-multiple-line command.
  5684. _rl_move_vert(@_rl_vis_botlin)
  5685. # Handle simple case first. What if there is only one answer?
  5686. if matches[1].nil?
  5687. temp = printable_part(matches[0])
  5688. rl_crlf()
  5689. print_filename(temp, matches[0])
  5690. rl_crlf()
  5691. rl_forced_update_display()
  5692. @rl_display_fixed = true
  5693. return
  5694. end
  5695. # There is more than one answer. Find out how many there are,
  5696. # and find the maximum printed length of a single entry.
  5697. max = 0
  5698. i = 1
  5699. while(matches[i])
  5700. temp = printable_part(matches[i])
  5701. len = fnwidth(temp)
  5702. if (len > max)
  5703. max = len
  5704. end
  5705. i += 1
  5706. end
  5707. len = i - 1
  5708. # If the caller has defined a display hook, then call that now.
  5709. if (@rl_completion_display_matches_hook)
  5710. send(@rl_completion_display_matches_hook,matches, len, max)
  5711. return
  5712. end
  5713. # If there are many items, then ask the user if she really wants to
  5714. # see them all.
  5715. if (@rl_completion_query_items > 0 && len >= @rl_completion_query_items)
  5716. rl_crlf()
  5717. @rl_outstream.write("Display all #{len} possibilities? (y or n)")
  5718. @rl_outstream.flush
  5719. if (get_y_or_n(false)==0)
  5720. rl_crlf()
  5721. rl_forced_update_display()
  5722. @rl_display_fixed = true
  5723. return
  5724. end
  5725. end
  5726. rl_display_match_list(matches, len, max)
  5727. rl_forced_update_display()
  5728. @rl_display_fixed = true
  5729. end
  5730. # Complete the word at or before point.
  5731. # WHAT_TO_DO says what to do with the completion.
  5732. # `?' means list the possible completions.
  5733. # TAB means do standard completion.
  5734. # `*' means insert all of the possible completions.
  5735. # `!' means to do standard completion, and list all possible completions if
  5736. # there is more than one.
  5737. # `@' means to do standard completion, and list all possible completions if
  5738. # there is more than one and partial completion is not possible.
  5739. def rl_complete_internal(what_to_do)
  5740. rl_setstate(RL_STATE_COMPLETING)
  5741. set_completion_defaults(what_to_do)
  5742. saved_line_buffer = @rl_line_buffer ? @rl_line_buffer.delete(0.chr) : nil
  5743. our_func = @rl_completion_entry_function ?
  5744. @rl_completion_entry_function : :rl_filename_completion_function
  5745. # We now look backwards for the start of a filename/variable word.
  5746. _end = @rl_point
  5747. found_quote = false
  5748. delimiter = 0.chr
  5749. quote_char = 0.chr
  5750. if (@rl_point!=0)
  5751. # This (possibly) changes rl_point. If it returns a non-zero char,
  5752. # we know we have an open quote.
  5753. quote_char,found_quote,delimiter = _rl_find_completion_word()
  5754. end
  5755. start = @rl_point
  5756. @rl_point = _end
  5757. text = rl_copy_text(start, _end)
  5758. matches = gen_completion_matches(text, start, _end, our_func, found_quote, quote_char)
  5759. # nontrivial_lcd is set if the common prefix adds something to the word
  5760. # being completed.
  5761. nontrivial_lcd = !!(matches && text != matches[0])
  5762. text = nil
  5763. if matches.nil?
  5764. rl_ding()
  5765. saved_line_buffer = nil
  5766. @completion_changed_buffer = false
  5767. rl_unsetstate(RL_STATE_COMPLETING)
  5768. return 0
  5769. end
  5770. # If we are matching filenames, the attempted completion function will
  5771. # have set rl_filename_completion_desired to a non-zero value. The basic
  5772. # rl_filename_completion_function does this.
  5773. i = @rl_filename_completion_desired
  5774. if (postprocess_matches(matches, i) == 0)
  5775. rl_ding()
  5776. saved_line_buffer = nil
  5777. @completion_changed_buffer = false
  5778. rl_unsetstate(RL_STATE_COMPLETING)
  5779. return 0
  5780. end
  5781. case (what_to_do)
  5782. when TAB,'!','@'
  5783. # Insert the first match with proper quoting.
  5784. if (matches[0])
  5785. insert_match(matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, quote_char)
  5786. end
  5787. # If there are more matches, ring the bell to indicate.
  5788. # If we are in vi mode, Posix.2 says to not ring the bell.
  5789. # If the `show-all-if-ambiguous' variable is set, display
  5790. # all the matches immediately. Otherwise, if this was the
  5791. # only match, and we are hacking files, check the file to
  5792. # see if it was a directory. If so, and the `mark-directories'
  5793. # variable is set, add a '/' to the name. If not, and we
  5794. # are at the end of the line, then add a space.
  5795. if (matches[1])
  5796. if (what_to_do == '!')
  5797. display_matches(matches)
  5798. elsif (what_to_do == '@')
  5799. if (!nontrivial_lcd)
  5800. display_matches(matches)
  5801. end
  5802. elsif (@rl_editing_mode != @vi_mode)
  5803. rl_ding() # There are other matches remaining.
  5804. end
  5805. else
  5806. append_to_match(matches[0], delimiter, quote_char, nontrivial_lcd)
  5807. end
  5808. when '*'
  5809. insert_all_matches(matches, start, quote_char)
  5810. when '?'
  5811. display_matches(matches)
  5812. else
  5813. $stderr.write("\r\nreadline: bad value #{what_to_do} for what_to_do in rl_complete\n")
  5814. rl_ding()
  5815. saved_line_buffer = nil
  5816. rl_unsetstate(RL_STATE_COMPLETING)
  5817. return 1
  5818. end
  5819. matches = nil
  5820. # Check to see if the line has changed through all of this manipulation.
  5821. if (saved_line_buffer)
  5822. @completion_changed_buffer = @rl_line_buffer.delete(0.chr) != saved_line_buffer
  5823. saved_line_buffer = nil
  5824. end
  5825. rl_unsetstate(RL_STATE_COMPLETING)
  5826. 0
  5827. end
  5828. # Complete the word at or before point. You have supplied the function
  5829. # that does the initial simple matching selection algorithm (see
  5830. # rl_completion_matches ()). The default is to do filename completion.
  5831. def rl_complete(ignore, invoking_key)
  5832. if (@rl_inhibit_completion)
  5833. return (_rl_insert_char(ignore, invoking_key))
  5834. elsif (@rl_last_func == :rl_complete && !@completion_changed_buffer)
  5835. return (rl_complete_internal('?'))
  5836. elsif (@_rl_complete_show_all)
  5837. return (rl_complete_internal('!'))
  5838. elsif (@_rl_complete_show_unmodified)
  5839. return (rl_complete_internal('@'))
  5840. else
  5841. return (rl_complete_internal(TAB))
  5842. end
  5843. end
  5844. # Return the history entry which is logically at OFFSET in the history array.
  5845. # OFFSET is relative to history_base.
  5846. def history_get(offset)
  5847. local_index = offset - @history_base
  5848. return (local_index >= @history_length || local_index < 0 || @the_history.nil?) ?
  5849. nil : @the_history[local_index]
  5850. end
  5851. def rl_replace_from_history(entry, flags)
  5852. # Can't call with `1' because rl_undo_list might point to an undo list
  5853. # from a history entry, just like we're setting up here.
  5854. rl_replace_line(entry.line, false)
  5855. @rl_undo_list = entry.data
  5856. @rl_point = @rl_end
  5857. @rl_mark = 0
  5858. if (@rl_editing_mode == @vi_mode)
  5859. @rl_point = 0
  5860. @rl_mark = @rl_end
  5861. end
  5862. end
  5863. # Remove history element WHICH from the history. The removed
  5864. # element is returned to you so you can free the line, data,
  5865. # and containing structure.
  5866. def remove_history(which)
  5867. if (which < 0 || which >= @history_length || @history_length == 0 || @the_history.nil?)
  5868. return nil
  5869. end
  5870. return_value = @the_history[which]
  5871. @the_history.delete_at(which)
  5872. @history_length-=1
  5873. return_value
  5874. end
  5875. def block_sigint()
  5876. return if @sigint_blocked
  5877. #@sigint_proc = Signal.trap("INT","IGNORE")
  5878. @sigint_blocked = true
  5879. end
  5880. def release_sigint()
  5881. return if !@sigint_blocked
  5882. #Signal.trap("INT",@sigint_proc)
  5883. @sigint_blocked = false
  5884. end
  5885. def save_tty_chars()
  5886. @_rl_last_tty_chars = @_rl_tty_chars
  5887. h = Hash[*`stty -a`.scan(/(\w+) = ([^;]+);/).flatten]
  5888. h.each {|k,v| v.gsub!(/\^(.)/){($1[0].ord ^ ((?a..?z).include?($1[0]) ? 0x60 : 0x40)).chr}}
  5889. @_rl_tty_chars.t_erase = h['erase']
  5890. @_rl_tty_chars.t_kill = h['kill']
  5891. @_rl_tty_chars.t_intr = h['intr']
  5892. @_rl_tty_chars.t_quit = h['quit']
  5893. @_rl_tty_chars.t_start = h['start']
  5894. @_rl_tty_chars.t_stop = h['stop']
  5895. @_rl_tty_chars.t_eof = h['eof']
  5896. @_rl_tty_chars.t_eol = "\n"
  5897. @_rl_tty_chars.t_eol2 = h['eol2']
  5898. @_rl_tty_chars.t_susp = h['susp']
  5899. @_rl_tty_chars.t_dsusp = h['dsusp']
  5900. @_rl_tty_chars.t_reprint = h['rprnt']
  5901. @_rl_tty_chars.t_flush = h['flush']
  5902. @_rl_tty_chars.t_werase = h['werase']
  5903. @_rl_tty_chars.t_lnext = h['lnext']
  5904. @_rl_tty_chars.t_status = -1
  5905. @otio = `stty -g`
  5906. end
  5907. def _rl_bind_tty_special_chars(kmap)
  5908. kmap[@_rl_tty_chars.t_erase] = :rl_rubout
  5909. kmap[@_rl_tty_chars.t_kill] = :rl_unix_line_discard
  5910. kmap[@_rl_tty_chars.t_werase] = :rl_unix_word_rubout
  5911. kmap[@_rl_tty_chars.t_lnext] = :rl_quoted_insert
  5912. end
  5913. def prepare_terminal_settings(meta_flag)
  5914. @readline_echoing_p = (`stty -a`.scan(/-*echo\b/).first == 'echo')
  5915. # First, the basic settings to put us into character-at-a-time, no-echo
  5916. # input mode.
  5917. setting = " -echo -icrnl cbreak"
  5918. # If this terminal doesn't care how the 8th bit is used, then we can
  5919. # use it for the meta-key. If only one of even or odd parity is
  5920. # specified, then the terminal is using parity, and we cannot.
  5921. if (`stty -a`.scan(/-parenb\b/).first == '-parenb')
  5922. setting << " pass8"
  5923. end
  5924. setting << " -ixoff"
  5925. rl_bind_key(@_rl_tty_chars.t_start, :rl_restart_output)
  5926. @_rl_eof_char = @_rl_tty_chars.t_eof
  5927. #setting << " -isig"
  5928. `stty #{setting}`
  5929. end
  5930. def _rl_control_keypad(on)
  5931. if on && @_rl_term_ks
  5932. @_rl_out_stream.write(@_rl_term_ks)
  5933. elsif !on && @_rl_term_ke
  5934. @_rl_out_stream.write(@_rl_term_ke)
  5935. end
  5936. end
  5937. # Rebind all of the tty special chars that readline worries about back
  5938. # to self-insert. Call this before saving the current terminal special
  5939. # chars with save_tty_chars(). This only works on POSIX termios or termio
  5940. # systems.
  5941. def rl_tty_unset_default_bindings(kmap)
  5942. # Don't bother before we've saved the tty special chars at least once.
  5943. return if (!rl_isstate(RL_STATE_TTYCSAVED))
  5944. kmap[@_rl_tty_chars.t_erase] = :rl_insert
  5945. kmap[@_rl_tty_chars.t_kill] = :rl_insert
  5946. kmap[@_rl_tty_chars.t_lnext] = :rl_insert
  5947. kmap[@_rl_tty_chars.t_werase] = :rl_insert
  5948. end
  5949. def rl_prep_terminal(meta_flag)
  5950. if no_terminal?
  5951. @readline_echoing_p = true
  5952. return
  5953. end
  5954. return if (@terminal_prepped)
  5955. # Try to keep this function from being INTerrupted.
  5956. block_sigint()
  5957. if (@_rl_bind_stty_chars)
  5958. # If editing in vi mode, make sure we restore the bindings in the
  5959. # insertion keymap no matter what keymap we ended up in.
  5960. if (@rl_editing_mode == @vi_mode)
  5961. rl_tty_unset_default_bindings(@vi_insertion_keymap)
  5962. else
  5963. rl_tty_unset_default_bindings(@_rl_keymap)
  5964. end
  5965. end
  5966. save_tty_chars()
  5967. rl_setstate(RL_STATE_TTYCSAVED)
  5968. if (@_rl_bind_stty_chars)
  5969. # If editing in vi mode, make sure we set the bindings in the
  5970. # insertion keymap no matter what keymap we ended up in.
  5971. if (@rl_editing_mode == @vi_mode)
  5972. _rl_bind_tty_special_chars(@vi_insertion_keymap)
  5973. else
  5974. _rl_bind_tty_special_chars(@_rl_keymap)
  5975. end
  5976. end
  5977. prepare_terminal_settings(meta_flag)
  5978. if (@_rl_enable_keypad)
  5979. _rl_control_keypad(true)
  5980. end
  5981. @rl_outstream.flush
  5982. @terminal_prepped = true
  5983. rl_setstate(RL_STATE_TERMPREPPED)
  5984. release_sigint()
  5985. end
  5986. # Restore the terminal's normal settings and modes.
  5987. def rl_deprep_terminal()
  5988. return if ENV["TERM"].nil?
  5989. return if (!@terminal_prepped)
  5990. # Try to keep this function from being interrupted.
  5991. block_sigint()
  5992. if (@_rl_enable_keypad)
  5993. _rl_control_keypad(false)
  5994. end
  5995. @rl_outstream.flush
  5996. # restore terminal setting
  5997. `stty #{@otio}`
  5998. @terminal_prepped = false
  5999. rl_unsetstate(RL_STATE_TERMPREPPED)
  6000. release_sigint()
  6001. end
  6002. # Set the mark at POSITION.
  6003. def _rl_set_mark_at_pos(position)
  6004. return -1 if (position > @rl_end)
  6005. @rl_mark = position
  6006. 0
  6007. end
  6008. # A bindable command to set the mark.
  6009. def rl_set_mark(count, key)
  6010. _rl_set_mark_at_pos(@rl_explicit_arg ? count : @rl_point)
  6011. end
  6012. # Kill from here to the end of the line. If DIRECTION is negative, kill
  6013. # back to the line start instead.
  6014. def rl_kill_line (direction, ignore)
  6015. if (direction < 0)
  6016. return (rl_backward_kill_line(1, ignore))
  6017. else
  6018. orig_point = @rl_point
  6019. rl_end_of_line(1, ignore)
  6020. if (orig_point != @rl_point)
  6021. rl_kill_text(orig_point, @rl_point)
  6022. end
  6023. @rl_point = orig_point
  6024. if (@rl_editing_mode == @emacs_mode)
  6025. @rl_mark = @rl_point
  6026. end
  6027. end
  6028. 0
  6029. end
  6030. # Kill backwards to the start of the line. If DIRECTION is negative, kill
  6031. # forwards to the line end instead.
  6032. def rl_backward_kill_line(direction, ignore)
  6033. if (direction < 0)
  6034. return (rl_kill_line(1, ignore))
  6035. else
  6036. if (@rl_point==0)
  6037. rl_ding()
  6038. else
  6039. orig_point = @rl_point
  6040. rl_beg_of_line(1, ignore)
  6041. if (@rl_point != orig_point)
  6042. rl_kill_text(orig_point, @rl_point)
  6043. end
  6044. if (@rl_editing_mode == @emacs_mode)
  6045. @rl_mark = @rl_point
  6046. end
  6047. end
  6048. end
  6049. 0
  6050. end
  6051. # Kill the whole line, no matter where point is.
  6052. def rl_kill_full_line(count, ignore)
  6053. rl_begin_undo_group()
  6054. @rl_point = 0
  6055. rl_kill_text(@rl_point, @rl_end)
  6056. @rl_mark = 0
  6057. rl_end_undo_group()
  6058. 0
  6059. end
  6060. # Search backwards through the history looking for a string which is typed
  6061. # interactively. Start with the current line.
  6062. def rl_reverse_search_history(sign, key)
  6063. rl_search_history(-sign, key)
  6064. end
  6065. # Search forwards through the history looking for a string which is typed
  6066. # interactively. Start with the current line.
  6067. def rl_forward_search_history(sign, key)
  6068. rl_search_history(sign, key)
  6069. end
  6070. # Search through the history looking for an interactively typed string.
  6071. # This is analogous to i-search. We start the search in the current line.
  6072. # DIRECTION is which direction to search; >= 0 means forward, < 0 means
  6073. # backwards.
  6074. def rl_search_history(direction, invoking_key)
  6075. rl_setstate(RL_STATE_ISEARCH)
  6076. cxt = _rl_isearch_init(direction)
  6077. rl_display_search(cxt.search_string, (cxt.sflags & SF_REVERSE)!=0, -1)
  6078. # If we are using the callback interface, all we do is set up here and
  6079. # return. The key is that we leave RL_STATE_ISEARCH set.
  6080. if (rl_isstate(RL_STATE_CALLBACK))
  6081. return (0)
  6082. end
  6083. r = -1
  6084. while(true)
  6085. c = _rl_search_getchar(cxt)
  6086. # We might want to handle EOF here (c == 0)
  6087. r = _rl_isearch_dispatch(cxt, cxt.lastc)
  6088. break if (r <= 0)
  6089. end
  6090. # The searching is over. The user may have found the string that she
  6091. # was looking for, or else she may have exited a failing search. If
  6092. # LINE_INDEX is -1, then that shows that the string searched for was
  6093. # not found. We use this to determine where to place rl_point.
  6094. _rl_isearch_cleanup(cxt, r)
  6095. end
  6096. def _rl_scxt_alloc(type, flags)
  6097. cxt = Struct.new(:type,:sflags,:search_string,:search_string_index,:search_string_size,:lines,:allocated_line,
  6098. :hlen,:hindex,:save_point,:save_mark,:save_line,:last_found_line,:prev_line_found,:save_undo_list,:history_pos,
  6099. :direction,:lastc,:sline,:sline_len,:sline_index,:search_terminators).new
  6100. cxt.type = type
  6101. cxt.sflags = flags
  6102. cxt.search_string = nil
  6103. cxt.search_string_size = cxt.search_string_index = 0
  6104. cxt.lines = nil
  6105. cxt.allocated_line = nil
  6106. cxt.hlen = cxt.hindex = 0
  6107. cxt.save_point = @rl_point
  6108. cxt.save_mark = @rl_mark
  6109. cxt.save_line = where_history()
  6110. cxt.last_found_line = cxt.save_line
  6111. cxt.prev_line_found = nil
  6112. cxt.save_undo_list = nil
  6113. cxt.history_pos = 0
  6114. cxt.direction = 0
  6115. cxt.lastc = 0
  6116. cxt.sline = nil
  6117. cxt.sline_len = cxt.sline_index = 0
  6118. cxt.search_terminators = nil
  6119. cxt
  6120. end
  6121. def history_list()
  6122. @the_history
  6123. end
  6124. def _rl_isearch_init(direction)
  6125. cxt = _rl_scxt_alloc(RL_SEARCH_ISEARCH, 0)
  6126. if (direction < 0)
  6127. cxt.sflags |= SF_REVERSE
  6128. end
  6129. cxt.search_terminators = @_rl_isearch_terminators ? @_rl_isearch_terminators :
  6130. @default_isearch_terminators
  6131. # Create an arrary of pointers to the lines that we want to search.
  6132. hlist = history_list()
  6133. rl_maybe_replace_line()
  6134. i = 0
  6135. if (hlist)
  6136. i += 1 while(hlist[i])
  6137. end
  6138. # Allocate space for this many lines, +1 for the current input line,
  6139. # and remember those lines.
  6140. cxt.hlen = i
  6141. cxt.lines = Array.new(cxt.hlen+1)
  6142. for i in 0 ... cxt.hlen
  6143. cxt.lines[i] = hlist[i].line
  6144. end
  6145. if (@_rl_saved_line_for_history)
  6146. cxt.lines[i] = @_rl_saved_line_for_history.line.dup
  6147. else
  6148. # Keep track of this so we can free it.
  6149. cxt.allocated_line = @rl_line_buffer.dup
  6150. cxt.lines[i] = cxt.allocated_line
  6151. end
  6152. cxt.hlen+=1
  6153. # The line where we start the search.
  6154. cxt.history_pos = cxt.save_line
  6155. rl_save_prompt()
  6156. # Initialize search parameters.
  6157. cxt.search_string_size = 128
  6158. cxt.search_string_index = 0
  6159. cxt.search_string = 0.chr * cxt.search_string_size
  6160. # Normalize DIRECTION into 1 or -1.
  6161. cxt.direction = (direction >= 0) ? 1 : -1
  6162. cxt.sline = @rl_line_buffer
  6163. cxt.sline_len = cxt.sline.delete(0.chr).length
  6164. cxt.sline_index = @rl_point
  6165. @_rl_iscxt = cxt # save globally
  6166. cxt
  6167. end
  6168. def rl_save_prompt()
  6169. @saved_local_prompt = @local_prompt
  6170. @saved_local_prefix = @local_prompt_prefix
  6171. @saved_prefix_length = @prompt_prefix_length
  6172. @saved_local_length = @local_prompt_len
  6173. @saved_last_invisible = @prompt_last_invisible
  6174. @saved_visible_length = @prompt_visible_length
  6175. @saved_invis_chars_first_line = @prompt_invis_chars_first_line
  6176. @saved_physical_chars = @prompt_physical_chars
  6177. @local_prompt = @local_prompt_prefix = nil
  6178. @local_prompt_len = 0
  6179. @prompt_last_invisible = @prompt_visible_length = @prompt_prefix_length = 0
  6180. @prompt_invis_chars_first_line = @prompt_physical_chars = 0
  6181. end
  6182. def rl_restore_prompt()
  6183. @local_prompt = nil
  6184. @local_prompt_prefix = nil
  6185. @local_prompt = @saved_local_prompt
  6186. @local_prompt_prefix = @saved_local_prefix
  6187. @local_prompt_len = @saved_local_length
  6188. @prompt_prefix_length = @saved_prefix_length
  6189. @prompt_last_invisible = @saved_last_invisible
  6190. @prompt_visible_length = @saved_visible_length
  6191. @prompt_invis_chars_first_line = @saved_invis_chars_first_line
  6192. @prompt_physical_chars = @saved_physical_chars
  6193. # can test saved_local_prompt to see if prompt info has been saved.
  6194. @saved_local_prompt = @saved_local_prefix = nil
  6195. @saved_local_length = 0
  6196. @saved_last_invisible = @saved_visible_length = @saved_prefix_length = 0
  6197. @saved_invis_chars_first_line = @saved_physical_chars = 0
  6198. end
  6199. def rl_message(msg_buf)
  6200. @rl_display_prompt = msg_buf
  6201. if @saved_local_prompt.nil?
  6202. rl_save_prompt()
  6203. @msg_saved_prompt = true
  6204. end
  6205. @local_prompt,@prompt_visible_length,@prompt_last_invisible,@prompt_invis_chars_first_line,@prompt_physical_chars =
  6206. expand_prompt(msg_buf)
  6207. @local_prompt_prefix = nil
  6208. @local_prompt_len = @local_prompt ? @local_prompt.length : 0
  6209. send(@rl_redisplay_function)
  6210. 0
  6211. end
  6212. # Display the current state of the search in the echo-area.
  6213. # SEARCH_STRING contains the string that is being searched for,
  6214. # DIRECTION is zero for forward, or non-zero for reverse,
  6215. # WHERE is the history list number of the current line. If it is
  6216. # -1, then this line is the starting one.
  6217. def rl_display_search(search_string, reverse_p, where)
  6218. message = '('
  6219. if (reverse_p)
  6220. message << "reverse-"
  6221. end
  6222. message << "i-search)`"
  6223. if (search_string)
  6224. message << search_string
  6225. end
  6226. message << "': "
  6227. rl_message(message)
  6228. message = nil
  6229. send(@rl_redisplay_function)
  6230. end
  6231. # Transpose the characters at point. If point is at the end of the line,
  6232. # then transpose the characters before point.
  6233. def rl_transpose_chars(count, key)
  6234. return 0 if (count == 0)
  6235. if (@rl_point==0 || @rl_end < 2)
  6236. rl_ding()
  6237. return -1
  6238. end
  6239. rl_begin_undo_group()
  6240. if (@rl_point == @rl_end)
  6241. if !@rl_byte_oriented
  6242. @rl_point = _rl_find_prev_mbchar(@rl_line_buffer, @rl_point, MB_FIND_NONZERO)
  6243. else
  6244. @rl_point -= 1
  6245. end
  6246. count = 1
  6247. end
  6248. prev_point = @rl_point
  6249. if !@rl_byte_oriented
  6250. @rl_point = _rl_find_prev_mbchar(@rl_line_buffer, @rl_point, MB_FIND_NONZERO)
  6251. else
  6252. @rl_point -= 1
  6253. end
  6254. char_length = prev_point - @rl_point
  6255. dummy = @rl_line_buffer[@rl_point,char_length]
  6256. rl_delete_text(@rl_point, @rl_point + char_length)
  6257. @rl_point += count
  6258. _rl_fix_point(0)
  6259. rl_insert_text(dummy)
  6260. rl_end_undo_group()
  6261. dummy = nil
  6262. 0
  6263. end
  6264. # Here is C-u doing what Unix does. You don't *have* to use these
  6265. # key-bindings. We have a choice of killing the entire line, or
  6266. # killing from where we are to the start of the line. We choose the
  6267. # latter, because if you are a Unix weenie, then you haven't backspaced
  6268. # into the line at all, and if you aren't, then you know what you are
  6269. # doing.
  6270. def rl_unix_line_discard(count, key)
  6271. if (@rl_point == 0)
  6272. rl_ding()
  6273. else
  6274. rl_kill_text(@rl_point, 0)
  6275. @rl_point = 0
  6276. if (@rl_editing_mode == @emacs_mode)
  6277. @rl_mark = @rl_point
  6278. end
  6279. end
  6280. 0
  6281. end
  6282. # Yank back the last killed text. This ignores arguments.
  6283. def rl_yank(count, ignore)
  6284. if @rl_kill_ring.nil?
  6285. _rl_abort_internal()
  6286. return -1
  6287. end
  6288. _rl_set_mark_at_pos(@rl_point)
  6289. rl_insert_text(@rl_kill_ring[@rl_kill_index])
  6290. 0
  6291. end
  6292. # If the last command was yank, or yank_pop, and the text just
  6293. # before point is identical to the current kill item, then
  6294. # delete that text from the line, rotate the index down, and
  6295. # yank back some other text.
  6296. def rl_yank_pop(count, key)
  6297. if (((@rl_last_func != :rl_yank_pop) && (@rl_last_func != :rl_yank)) ||
  6298. @rl_kill_ring.nil?)
  6299. _rl_abort_internal()
  6300. return -1
  6301. end
  6302. l = @rl_kill_ring[@rl_kill_index].length
  6303. n = @rl_point - l
  6304. if (n >= 0 && @rl_line_buffer[n,l] == @rl_kill_ring[@rl_kill_index][0,l])
  6305. rl_delete_text(n, @rl_point)
  6306. @rl_point = n
  6307. @rl_kill_index-=1
  6308. if (@rl_kill_index < 0)
  6309. @rl_kill_index = @rl_kill_ring_length - 1
  6310. end
  6311. rl_yank(1, 0)
  6312. return 0
  6313. else
  6314. _rl_abort_internal()
  6315. return -1
  6316. end
  6317. end
  6318. # Yank the COUNTh argument from the previous history line, skipping
  6319. # HISTORY_SKIP lines before looking for the `previous line'.
  6320. def rl_yank_nth_arg_internal(count, ignore, history_skip)
  6321. pos = where_history()
  6322. if (history_skip>0)
  6323. history_skip.times { entry = previous_history() }
  6324. end
  6325. entry = previous_history()
  6326. history_set_pos(pos)
  6327. if entry.nil?
  6328. rl_ding()
  6329. return -1
  6330. end
  6331. arg = history_arg_extract(count, count, entry.line)
  6332. if (arg.nil? || arg=='')
  6333. rl_ding()
  6334. arg = nil
  6335. return -1
  6336. end
  6337. rl_begin_undo_group()
  6338. _rl_set_mark_at_pos(@rl_point)
  6339. # Vi mode always inserts a space before yanking the argument, and it
  6340. # inserts it right *after* rl_point.
  6341. if (@rl_editing_mode == @vi_mode)
  6342. rl_vi_append_mode(1, ignore)
  6343. rl_insert_text(" ")
  6344. end
  6345. rl_insert_text(arg)
  6346. arg = nil
  6347. rl_end_undo_group()
  6348. return 0
  6349. end
  6350. # Yank the COUNTth argument from the previous history line.
  6351. def rl_yank_nth_arg(count, ignore)
  6352. rl_yank_nth_arg_internal(count, ignore, 0)
  6353. end
  6354. # Yank the last argument from the previous history line. This `knows'
  6355. # how rl_yank_nth_arg treats a count of `$'. With an argument, this
  6356. # behaves the same as rl_yank_nth_arg.
  6357. @history_skip = 0
  6358. @explicit_arg_p = false
  6359. @count_passed = 1
  6360. @direction = 1
  6361. @undo_needed = false
  6362. def rl_yank_last_arg(count, key)
  6363. if (@rl_last_func != :rl_yank_last_arg)
  6364. @history_skip = 0
  6365. @explicit_arg_p = @rl_explicit_arg
  6366. @count_passed = count
  6367. @direction = 1
  6368. else
  6369. if (@undo_needed)
  6370. rl_do_undo()
  6371. end
  6372. if (count < 1)
  6373. @direction = -@direction
  6374. end
  6375. @history_skip += @direction
  6376. if (@history_skip < 0)
  6377. @history_skip = 0
  6378. end
  6379. end
  6380. if (@explicit_arg_p)
  6381. retval = rl_yank_nth_arg_internal(@count_passed, key, @history_skip)
  6382. else
  6383. retval = rl_yank_nth_arg_internal('$', key, @history_skip)
  6384. end
  6385. @undo_needed = retval == 0
  6386. retval
  6387. end
  6388. def _rl_char_search_internal(count, dir, smbchar, len)
  6389. pos = @rl_point
  6390. inc = (dir < 0) ? -1 : 1
  6391. while (count!=0)
  6392. if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= @rl_end))
  6393. rl_ding()
  6394. return -1
  6395. end
  6396. pos = (inc > 0) ? _rl_find_next_mbchar(@rl_line_buffer, pos, 1, MB_FIND_ANY) :
  6397. _rl_find_prev_mbchar(@rl_line_buffer, pos, MB_FIND_ANY)
  6398. begin
  6399. if (_rl_is_mbchar_matched(@rl_line_buffer, pos, @rl_end, smbchar, len)!=0)
  6400. count-=1
  6401. if (dir < 0)
  6402. @rl_point = (dir == BTO) ? pos+1 : pos
  6403. else
  6404. @rl_point = (dir == FTO) ? pos-1 : pos
  6405. end
  6406. break
  6407. end
  6408. prepos = pos
  6409. end while ((dir < 0) ? (pos = _rl_find_prev_mbchar(@rl_line_buffer, pos, MB_FIND_ANY)) != prepos :
  6410. (pos = _rl_find_next_mbchar(@rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos)
  6411. end
  6412. 0
  6413. end
  6414. def _rl_char_search(count, fdir, bdir)
  6415. mbchar = ''
  6416. mb_len = _rl_read_mbchar(mbchar, MB_LEN_MAX)
  6417. if (count < 0)
  6418. return (_rl_char_search_internal(-count, bdir, mbchar, mb_len))
  6419. else
  6420. return (_rl_char_search_internal(count, fdir, mbchar, mb_len))
  6421. end
  6422. end
  6423. def rl_char_search(count, key)
  6424. _rl_char_search(count, FFIND, BFIND)
  6425. end
  6426. # Undo the next thing in the list. Return 0 if there
  6427. # is nothing to undo, or non-zero if there was.
  6428. def trans(i)
  6429. ((i) == -1 ? @rl_point : ((i) == -2 ? @rl_end : (i)))
  6430. end
  6431. def rl_do_undo()
  6432. start = _end = waiting_for_begin = 0
  6433. begin
  6434. return 0 if @rl_undo_list.nil?
  6435. @_rl_doing_an_undo = true
  6436. rl_setstate(RL_STATE_UNDOING)
  6437. # To better support vi-mode, a start or end value of -1 means
  6438. # rl_point, and a value of -2 means rl_end.
  6439. if (@rl_undo_list.what == UNDO_DELETE || @rl_undo_list.what == UNDO_INSERT)
  6440. start = trans(@rl_undo_list.start)
  6441. _end = trans(@rl_undo_list.end)
  6442. end
  6443. case (@rl_undo_list.what)
  6444. # Undoing deletes means inserting some text.
  6445. when UNDO_DELETE
  6446. @rl_point = start
  6447. rl_insert_text(@rl_undo_list.text)
  6448. @rl_undo_list.text = nil
  6449. # Undoing inserts means deleting some text.
  6450. when UNDO_INSERT
  6451. rl_delete_text(start, _end)
  6452. @rl_point = start
  6453. # Undoing an END means undoing everything 'til we get to a BEGIN.
  6454. when UNDO_END
  6455. waiting_for_begin+=1
  6456. # Undoing a BEGIN means that we are done with this group.
  6457. when UNDO_BEGIN
  6458. if (waiting_for_begin!=0)
  6459. waiting_for_begin-=1
  6460. else
  6461. rl_ding()
  6462. end
  6463. end
  6464. @_rl_doing_an_undo = false
  6465. rl_unsetstate(RL_STATE_UNDOING)
  6466. release = @rl_undo_list
  6467. @rl_undo_list = @rl_undo_list.next
  6468. replace_history_data(-1, release, @rl_undo_list)
  6469. release = nil
  6470. end while (waiting_for_begin!=0)
  6471. 1
  6472. end
  6473. # Do some undoing of things that were done.
  6474. def rl_undo_command(count, key)
  6475. if (count < 0)
  6476. return 0 # Nothing to do.
  6477. end
  6478. while (count>0)
  6479. if (rl_do_undo())
  6480. count-=1
  6481. else
  6482. rl_ding()
  6483. break
  6484. end
  6485. end
  6486. 0
  6487. end
  6488. # Delete the word at point, saving the text in the kill ring.
  6489. def rl_kill_word(count, key)
  6490. if (count < 0)
  6491. return (rl_backward_kill_word(-count, key))
  6492. else
  6493. orig_point = @rl_point
  6494. rl_forward_word(count, key)
  6495. if (@rl_point != orig_point)
  6496. rl_kill_text(orig_point, @rl_point)
  6497. end
  6498. @rl_point = orig_point
  6499. if (@rl_editing_mode == @emacs_mode)
  6500. rl_mark = @rl_point
  6501. end
  6502. end
  6503. 0
  6504. end
  6505. # Rubout the word before point, placing it on the kill ring.
  6506. def rl_backward_kill_word(count, ignore)
  6507. if (count < 0)
  6508. return (rl_kill_word(-count, ignore))
  6509. else
  6510. orig_point = @rl_point
  6511. rl_backward_word(count, ignore)
  6512. if (@rl_point != orig_point)
  6513. rl_kill_text(orig_point, @rl_point)
  6514. end
  6515. if (@rl_editing_mode == @emacs_mode)
  6516. @rl_mark = @rl_point
  6517. end
  6518. end
  6519. 0
  6520. end
  6521. # Revert the current line to its previous state.
  6522. def rl_revert_line(count, key)
  6523. if @rl_undo_list.nil?
  6524. rl_ding()
  6525. else
  6526. while (@rl_undo_list)
  6527. rl_do_undo()
  6528. end
  6529. if (@rl_editing_mode == @vi_mode)
  6530. @rl_point = @rl_mark = 0 # rl_end should be set correctly
  6531. end
  6532. end
  6533. 0
  6534. end
  6535. def rl_backward_char_search (count, key)
  6536. _rl_char_search(count, BFIND, FFIND)
  6537. end
  6538. def rl_insert_completions(ignore, invoking_key)
  6539. rl_complete_internal('*')
  6540. end
  6541. def _rl_arg_init()
  6542. rl_save_prompt()
  6543. @_rl_argcxt = 0
  6544. rl_setstate(RL_STATE_NUMERICARG)
  6545. end
  6546. def _rl_arg_getchar()
  6547. rl_message("(arg: #{@rl_arg_sign * @rl_numeric_arg}) ")
  6548. rl_setstate(RL_STATE_MOREINPUT)
  6549. c = rl_read_key()
  6550. rl_unsetstate(RL_STATE_MOREINPUT)
  6551. c
  6552. end
  6553. # Process C as part of the current numeric argument. Return -1 if the
  6554. # argument should be aborted, 0 if we should not read any more chars, and
  6555. # 1 if we should continue to read chars.
  6556. def _rl_arg_dispatch(cxt, c)
  6557. key = c
  6558. # If we see a key bound to `universal-argument' after seeing digits,
  6559. # it ends the argument but is otherwise ignored.
  6560. if (@_rl_keymap[c] == :rl_universal_argument)
  6561. if ((cxt & NUM_SAWDIGITS) == 0)
  6562. @rl_numeric_arg *= 4
  6563. return 1
  6564. elsif (rl_isstate(RL_STATE_CALLBACK))
  6565. @_rl_argcxt |= NUM_READONE
  6566. return 0 # XXX
  6567. else
  6568. rl_setstate(RL_STATE_MOREINPUT)
  6569. key = rl_read_key()
  6570. rl_unsetstate(RL_STATE_MOREINPUT)
  6571. rl_restore_prompt()
  6572. rl_clear_message()
  6573. rl_unsetstate(RL_STATE_NUMERICARG)
  6574. return (_rl_dispatch(key, @_rl_keymap))
  6575. end
  6576. end
  6577. #c = (c[0].ord & ~0x80).chr
  6578. r = c[1,1]
  6579. if (r>='0' && r<='9')
  6580. r = r.to_i
  6581. @rl_numeric_arg = @rl_explicit_arg ? (@rl_numeric_arg * 10) + r : r
  6582. @rl_explicit_arg = 1
  6583. @_rl_argcxt |= NUM_SAWDIGITS
  6584. elsif (c == '-' && !@rl_explicit_arg)
  6585. @rl_numeric_arg = 1
  6586. @_rl_argcxt |= NUM_SAWMINUS
  6587. @rl_arg_sign = -1
  6588. else
  6589. # Make M-- command equivalent to M--1 command.
  6590. if ((@_rl_argcxt & NUM_SAWMINUS)!=0 && @rl_numeric_arg == 1 && !@rl_explicit_arg)
  6591. @rl_explicit_arg = 1
  6592. end
  6593. rl_restore_prompt()
  6594. rl_clear_message()
  6595. rl_unsetstate(RL_STATE_NUMERICARG)
  6596. r = _rl_dispatch(key, @_rl_keymap)
  6597. if (rl_isstate(RL_STATE_CALLBACK))
  6598. # At worst, this will cause an extra redisplay. Otherwise,
  6599. # we have to wait until the next character comes in.
  6600. if (!@rl_done)
  6601. send(@rl_redisplay_function)
  6602. end
  6603. r = 0
  6604. end
  6605. return r
  6606. end
  6607. 1
  6608. end
  6609. def _rl_arg_overflow()
  6610. if (@rl_numeric_arg > 1000000)
  6611. @_rl_argcxt = 0
  6612. @rl_explicit_arg = @rl_numeric_arg = 0
  6613. rl_ding()
  6614. rl_restore_prompt()
  6615. rl_clear_message()
  6616. rl_unsetstate(RL_STATE_NUMERICARG)
  6617. return 1
  6618. end
  6619. 0
  6620. end
  6621. # Handle C-u style numeric args, as well as M--, and M-digits.
  6622. def rl_digit_loop()
  6623. while (true)
  6624. return 1 if _rl_arg_overflow()!=0
  6625. c = _rl_arg_getchar()
  6626. if (c >= "\xFE")
  6627. _rl_abort_internal()
  6628. return -1
  6629. end
  6630. r = _rl_arg_dispatch(@_rl_argcxt, c)
  6631. break if (r <= 0 || !rl_isstate(RL_STATE_NUMERICARG))
  6632. end
  6633. return r
  6634. end
  6635. # Start a numeric argument with initial value KEY
  6636. def rl_digit_argument(ignore, key)
  6637. _rl_arg_init()
  6638. if (rl_isstate(RL_STATE_CALLBACK))
  6639. _rl_arg_dispatch(@_rl_argcxt, key)
  6640. rl_message("(arg: #{@rl_arg_sign * @rl_numeric_arg}) ")
  6641. return 0
  6642. else
  6643. rl_execute_next(key)
  6644. return (rl_digit_loop())
  6645. end
  6646. end
  6647. # Make C be the next command to be executed.
  6648. def rl_execute_next(c)
  6649. @rl_pending_input = c
  6650. rl_setstate(RL_STATE_INPUTPENDING)
  6651. 0
  6652. end
  6653. # Meta-< goes to the start of the history.
  6654. def rl_beginning_of_history(count, key)
  6655. rl_get_previous_history(1 + where_history(), key)
  6656. end
  6657. # Meta-> goes to the end of the history. (The current line).
  6658. def rl_end_of_history(count, key)
  6659. rl_maybe_replace_line()
  6660. using_history()
  6661. rl_maybe_unsave_line()
  6662. 0
  6663. end
  6664. # Uppercase the word at point.
  6665. def rl_upcase_word(count, key)
  6666. rl_change_case(count, UpCase)
  6667. end
  6668. # Lowercase the word at point.
  6669. def rl_downcase_word(count, key)
  6670. rl_change_case(count, DownCase)
  6671. end
  6672. # Upcase the first letter, downcase the rest.
  6673. def rl_capitalize_word(count, key)
  6674. rl_change_case(count, CapCase)
  6675. end
  6676. # Save an undo entry for the text from START to END.
  6677. def rl_modifying(start, _end)
  6678. if (start > _end)
  6679. start,_end = _end,start
  6680. end
  6681. if (start != _end)
  6682. temp = rl_copy_text(start, _end)
  6683. rl_begin_undo_group()
  6684. rl_add_undo(UNDO_DELETE, start, _end, temp)
  6685. rl_add_undo(UNDO_INSERT, start, _end, nil)
  6686. rl_end_undo_group()
  6687. end
  6688. 0
  6689. end
  6690. # The meaty function.
  6691. # Change the case of COUNT words, performing OP on them.
  6692. # OP is one of UpCase, DownCase, or CapCase.
  6693. # If a negative argument is given, leave point where it started,
  6694. # otherwise, leave it where it moves to.
  6695. def rl_change_case(count, op)
  6696. start = @rl_point
  6697. rl_forward_word(count, 0)
  6698. _end = @rl_point
  6699. if (op != UpCase && op != DownCase && op != CapCase)
  6700. rl_ding()
  6701. return -1
  6702. end
  6703. if (count < 0)
  6704. start,_end = _end,start
  6705. end
  6706. # We are going to modify some text, so let's prepare to undo it.
  6707. rl_modifying(start, _end)
  6708. inword = false
  6709. while (start < _end)
  6710. c = _rl_char_value(@rl_line_buffer, start)
  6711. # This assumes that the upper and lower case versions are the same width.
  6712. if !@rl_byte_oriented
  6713. _next = _rl_find_next_mbchar(@rl_line_buffer, start, 1, MB_FIND_NONZERO)
  6714. else
  6715. _next = start + 1
  6716. end
  6717. if (!_rl_walphabetic(c))
  6718. inword = false
  6719. start = _next
  6720. next
  6721. end
  6722. if (op == CapCase)
  6723. nop = inword ? DownCase : UpCase
  6724. inword = true
  6725. else
  6726. nop = op
  6727. end
  6728. if (isascii(c))
  6729. nc = (nop == UpCase) ? c.upcase : c.downcase
  6730. @rl_line_buffer[start] = nc
  6731. end
  6732. start = _next
  6733. end
  6734. @rl_point = _end
  6735. 0
  6736. end
  6737. def isascii(c)
  6738. int_val = c[0].to_i # 1.8 + 1.9 compat.
  6739. return (int_val < 128 && int_val > 0)
  6740. end
  6741. # Search non-interactively through the history list. DIR < 0 means to
  6742. # search backwards through the history of previous commands; otherwise
  6743. # the search is for commands subsequent to the current position in the
  6744. # history list. PCHAR is the character to use for prompting when reading
  6745. # the search string; if not specified (0), it defaults to `:'.
  6746. def noninc_search(dir, pchar)
  6747. cxt = _rl_nsearch_init(dir, pchar)
  6748. if (rl_isstate(RL_STATE_CALLBACK))
  6749. return (0)
  6750. end
  6751. # Read the search string.
  6752. r = 0
  6753. while (true)
  6754. c = _rl_search_getchar(cxt)
  6755. if (c == 0.chr)
  6756. break
  6757. end
  6758. r = _rl_nsearch_dispatch(cxt, c)
  6759. if (r < 0)
  6760. return 1
  6761. elsif (r == 0)
  6762. break
  6763. end
  6764. end
  6765. r = _rl_nsearch_dosearch(cxt)
  6766. (r >= 0) ? _rl_nsearch_cleanup(cxt, r) : (r != 1)
  6767. end
  6768. # Search forward through the history list for a string. If the vi-mode
  6769. # code calls this, KEY will be `?'.
  6770. def rl_noninc_forward_search(count, key)
  6771. noninc_search(1, (key == '?') ? '?' : nil)
  6772. end
  6773. # Reverse search the history list for a string. If the vi-mode code
  6774. # calls this, KEY will be `/'.
  6775. def rl_noninc_reverse_search(count, key)
  6776. noninc_search(-1, (key == '/') ? '/' : nil)
  6777. end
  6778. # Make the data from the history entry ENTRY be the contents of the
  6779. # current line. This doesn't do anything with rl_point; the caller
  6780. # must set it.
  6781. def make_history_line_current(entry)
  6782. _rl_replace_text(entry.line, 0, @rl_end)
  6783. _rl_fix_point(1)
  6784. if (@rl_editing_mode == @vi_mode)
  6785. # POSIX.2 says that the `U' command doesn't affect the copy of any
  6786. # command lines to the edit line. We're going to implement that by
  6787. # making the undo list start after the matching line is copied to the
  6788. # current editing buffer.
  6789. rl_free_undo_list()
  6790. end
  6791. if (@_rl_saved_line_for_history)
  6792. @_rl_saved_line_for_history = nil
  6793. end
  6794. end
  6795. # Make the current history item be the one at POS, an absolute index.
  6796. # Returns zero if POS is out of range, else non-zero.
  6797. def history_set_pos(pos)
  6798. if (pos > @history_length || pos < 0 || @the_history.nil?)
  6799. return (0)
  6800. end
  6801. @history_offset = pos
  6802. 1
  6803. end
  6804. # Do an anchored search for string through the history in DIRECTION.
  6805. def history_search_prefix (string, direction)
  6806. history_search_internal(string, direction, ANCHORED_SEARCH)
  6807. end
  6808. # Search for STRING in the history list. DIR is < 0 for searching
  6809. # backwards. POS is an absolute index into the history list at
  6810. # which point to begin searching.
  6811. def history_search_pos(string, dir, pos)
  6812. old = where_history()
  6813. history_set_pos(pos)
  6814. if (history_search(string, dir) == -1)
  6815. history_set_pos(old)
  6816. return (-1)
  6817. end
  6818. ret = where_history()
  6819. history_set_pos(old)
  6820. ret
  6821. end
  6822. # Search the history list for STRING starting at absolute history position
  6823. # POS. If STRING begins with `^', the search must match STRING at the
  6824. # beginning of a history line, otherwise a full substring match is performed
  6825. # for STRING. DIR < 0 means to search backwards through the history list,
  6826. # DIR >= 0 means to search forward.
  6827. def noninc_search_from_pos(string, pos, dir)
  6828. return 1 if (pos < 0)
  6829. old = where_history()
  6830. return -1 if (history_set_pos(pos) == 0)
  6831. rl_setstate(RL_STATE_SEARCH)
  6832. if (string[0,1] == '^')
  6833. ret = history_search_prefix(string + 1, dir)
  6834. else
  6835. ret = history_search(string, dir)
  6836. end
  6837. rl_unsetstate(RL_STATE_SEARCH)
  6838. if (ret != -1)
  6839. ret = where_history()
  6840. end
  6841. history_set_pos(old)
  6842. ret
  6843. end
  6844. # Search for a line in the history containing STRING. If DIR is < 0, the
  6845. # search is backwards through previous entries, else through subsequent
  6846. # entries. Returns 1 if the search was successful, 0 otherwise.
  6847. def noninc_dosearch(string, dir)
  6848. if (string.nil? || string == '' || @noninc_history_pos < 0)
  6849. rl_ding()
  6850. return 0
  6851. end
  6852. pos = noninc_search_from_pos(string, @noninc_history_pos + dir, dir)
  6853. if (pos == -1)
  6854. # Search failed, current history position unchanged.
  6855. rl_maybe_unsave_line()
  6856. rl_clear_message()
  6857. @rl_point = 0
  6858. rl_ding()
  6859. return 0
  6860. end
  6861. @noninc_history_pos = pos
  6862. oldpos = where_history()
  6863. history_set_pos(@noninc_history_pos)
  6864. entry = current_history()
  6865. if (@rl_editing_mode != @vi_mode)
  6866. history_set_pos(oldpos)
  6867. end
  6868. make_history_line_current(entry)
  6869. @rl_point = 0
  6870. @rl_mark = @rl_end
  6871. rl_clear_message()
  6872. 1
  6873. end
  6874. def _rl_make_prompt_for_search(pchar)
  6875. rl_save_prompt()
  6876. # We've saved the prompt, and can do anything with the various prompt
  6877. # strings we need before they're restored. We want the unexpanded
  6878. # portion of the prompt string after any final newline.
  6879. _p = @rl_prompt ? @rl_prompt.rindex("\n") : nil
  6880. if _p.nil?
  6881. len = (@rl_prompt && @rl_prompt.length>0 ) ? @rl_prompt.length : 0
  6882. if (len>0)
  6883. pmt = @rl_prompt.dup
  6884. else
  6885. pmt = ''
  6886. end
  6887. pmt << pchar
  6888. else
  6889. _p+=1
  6890. pmt = @rl_prompt[_p..-1]
  6891. pmt << pchar
  6892. end
  6893. # will be overwritten by expand_prompt, called from rl_message
  6894. @prompt_physical_chars = @saved_physical_chars + 1
  6895. pmt
  6896. end
  6897. def _rl_nsearch_init(dir, pchar)
  6898. cxt = _rl_scxt_alloc(RL_SEARCH_NSEARCH, 0)
  6899. if (dir < 0)
  6900. cxt.sflags |= SF_REVERSE # not strictly needed
  6901. end
  6902. cxt.direction = dir
  6903. cxt.history_pos = cxt.save_line
  6904. rl_maybe_save_line()
  6905. # Clear the undo list, since reading the search string should create its
  6906. # own undo list, and the whole list will end up being freed when we
  6907. # finish reading the search string.
  6908. @rl_undo_list = nil
  6909. # Use the line buffer to read the search string.
  6910. @rl_line_buffer[0] = 0.chr
  6911. @rl_end = @rl_point = 0
  6912. _p = _rl_make_prompt_for_search(pchar ? pchar : ':')
  6913. rl_message(_p)
  6914. _p = nil
  6915. rl_setstate(RL_STATE_NSEARCH)
  6916. @_rl_nscxt = cxt
  6917. cxt
  6918. end
  6919. def _rl_nsearch_cleanup(cxt, r)
  6920. cxt = nil
  6921. @_rl_nscxt = nil
  6922. rl_unsetstate(RL_STATE_NSEARCH)
  6923. r != 1
  6924. end
  6925. def _rl_nsearch_abort(cxt)
  6926. rl_maybe_unsave_line()
  6927. rl_clear_message()
  6928. @rl_point = cxt.save_point
  6929. @rl_mark = cxt.save_mark
  6930. rl_restore_prompt()
  6931. rl_unsetstate(RL_STATE_NSEARCH)
  6932. end
  6933. # Process just-read character C according to search context CXT. Return -1
  6934. # if the caller should abort the search, 0 if we should break out of the
  6935. # loop, and 1 if we should continue to read characters.
  6936. def _rl_nsearch_dispatch(cxt, c)
  6937. case (c)
  6938. when "\C-W"
  6939. rl_unix_word_rubout(1, c)
  6940. when "\C-W"
  6941. rl_unix_line_discard(1, c)
  6942. when RETURN,NEWLINE
  6943. return 0
  6944. when "\C-H",RUBOUT
  6945. if (@rl_point == 0)
  6946. _rl_nsearch_abort(cxt)
  6947. return -1
  6948. end
  6949. _rl_rubout_char(1, c)
  6950. when "\C-C","\C-G"
  6951. rl_ding()
  6952. _rl_nsearch_abort(cxt)
  6953. return -1
  6954. else
  6955. if !@rl_byte_oriented
  6956. rl_insert_text(cxt.mb)
  6957. else
  6958. _rl_insert_char(1, c)
  6959. end
  6960. end
  6961. send(@rl_redisplay_function)
  6962. 1
  6963. end
  6964. # Perform one search according to CXT, using NONINC_SEARCH_STRING. Return
  6965. # -1 if the search should be aborted, any other value means to clean up
  6966. # using _rl_nsearch_cleanup (). Returns 1 if the search was successful,
  6967. # 0 otherwise.
  6968. def _rl_nsearch_dosearch(cxt)
  6969. @rl_mark = cxt.save_mark
  6970. # If rl_point == 0, we want to re-use the previous search string and
  6971. # start from the saved history position. If there's no previous search
  6972. # string, punt.
  6973. if (@rl_point == 0)
  6974. if @noninc_search_string.nil?
  6975. rl_ding()
  6976. rl_restore_prompt()
  6977. rl_unsetstate(RL_STATE_NSEARCH)
  6978. return -1
  6979. end
  6980. else
  6981. # We want to start the search from the current history position.
  6982. @noninc_history_pos = cxt.save_line
  6983. @noninc_search_string = @rl_line_buffer.dup
  6984. # If we don't want the subsequent undo list generated by the search
  6985. #matching a history line to include the contents of the search string,
  6986. #we need to clear rl_line_buffer here. For now, we just clear the
  6987. #undo list generated by reading the search string. (If the search
  6988. #fails, the old undo list will be restored by rl_maybe_unsave_line.)
  6989. rl_free_undo_list()
  6990. end
  6991. rl_restore_prompt()
  6992. noninc_dosearch(@noninc_search_string, cxt.direction)
  6993. end
  6994. # Transpose the words at point. If point is at the end of the line,
  6995. # transpose the two words before point.
  6996. def rl_transpose_words(count, key)
  6997. orig_point = @rl_point
  6998. return if (count==0)
  6999. # Find the two words.
  7000. rl_forward_word(count, key)
  7001. w2_end = @rl_point
  7002. rl_backward_word(1, key)
  7003. w2_beg = @rl_point
  7004. rl_backward_word(count, key)
  7005. w1_beg = @rl_point
  7006. rl_forward_word(1, key)
  7007. w1_end = @rl_point
  7008. # Do some check to make sure that there really are two words.
  7009. if ((w1_beg == w2_beg) || (w2_beg < w1_end))
  7010. rl_ding()
  7011. @rl_point = orig_point
  7012. return -1
  7013. end
  7014. # Get the text of the words.
  7015. word1 = rl_copy_text(w1_beg, w1_end)
  7016. word2 = rl_copy_text(w2_beg, w2_end)
  7017. # We are about to do many insertions and deletions. Remember them
  7018. # as one operation.
  7019. rl_begin_undo_group()
  7020. # Do the stuff at word2 first, so that we don't have to worry
  7021. # about word1 moving.
  7022. @rl_point = w2_beg
  7023. rl_delete_text(w2_beg, w2_end)
  7024. rl_insert_text(word1)
  7025. @rl_point = w1_beg
  7026. rl_delete_text(w1_beg, w1_end)
  7027. rl_insert_text(word2)
  7028. # This is exactly correct since the text before this point has not
  7029. # changed in length.
  7030. @rl_point = w2_end
  7031. # I think that does it.
  7032. rl_end_undo_group()
  7033. word1 = nil
  7034. word2 = nil
  7035. 0
  7036. end
  7037. # Re-read the current keybindings file.
  7038. def rl_re_read_init_file(count, ignore)
  7039. r = rl_read_init_file(nil)
  7040. rl_set_keymap_from_edit_mode()
  7041. r
  7042. end
  7043. # Exchange the position of mark and point.
  7044. def rl_exchange_point_and_mark(count, key)
  7045. if (@rl_mark > @rl_end)
  7046. @rl_mark = -1
  7047. end
  7048. if (@rl_mark == -1)
  7049. rl_ding()
  7050. return -1
  7051. else
  7052. @rl_point, @rl_mark = @rl_mark, @rl_point
  7053. end
  7054. 0
  7055. end
  7056. # A convenience function for displaying a list of strings in
  7057. # columnar format on readline's output stream. MATCHES is the list
  7058. # of strings, in argv format, LEN is the number of strings in MATCHES,
  7059. # and MAX is the length of the longest string in MATCHES.
  7060. def rl_display_match_list(matches, len, max)
  7061. # How many items of MAX length can we fit in the screen window?
  7062. max += 2
  7063. limit = @_rl_screenwidth / max
  7064. if (limit != 1 && (limit * max == @_rl_screenwidth))
  7065. limit-=1
  7066. end
  7067. # Avoid a possible floating exception. If max > _rl_screenwidth,
  7068. # limit will be 0 and a divide-by-zero fault will result.
  7069. if (limit == 0)
  7070. limit = 1
  7071. end
  7072. # How many iterations of the printing loop?
  7073. count = (len + (limit - 1)) / limit
  7074. # Watch out for special case. If LEN is less than LIMIT, then
  7075. # just do the inner printing loop.
  7076. # 0 < len <= limit implies count = 1.
  7077. # Sort the items if they are not already sorted.
  7078. if (!@rl_ignore_completion_duplicates)
  7079. matches[1,len] = matches[1,len].sort
  7080. end
  7081. rl_crlf()
  7082. lines = 0
  7083. if (!@_rl_print_completions_horizontally)
  7084. # Print the sorted items, up-and-down alphabetically, like ls.
  7085. for i in 1 .. count
  7086. l = i
  7087. for j in 0 ... limit
  7088. if (l > len || matches[l].nil?)
  7089. break
  7090. else
  7091. temp = printable_part(matches[l])
  7092. printed_len = print_filename(temp, matches[l])
  7093. if (j + 1 < limit)
  7094. @rl_outstream.write(' '*(max - printed_len))
  7095. end
  7096. end
  7097. l += count
  7098. end
  7099. rl_crlf()
  7100. lines+=1
  7101. if (@_rl_page_completions && lines >= (@_rl_screenheight - 1) && i < count)
  7102. lines = _rl_internal_pager(lines)
  7103. return if (lines < 0)
  7104. end
  7105. end
  7106. else
  7107. # Print the sorted items, across alphabetically, like ls -x.
  7108. i = 1
  7109. while(matches[i])
  7110. temp = printable_part(matches[i])
  7111. printed_len = print_filename(temp, matches[i])
  7112. # Have we reached the end of this line?
  7113. if (matches[i+1])
  7114. if ((limit > 1) && (i % limit) == 0)
  7115. rl_crlf()
  7116. lines+=1
  7117. if (@_rl_page_completions && lines >= @_rl_screenheight - 1)
  7118. lines = _rl_internal_pager(lines)
  7119. return if (lines < 0)
  7120. end
  7121. else
  7122. @rl_outstream.write(' '*(max - printed_len))
  7123. end
  7124. end
  7125. i += 1
  7126. end
  7127. rl_crlf()
  7128. end
  7129. end
  7130. # Append any necessary closing quote and a separator character to the
  7131. # just-inserted match. If the user has specified that directories
  7132. # should be marked by a trailing `/', append one of those instead. The
  7133. # default trailing character is a space. Returns the number of characters
  7134. # appended. If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS
  7135. # has them) and don't add a suffix for a symlink to a directory. A
  7136. # nontrivial match is one that actually adds to the word being completed.
  7137. # The variable rl_completion_mark_symlink_dirs controls this behavior
  7138. # (it's initially set to the what the user has chosen, indicated by the
  7139. # value of _rl_complete_mark_symlink_dirs, but may be modified by an
  7140. # application's completion function).
  7141. def append_to_match(text, delimiter, quote_char, nontrivial_match)
  7142. temp_string = 0.chr * 4
  7143. temp_string_index = 0
  7144. if (quote_char && @rl_point>0 && !@rl_completion_suppress_quote &&
  7145. @rl_line_buffer[@rl_point - 1,1] != quote_char)
  7146. temp_string[temp_string_index] = quote_char
  7147. temp_string_index += 1
  7148. end
  7149. if (delimiter != 0.chr)
  7150. temp_string[temp_string_index] = delimiter
  7151. temp_string_index += 1
  7152. elsif (!@rl_completion_suppress_append && @rl_completion_append_character)
  7153. temp_string[temp_string_index] = @rl_completion_append_character
  7154. temp_string_index += 1
  7155. end
  7156. temp_string[temp_string_index] = 0.chr
  7157. temp_string_index += 1
  7158. if (@rl_filename_completion_desired)
  7159. filename = File.expand_path(text)
  7160. s = (nontrivial_match && !@rl_completion_mark_symlink_dirs) ?
  7161. File.lstat(filename) : File.stat(filename)
  7162. if s.directory?
  7163. if @_rl_complete_mark_directories
  7164. # This is clumsy. Avoid putting in a double slash if point
  7165. # is at the end of the line and the previous character is a
  7166. # slash.
  7167. if (@rl_point>0 && @rl_line_buffer[@rl_point] == ?\0 && @rl_line_buffer[@rl_point - 1] == ?/ )
  7168. elsif (@rl_line_buffer[@rl_point] != ?/ )
  7169. rl_insert_text("/")
  7170. end
  7171. end
  7172. # Don't add anything if the filename is a symlink and resolves to a
  7173. # directory.
  7174. elsif s.symlink? && File.stat(filename).directory?
  7175. else
  7176. if (@rl_point == @rl_end && temp_string_index>0)
  7177. rl_insert_text(temp_string)
  7178. end
  7179. end
  7180. filename = nil
  7181. else
  7182. if (@rl_point == @rl_end && temp_string_index>0)
  7183. rl_insert_text(temp_string)
  7184. end
  7185. end
  7186. temp_string_index
  7187. end
  7188. # Stifle the history list, remembering only MAX number of lines.
  7189. def stifle_history(max)
  7190. max = 0 if (max < 0)
  7191. if (@history_length > max)
  7192. @the_history.slice!(0,(@history_length - max))
  7193. @history_length = max
  7194. end
  7195. @history_stifled = true
  7196. @max_input_history = @history_max_entries = max
  7197. end
  7198. # Stop stifling the history. This returns the previous maximum
  7199. # number of history entries. The value is positive if the history
  7200. # was stifled, negative if it wasn't.
  7201. def unstifle_history()
  7202. if (@history_stifled)
  7203. @history_stifled = false
  7204. return (@history_max_entries)
  7205. else
  7206. return (-@history_max_entries)
  7207. end
  7208. end
  7209. def history_is_stifled()
  7210. return (@history_stifled)
  7211. end
  7212. def clear_history()
  7213. @the_history = nil
  7214. @history_offset = @history_length = 0
  7215. end
  7216. # Insert COUNT characters from STRING to the output stream at column COL.
  7217. def insert_some_chars(string, count, col)
  7218. if @hConsoleHandle
  7219. _rl_output_some_chars(string,0,count)
  7220. else
  7221. # DEBUGGING
  7222. if (@rl_byte_oriented)
  7223. if (count != col)
  7224. $stderr.write("readline: debug: insert_some_chars: count (#{count}) != col (#{col})\n");
  7225. end
  7226. end
  7227. # If IC is defined, then we do not have to "enter" insert mode.
  7228. #if (@_rl_term_IC)
  7229. # buffer = tgoto(@_rl_term_IC, 0, col)
  7230. # @_rl_out_stream.write(buffer)
  7231. # _rl_output_some_chars(string,0,count)
  7232. #else
  7233. # If we have to turn on insert-mode, then do so.
  7234. if (@_rl_term_im)
  7235. @_rl_out_stream.write(@_rl_term_im)
  7236. end
  7237. # If there is a special command for inserting characters, then
  7238. # use that first to open up the space.
  7239. if (@_rl_term_ic)
  7240. @_rl_out_stream.write(@_rl_term_ic * count)
  7241. end
  7242. # Print the text.
  7243. _rl_output_some_chars(string,0, count)
  7244. # If there is a string to turn off insert mode, we had best use
  7245. # it now.
  7246. if (@_rl_term_ei)
  7247. @_rl_out_stream.write(@_rl_term_ei)
  7248. end
  7249. #end
  7250. end
  7251. end
  7252. # Delete COUNT characters from the display line.
  7253. def delete_chars(count)
  7254. return if (count > @_rl_screenwidth) # XXX
  7255. if @hConsoleHandle.nil?
  7256. #if (@_rl_term_DC)
  7257. # buffer = tgoto(_rl_term_DC, count, count);
  7258. # @_rl_out_stream.write(buffer * count)
  7259. #else
  7260. if (@_rl_term_dc)
  7261. @_rl_out_stream.write(@_rl_term_dc * count)
  7262. end
  7263. #end
  7264. end
  7265. end
  7266. # adjust pointed byte and find mbstate of the point of string.
  7267. # adjusted point will be point <= adjusted_point, and returns
  7268. # differences of the byte(adjusted_point - point).
  7269. # if point is invalied (point < 0 || more than string length),
  7270. # it returns -1
  7271. def _rl_adjust_point(string, point)
  7272. length = string.length
  7273. return -1 if (point < 0)
  7274. return -1 if (length < point)
  7275. pos = 0
  7276. case @encoding
  7277. when 'E'
  7278. pos = string.scan(/./me).inject(0){|r,x| r<point ? r += x.length : r }
  7279. when 'S'
  7280. pos = string.scan(/./ms).inject(0){|r,x| r<point ? r += x.length : r }
  7281. when 'U'
  7282. pos = string.scan(/./mu).inject(0){|r,x| r<point ? r += x.length : r }
  7283. when 'X'
  7284. pos = string.dup.force_encoding(@encoding_name).chars.inject(0){|r,x| r<point ? r += x.bytesize : r }
  7285. else
  7286. pos = point
  7287. end
  7288. pos - point
  7289. end
  7290. # Find next `count' characters started byte point of the specified seed.
  7291. # If flags is MB_FIND_NONZERO, we look for non-zero-width multibyte
  7292. # characters.
  7293. def _rl_find_next_mbchar(string, seed, count, flags)
  7294. if @encoding == 'N'
  7295. return (seed + count)
  7296. end
  7297. seed = 0 if seed < 0
  7298. return seed if count <= 0
  7299. point = seed + _rl_adjust_point(string,seed)
  7300. if (seed < point)
  7301. count -= 1
  7302. end
  7303. case @encoding
  7304. when 'E'
  7305. point += string[point..-1].scan(/./me)[0,count].to_s.length
  7306. when 'S'
  7307. point += string[point..-1].scan(/./ms)[0,count].to_s.length
  7308. when 'U'
  7309. point += string[point..-1].scan(/./mu)[0,count].to_s.length
  7310. when 'X'
  7311. point += string[point..-1].force_encoding(@encoding_name)[0,count].bytesize
  7312. else
  7313. point += count
  7314. end
  7315. if flags == MB_FIND_NONZERO
  7316. point = string.length if point>=string.length
  7317. end
  7318. point
  7319. end
  7320. # Find previous character started byte point of the specified seed.
  7321. # Returned point will be point <= seed. If flags is MB_FIND_NONZERO,
  7322. # we look for non-zero-width multibyte characters.
  7323. def _rl_find_prev_mbchar(string, seed, flags)
  7324. if @encoding == 'N'
  7325. return ((seed == 0) ? seed : seed - 1)
  7326. end
  7327. length = string.length
  7328. if seed < 0
  7329. return 0
  7330. elsif length < seed
  7331. return length
  7332. end
  7333. case @encoding
  7334. when 'E'
  7335. string[0,seed].scan(/./me)[0..-2].to_s.length
  7336. when 'S'
  7337. string[0,seed].scan(/./ms)[0..-2].to_s.length
  7338. when 'U'
  7339. string[0,seed].scan(/./mu)[0..-2].to_s.length
  7340. when 'X'
  7341. string[0,seed].force_encoding(@encoding_name)[0..-2].bytesize
  7342. end
  7343. end
  7344. # compare the specified two characters. If the characters matched,
  7345. # return true. Otherwise return false.
  7346. def _rl_compare_chars(buf1, pos1, buf2, pos2)
  7347. return false if buf1[pos1].nil? || buf2[pos2].nil?
  7348. case @encoding
  7349. when 'E'
  7350. buf1[pos1..-1].scan(/./me)[0] == buf2[pos2..-1].scan(/./me)[0]
  7351. when 'S'
  7352. buf1[pos1..-1].scan(/./ms)[0] == buf2[pos2..-1].scan(/./ms)[0]
  7353. when 'U'
  7354. buf1[pos1..-1].scan(/./mu)[0] == buf2[pos2..-1].scan(/./mu)[0]
  7355. when 'X'
  7356. buf1[pos1..-1].force_encoding(@encoding_name)[0] == buf2[pos2..-1].force_encoding(@encoding_name)[0]
  7357. else
  7358. buf1[pos1] == buf2[pos2]
  7359. end
  7360. end
  7361. # return the number of bytes parsed from the multibyte sequence starting
  7362. # at src, if a non-L'\0' wide character was recognized. It returns 0,
  7363. # if a L'\0' wide character was recognized. It returns (size_t)(-1),
  7364. # if an invalid multibyte sequence was encountered. It returns (size_t)(-2)
  7365. # if it couldn't parse a complete multibyte character.
  7366. def _rl_get_char_len(src)
  7367. return 0 if src[0] == ?\0 || src.length==0
  7368. case @encoding
  7369. when 'E'
  7370. len = src.scan(/./me)[0].to_s.length
  7371. when 'S'
  7372. len = src.scan(/./ms)[0].to_s.length
  7373. when 'U'
  7374. len = src.scan(/./mu)[0].to_s.length
  7375. when 'X'
  7376. src = src.dup.force_encoding(@encoding_name)
  7377. len = src.valid_encoding? ? src[0].bytesize : 0
  7378. else
  7379. len = 1
  7380. end
  7381. len==0 ? -2 : len
  7382. end
  7383. # read multibyte char
  7384. def _rl_read_mbchar(mbchar, size)
  7385. mb_len = 0
  7386. while (mb_len < size)
  7387. rl_setstate(RL_STATE_MOREINPUT)
  7388. mbchar << rl_read_key()
  7389. mb_len += 1
  7390. rl_unsetstate(RL_STATE_MOREINPUT)
  7391. case @encoding
  7392. when 'E'
  7393. break unless mbchar.scan(/./me).empty?
  7394. when 'S'
  7395. break unless mbchar.scan(/./ms).empty?
  7396. when 'U'
  7397. break unless mbchar.scan(/./mu).empty?
  7398. when 'X'
  7399. break if mbchar.dup.force_encoding(@encoding_name).valid_encoding?
  7400. end
  7401. end
  7402. mb_len
  7403. end
  7404. # Read a multibyte-character string whose first character is FIRST into
  7405. # the buffer MB of length MLEN. Returns the last character read, which
  7406. # may be FIRST. Used by the search functions, among others. Very similar
  7407. # to _rl_read_mbchar.
  7408. def _rl_read_mbstring(first, mb, mlen)
  7409. c = first
  7410. for i in 0 ... mlen
  7411. mb << c
  7412. if _rl_get_char_len(mb) == -2
  7413. # Read more for multibyte character
  7414. rl_setstate(RL_STATE_MOREINPUT)
  7415. c = rl_read_key()
  7416. rl_unsetstate(RL_STATE_MOREINPUT)
  7417. else
  7418. break
  7419. end
  7420. end
  7421. c
  7422. end
  7423. def _rl_is_mbchar_matched(string, seed, _end, mbchar, length)
  7424. return 0 if ((_end - seed) < length)
  7425. for i in 0 ... length
  7426. if (string[seed + i] != mbchar[i])
  7427. return 0
  7428. end
  7429. end
  7430. 1
  7431. end
  7432. # Redraw the last line of a multi-line prompt that may possibly contain
  7433. # terminal escape sequences. Called with the cursor at column 0 of the
  7434. # line to draw the prompt on.
  7435. def redraw_prompt(t)
  7436. oldp = @rl_display_prompt
  7437. rl_save_prompt()
  7438. @rl_display_prompt = t
  7439. @local_prompt,@prompt_visible_length,@prompt_last_invisible,@prompt_invis_chars_first_line,@prompt_physical_chars =
  7440. expand_prompt(t)
  7441. @local_prompt_prefix = nil
  7442. @local_prompt_len = @local_prompt ? @local_prompt.length : 0
  7443. rl_forced_update_display()
  7444. @rl_display_prompt = oldp
  7445. rl_restore_prompt()
  7446. end
  7447. # Redisplay the current line after a SIGWINCH is received.
  7448. def _rl_redisplay_after_sigwinch()
  7449. # Clear the current line and put the cursor at column 0. Make sure
  7450. # the right thing happens if we have wrapped to a new screen line.
  7451. if @_rl_term_cr
  7452. @rl_outstream.write(@_rl_term_cr)
  7453. @_rl_last_c_pos = 0
  7454. if @_rl_term_clreol
  7455. @rl_outstream.write(@_rl_term_clreol)
  7456. else
  7457. space_to_eol(@_rl_screenwidth)
  7458. @rl_outstream.write(@_rl_term_cr)
  7459. end
  7460. if @_rl_last_v_pos > 0
  7461. _rl_move_vert(0)
  7462. end
  7463. else
  7464. rl_crlf()
  7465. end
  7466. # Redraw only the last line of a multi-line prompt.
  7467. t = @rl_display_prompt.index("\n")
  7468. if t
  7469. redraw_prompt(@rl_display_prompt[(t+1)..-1])
  7470. else
  7471. rl_forced_update_display()
  7472. end
  7473. end
  7474. def rl_resize_terminal()
  7475. if @readline_echoing_p
  7476. _rl_get_screen_size(@rl_instream.fileno, 1)
  7477. if @rl_redisplay_function != :rl_redisplay
  7478. rl_forced_update_display()
  7479. else
  7480. _rl_redisplay_after_sigwinch()
  7481. end
  7482. end
  7483. end
  7484. def rl_sigwinch_handler(sig)
  7485. rl_setstate(RL_STATE_SIGHANDLER)
  7486. rl_resize_terminal()
  7487. rl_unsetstate(RL_STATE_SIGHANDLER)
  7488. end
  7489. module_function :rl_attempted_completion_function,:rl_deprep_term_function,
  7490. :rl_event_hook,:rl_attempted_completion_over,:rl_basic_quote_characters,
  7491. :rl_basic_word_break_characters,:rl_completer_quote_characters,
  7492. :rl_completer_word_break_characters,:rl_completion_append_character,
  7493. :rl_filename_quote_characters,:rl_instream,:rl_library_version,:rl_outstream,
  7494. :rl_readline_name,
  7495. :rl_attempted_completion_function=,:rl_deprep_term_function=,
  7496. :rl_event_hook=,:rl_attempted_completion_over=,:rl_basic_quote_characters=,
  7497. :rl_basic_word_break_characters=,:rl_completer_quote_characters=,
  7498. :rl_completer_word_break_characters=,:rl_completion_append_character=,
  7499. :rl_filename_quote_characters=,:rl_instream=,:rl_library_version=,:rl_outstream=,
  7500. :rl_readline_name=,:history_length,:history_base
  7501. def no_terminal?
  7502. term = ENV["TERM"]
  7503. term.nil? || (term == 'dumb') || (term == 'cygwin' && RUBY_PLATFORM =~ /mswin|mingw/)
  7504. end
  7505. private :no_terminal?
  7506. end