2024-03-25: りらいん

コードリーディングメモ

github.com

autocompleteとtab completionの状態分離

tab completion は --noautocomplete で使える

Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE

最終的にDialogRenderInfoを返す。表示のために必要な枠組みの情報

      DialogRenderInfo.new(
        pos: cursor_pos_to_render,
        contents: result,
        scrollbar: true,
        height: [15, preferred_dialog_height].min,
        face: :completion_dialog
      )

journey_data として completion_journey_data から.DialogProcScope::CompletionJourneyData をもらってくる。 これは @completion_journey_state としてダイアログ遷移中の状態のときにどこにいるか、前後の行情報、ダイアログに何を表示すべきかのリスト、ポインタをもっている。 遷移中じゃなければ @completion_journey_statenil になる。

移動を表すのにjourneyという単語を使っているの好き

    def completion_journey_data
      @line_editor.dialog_proc_scope_completion_journey_data
    end

  def dialog_proc_scope_completion_journey_data
    return nil unless @completion_journey_state
    line_index = @completion_journey_state.line_index
    pre_lines = @buffer_of_lines[0...line_index].map { |line| line + "\n" }
    post_lines = @buffer_of_lines[(line_index + 1)..-1].map { |line| line + "\n" }
    DialogProcScope::CompletionJourneyData.new(
      pre_lines.join + @completion_journey_state.pre,
      @completion_journey_state.post + post_lines.join,
      @completion_journey_state.list,
      @completion_journey_state.pointer
    )
  end

dialog_proc_scope_completion_journey_data が呼ばれるのは Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE からのみ

@completion_journey_state はこう。move_completed_list で動いたときに CompletionJourneyState が入る。それ以外はnil

      @completion_journey_state = CompletionJourneyState.new(
        @line_index, pre, target, post, [target] + candidates, pointer
      )

pre target post は入力中の line を区切り文字などを考慮して切ったもの。例えば S を入力すると targetS になる

call_completion_proc_with_checking_args の返り値は STDERR とかダイアログに表示すべき文字列が Array に詰め込まれる

["STDERR", "STDIN", "STDOUT", "ScriptError", "SecurityError", "Set", "Shellwords", "Signal", "SignalException", "SimpleDelegator", "SingleForwardable", "Singleton", "SizedQueue", "S...

move_completed_list

ダイアログ表示中に tab を押したときなど移動が発生したときに入る。移動だけのときはCompletionJourneyStateの作成はスキップし、@completion_journey_state のポインタの位置更新とset_current_line でカーソル位置の更新を行う。

if (delta = { up: -1, down: +1 }[direction])

これで direction の存在チェックしながらdelta に数字を代入するの、こう書けるんだ..!面白い。

preposing, target, postposing = retrieve_completion_block でターゲットの文字列を前後に分割する。preposingが入力中の文字の手前、targetが入力中の文字、postposingが入力中の文字の後

list = call_completion_proc で表示対象の文字列を Array に詰め込んで返す。 call_completion_proc_with_checking_args と大体同じ(何が違うんだろう)

@completion_journey_state の更新が入るとこんな感じの状態を持つ

#<struct Reline::LineEditor::CompletionJourneyState line_index=0, pre="", target="S", post="", list=["S", "STDERR", "STDIN", "STDOUT", "ScriptError", "SecurityError", "Set", "Shellw...

list の最初の要素は入力中の文字っぽい。

em_delete_or_list

delete_char_of_list のalias

elsif !@config.autocompletion になったのはautocompleteが有効なときには補完周りの処理をしないためかな

delete-char-or-list Deletes the character under the cursor if not at the beginning or end of the line (like delete-char). If at the end of the line, behaves identically to possible-completions.

readline(3) - Linux manual page