<commit_before># encoding: utf-8
module Byebug

  # Mix-in module to assist in command parsing.
  module FrameFunctions
    def c_frame?(frame_no)
      @state.context.frame_binding(frame_no).nil?
    end

    def switch_to_frame(frame_no)
      if frame_no < 0
        abs_frame_no = Context.stack_size + frame_no
      else
        abs_frame_no = frame_no
      end
    end

    def navigate_to_frame(jump_no)
      return if jump_no == 0
      total_jumps, current_jumps, new_pos = jump_no.abs, 0, @state.frame_pos
      step = jump_no/total_jumps
      loop do
        new_pos += step
        return new_pos if new_pos < 0 || new_pos >= Context.stack_size

        next if c_frame?(new_pos)

        current_jumps += 1
        break if current_jumps == total_jumps
      end
      return new_pos
    end

    def adjust_frame(frame_pos, absolute)
      if absolute
        abs_frame_pos = switch_to_frame(frame_pos)
        return errmsg "Can't navigate to c-frame\n" if c_frame?(abs_frame_pos)
      else
        abs_frame_pos = navigate_to_frame(frame_pos)
      end

      return errmsg "Can't navigate beyond the oldest frame\n" if
        abs_frame_pos >= Context.stack_size
      return errmsg "Can't navigate beyond the newest frame\n" if
        abs_frame_pos < 0

      @state.frame_pos = abs_frame_pos
      @state.file = @state.context.frame_file @state.frame_pos
      @state.line = @state.context.frame_line @state.frame_pos
      @state.previous_line = nil
      ListCommand.new(@state).execute
    end

    def get_frame_class(style, pos)
      frame_class = style == :short ? '' : "#{@state.context.frame_class pos}"
      return frame_class == '' ? '' : "#{frame_class}."
    end

    def get_frame_block_and_method(pos)
      frame_deco_regexp = /((?:block(?: \(\d+ levels\))?|rescue) in )?(.+)/
      frame_deco_method = "#{@state.context.frame_method pos}"
      frame_block_and_method = frame_deco_regexp.match(frame_deco_method)[1..2]
      return frame_block_and_method.map{ |x| x.nil? ? '' : x }
    end

    def get_frame_args(style, pos)
      args = @state.context.frame_args pos
      return '' if args.empty?

      locals = @state.context.frame_locals pos if style == :long
      my_args = args.map do |arg|
        case arg[0]
          when :block
            prefix, default = '&', 'block'
          when :rest
            prefix, default = '*', 'args'
          else
            prefix, default = '', nil
        end
        klass = style == :long && arg[1] ? "##{locals[arg[1]].class}" : ''
        "#{prefix}#{arg[1] || default}#{klass}"
      end

      return "(#{my_args.join(', ')})"
    end

    def get_frame_call(prefix, pos)
      frame_block, frame_method = get_frame_block_and_method(pos)
      frame_class = get_frame_class(Command.settings[:callstyle], pos)
      frame_args = get_frame_args(Command.settings[:callstyle], pos)

      call_str = frame_block + frame_class + frame_method + frame_args

      max_call_str_size = Command.settings[:width] - prefix.size
      if call_str.size > max_call_str_size
        call_str = call_str[0..max_call_str_size - 5] + "...)"
      end

      return call_str
    end

    def print_backtrace
      realsize = Context.stack_size
      calcedsize = @state.context.calced_stack_size
      if calcedsize != realsize
        if Byebug.post_mortem?
          stacksize = calcedsize
        else
          errmsg "Byebug's stacksize (#{calcedsize}) should be #{realsize}. " \
                 "This might be a bug in byebug or ruby's debugging API's\n"
          stacksize = realsize
        end
      else
        stacksize = calcedsize
      end
      (0...stacksize).each do |idx|
        print_frame(idx)
      end
    end

    def print_frame(pos, mark_current = true)
      file = @state.context.frame_file pos
      line = @state.context.frame_line pos

      unless Command.settings[:fullpath]
        path_components = file.split(/[\\\/]/)
        if path_components.size > 3
          path_components[0...-3] = '...'
          file = path_components.join(File::ALT_SEPARATOR || File::SEPARATOR)
        end
      end

      if mark_current
        frame_str = (pos == @state.frame_pos) ? '--> ' : '    '
      else
        frame_str = ""
      end
      frame_str += c_frame?(pos) ? ' ͱ-- ' : ''

      frame_str += sprintf "#%-2d ", pos
      frame_str += get_frame_call frame_str, pos
      file_line = "at #{CommandProcessor.canonic_file(file)}:#{line}"
      if frame_str.size + file_line.size + 1 > Command.settings[:width]
        frame_str += "\n      #{file_line}\n"
      else
        frame_str += " #{file_line}\n"
      end

      print frame_str
    end
  end

  # Implements byebug "where" or "backtrace" command.
  class WhereCommand < Command
    def regexp
      /^\s* (?:w(?:here)?|bt|backtrace) \s*$/x
    end

    def execute
      print_backtrace
    end

    class << self
      def names
        %w(where backtrace)
      end

      def description
        %{w[here]|bt|backtrace\tdisplay stack frames

          Print the entire stack frame. Each frame is numbered, the most recent
          frame is 0. Frame number can be referred to in the "frame" command;
          "up" and "down" add or subtract respectively to frame numbers shown.
          The position of the current frame is marked with -->. C-frames hang
          from their most inmediate ruby frame to indicate that they are not
          navigable}
      end
    end
  end

  class UpCommand < Command
    def regexp
      /^\s* u(?:p)? (?:\s+(\S+))? \s*$/x
    end

    def execute
      pos = get_int(@match[1], "Up")
      return unless pos<commit_msg>Fixes typo in help for where|backtrace command<commit_after># encoding: utf-8
module Byebug

  # Mix-in module to assist in command parsing.
  module FrameFunctions
    def c_frame?(frame_no)
      @state.context.frame_binding(frame_no).nil?
    end

    def switch_to_frame(frame_no)
      if frame_no < 0
        abs_frame_no = Context.stack_size + frame_no
      else
        abs_frame_no = frame_no
      end
    end

    def navigate_to_frame(jump_no)
      return if jump_no == 0
      total_jumps, current_jumps, new_pos = jump_no.abs, 0, @state.frame_pos
      step = jump_no/total_jumps
      loop do
        new_pos += step
        return new_pos if new_pos < 0 || new_pos >= Context.stack_size

        next if c_frame?(new_pos)

        current_jumps += 1
        break if current_jumps == total_jumps
      end
      return new_pos
    end

    def adjust_frame(frame_pos, absolute)
      if absolute
        abs_frame_pos = switch_to_frame(frame_pos)
        return errmsg "Can't navigate to c-frame\n" if c_frame?(abs_frame_pos)
      else
        abs_frame_pos = navigate_to_frame(frame_pos)
      end

      return errmsg "Can't navigate beyond the oldest frame\n" if
        abs_frame_pos >= Context.stack_size
      return errmsg "Can't navigate beyond the newest frame\n" if
        abs_frame_pos < 0

      @state.frame_pos = abs_frame_pos
      @state.file = @state.context.frame_file @state.frame_pos
      @state.line = @state.context.frame_line @state.frame_pos
      @state.previous_line = nil
      ListCommand.new(@state).execute
    end

    def get_frame_class(style, pos)
      frame_class = style == :short ? '' : "#{@state.context.frame_class pos}"
      return frame_class == '' ? '' : "#{frame_class}."
    end

    def get_frame_block_and_method(pos)
      frame_deco_regexp = /((?:block(?: \(\d+ levels\))?|rescue) in )?(.+)/
      frame_deco_method = "#{@state.context.frame_method pos}"
      frame_block_and_method = frame_deco_regexp.match(frame_deco_method)[1..2]
      return frame_block_and_method.map{ |x| x.nil? ? '' : x }
    end

    def get_frame_args(style, pos)
      args = @state.context.frame_args pos
      return '' if args.empty?

      locals = @state.context.frame_locals pos if style == :long
      my_args = args.map do |arg|
        case arg[0]
          when :block
            prefix, default = '&', 'block'
          when :rest
            prefix, default = '*', 'args'
          else
            prefix, default = '', nil
        end
        klass = style == :long && arg[1] ? "##{locals[arg[1]].class}" : ''
        "#{prefix}#{arg[1] || default}#{klass}"
      end

      return "(#{my_args.join(', ')})"
    end

    def get_frame_call(prefix, pos)
      frame_block, frame_method = get_frame_block_and_method(pos)
      frame_class = get_frame_class(Command.settings[:callstyle], pos)
      frame_args = get_frame_args(Command.settings[:callstyle], pos)

      call_str = frame_block + frame_class + frame_method + frame_args

      max_call_str_size = Command.settings[:width] - prefix.size
      if call_str.size > max_call_str_size
        call_str = call_str[0..max_call_str_size - 5] + "...)"
      end

      return call_str
    end

    def print_backtrace
      realsize = Context.stack_size
      calcedsize = @state.context.calced_stack_size
      if calcedsize != realsize
        if Byebug.post_mortem?
          stacksize = calcedsize
        else
          errmsg "Byebug's stacksize (#{calcedsize}) should be #{realsize}. " \
                 "This might be a bug in byebug or ruby's debugging API's\n"
          stacksize = realsize
        end
      else
        stacksize = calcedsize
      end
      (0...stacksize).each do |idx|
        print_frame(idx)
      end
    end

    def print_frame(pos, mark_current = true)
      file = @state.context.frame_file pos
      line = @state.context.frame_line pos

      unless Command.settings[:fullpath]
        path_components = file.split(/[\\\/]/)
        if path_components.size > 3
          path_components[0...-3] = '...'
          file = path_components.join(File::ALT_SEPARATOR || File::SEPARATOR)
        end
      end

      if mark_current
        frame_str = (pos == @state.frame_pos) ? '--> ' : '    '
      else
        frame_str = ""
      end
      frame_str += c_frame?(pos) ? ' ͱ-- ' : ''

      frame_str += sprintf "#%-2d ", pos
      frame_str += get_frame_call frame_str, pos
      file_line = "at #{CommandProcessor.canonic_file(file)}:#{line}"
      if frame_str.size + file_line.size + 1 > Command.settings[:width]
        frame_str += "\n      #{file_line}\n"
      else
        frame_str += " #{file_line}\n"
      end

      print frame_str
    end
  end

  # Implements byebug "where" or "backtrace" command.
  class WhereCommand < Command
    def regexp
      /^\s* (?:w(?:here)?|bt|backtrace) \s*$/x
    end

    def execute
      print_backtrace
    end

    class << self
      def names
        %w(where backtrace)
      end

      def description
        %{w[here]|bt|backtrace\tdisplay stack frames

          Print the entire stack frame. Each frame is numbered; the most recent
          frame is 0. A frame number can be referred to in the "frame" command;
          "up" and "down" add or subtract respectively to frame numbers shown.
          The position of the current frame is marked with -->. C-frames hang
          from their most immediate Ruby frame to indicate that they are not
          navigable}
      end
    end
  end

  class UpCommand < Command
    def regexp
      /^\s* u(?:p)? (?:\s+(\S+))? \s*$/x
    end

    def execute
      pos = get_int(@match[1], "Up")
      return unless pos
{'fraction_non_alphanumeric': 0.1080102446348141, 'fraction_numerical': 0.004062527598692926, 'mean_word_length': 2.263400576368876, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4199990', 'n_tokens_mistral': 3689, 'n_tokens_neox': 3603, 'n_words': 900}