# File lib/pry/indent.rb, line 130 def indentation_delta(tokens) # We need to keep track of whether we've seen a "for" on this line because # if the line ends with "do" then that "do" should be discounted (i.e. we're # only opening one level not two) To do this robustly we want to keep track # of the indent level at which we saw the for, so we can differentiate # between "for x in [1,2,3] do" and "for x in ([1,2,3].map do" properly seen_for_at = [] # When deciding whether an "if" token is the start of a multiline statement, # or just the middle of a single-line if statement, we just look at the # preceding token, which is tracked here. last_token, last_kind = [nil, nil] # delta keeps track of the total difference from the start of each line after # the given token, 0 is just the level at which the current line started for # reference. remove_before, add_after = [0, 0] # If the list of tokens contains a matching closing token the line should # not be indented (and thus we should return true). tokens.each do |token, kind| is_singleline_if = (SINGLELINE_TOKENS.include?(token)) && end_of_statement?(last_token, last_kind) is_optional_do = (token == "do" && seen_for_at.include?(add_after - 1)) last_token, last_kind = token, kind unless kind == :space next if IGNORE_TOKENS.include?(kind) seen_for_at << add_after if token == "for" if OPEN_TOKENS.keys.include?(token) && !is_optional_do && !is_singleline_if @stack << token add_after += 1 elsif token == OPEN_TOKENS[@stack.last] @stack.pop if add_after == 0 remove_before += 1 else add_after -= 1 end elsif MIDWAY_TOKENS.include?(token) if add_after == 0 remove_before += 1 add_after += 1 end end end return [remove_before, add_after] end