class Textbringer::CMode

Constants

BLOCK_BEG
BLOCK_END
CANONICAL_PUNCTUATORS
KEYWORDS
TOKEN_NAMES
TOKEN_REGEXP

Public Class Methods

new(buffer) click to toggle source
Calls superclass method
# File lib/textbringer/modes/c_mode.rb, line 41
def initialize(buffer)
  super(buffer)
  @buffer[:indent_level] = CONFIG[:c_indent_level]
  @buffer[:indent_tabs_mode] = CONFIG[:c_indent_tabs_mode]
end

Public Instance Methods

comment_start() click to toggle source
# File lib/textbringer/modes/c_mode.rb, line 37
def comment_start
  "//"
end
compile(cmd = read_from_minibuffer("Compile: ", default: default_compile_command)) click to toggle source
# File lib/textbringer/modes/c_mode.rb, line 47
def compile(cmd = read_from_minibuffer("Compile: ",
                                       default: default_compile_command))
  shell_execute(cmd, buffer_name: "*Compile result*",
                mode: BacktraceMode)
end
default_compile_command() click to toggle source
# File lib/textbringer/modes/c_mode.rb, line 57
def default_compile_command
  "make"
end
lex(s) click to toggle source
# File lib/textbringer/modes/c_mode.rb, line 180
def lex(s)
  tokens = []
  line = 1
  column = 0
  s.scan(TOKEN_REGEXP) do
    text = $&
    token_name = TOKEN_NAMES.find { |name| $~[name] }
    if text.empty?
      raise EditorError, "Empty token: (#{line},#{column}) #{$~.inspect}"
    end
    tokens.push([[line, column], token_name, text])
    lf_count = text.count("\n")
    if lf_count > 0
      line += lf_count
      column = text.slice(/[^\n]*\z/).size
    else
      column += text.size
    end
  end
  tokens
end
symbol_pattern() click to toggle source
# File lib/textbringer/modes/c_mode.rb, line 53
def symbol_pattern
  /[A-Za-z0-9\_\\]/
end

Private Instance Methods

calculate_indentation() click to toggle source
# File lib/textbringer/modes/c_mode.rb, line 204
def calculate_indentation
  if @buffer.current_line == 1
    return 0
  end
  @buffer.save_excursion do
    @buffer.beginning_of_line
    if @buffer.looking_at?(/[ \t]*(?:#|%:)/)
      return 0
    end
    bol_pos = @buffer.point
    s = @buffer.substring(@buffer.point_min, @buffer.point).b
    tokens = lex(s)
    _, event, = tokens.last
    if event == :partial_comment
      return nil
    end
    line, column, event, text = find_nearest_beginning_token(tokens)
    if event == :punctuator && text == "("
      return column + 1
    end
    if line
      @buffer.goto_line(line)
    else
      (ln, _), ev = tokens.reverse_each.drop_while { |(l, _), e, t|
        l >= @buffer.current_line - 1 || e == :space
      }.first
      if ev == :comment
        @buffer.goto_line(ln)
      else
        @buffer.backward_line
      end
    end
    @buffer.looking_at?(/[ \t]*/)
    base_indentation = @buffer.match_string(0).
      gsub(/\t/, " " * @buffer[:tab_width]).size
    @buffer.goto_char(bol_pos)
    if line.nil? ||
        @buffer.looking_at?(/[ \t]*([}\])]|:>|%>)/)
      indentation = base_indentation
    else
      indentation = base_indentation + @buffer[:indent_level]
    end
    if @buffer.looking_at?(/[ \t]*(?:case.*|default):/)
      indentation += @buffer[:c_case_label_offset]
    elsif @buffer.looking_at?(/[ \t]*[_a-zA-Z0-9\\]+:/)
      indentation += @buffer[:c_label_offset]
    end
    indent_continued_statement(indentation, tokens, line)
  end
end
find_nearest_beginning_token(tokens) click to toggle source
# File lib/textbringer/modes/c_mode.rb, line 284
def find_nearest_beginning_token(tokens)
  stack = []
  (tokens.size - 1).downto(0) do |i|
    (line, column), event, raw_text = tokens[i]
    text = CANONICAL_PUNCTUATORS[raw_text]
    case event
    when :punctuator
      if BLOCK_BEG.key?(text)
        stack.push(text)
      elsif BLOCK_END.key?(text)
        if stack.empty?
          return line, column, event, text
        end
        if stack.last != BLOCK_END[text]
          raise EditorError, "#{@buffer.name}:#{line}: Unmatched #{text}"
        end
        stack.pop
      end
    end
  end
  return nil
end
indent_continued_statement(indentation, tokens ,line) click to toggle source
# File lib/textbringer/modes/c_mode.rb, line 255
def indent_continued_statement(indentation, tokens ,line)
  if line && !@buffer.looking_at?(/[ \t]*\{/)
    _, last_event, last_text =
      tokens.reverse_each.drop_while { |(l, _), e, t|
        l == @buffer.current_line || e == :space || e == :comment
      }.first
    if last_event != :preprocessing_directive &&
        /[:;{}]/ !~ last_text
      indentation + @buffer[:c_continued_statement_offset]
    else
      indentation
    end
  else
    indentation
  end
end