Class: Glimmer::SWT::Custom::CodeText

Inherits:
Object
  • Object
show all
Includes:
UI::CustomWidget
Defined in:
lib/glimmer/swt/custom/code_text.rb

Overview

CodeText is a customization of StyledText with support for Ruby Syntax Highlighting

Constant Summary collapse

REGEX_COLOR_HEX6 =
/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/

Instance Attribute Summary

Attributes included from UI::CustomWidget

#body_root, #options, #parent, #parent_proxy, #swt_style, #swt_widget

Class Method Summary collapse

Instance Method Summary collapse

Methods included from UI::CustomWidget

add_custom_widget_namespaces_for, #add_observer, after_body, #async_exec, #attribute_setter, before_body, body, #can_add_observer?, #can_handle_observation_request?, #content, custom_widget_namespaces, def_option_attr_accessors, #disposed?, flyweight_custom_widget_classes, for, #get_attribute, #handle_observation_request, #has_attribute?, #has_instance_method?, #has_style?, #initialize, keyword, #local_respond_to?, #method_missing, namespaces_for_class, option, options, #pack, #post_initialize_child, reset_custom_widget_namespaces, #respond_to?, #set_attribute, shortcut_keyword, #sync_exec

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Glimmer::UI::CustomWidget

Class Method Details

.languagesObject



11
12
13
14
# File 'lib/glimmer/swt/custom/code_text.rb', line 11

def languages
  require 'rouge'
  Rouge::Lexer.all.map {|lexer| lexer.tag}.sort
end

.lexersObject



16
17
18
19
# File 'lib/glimmer/swt/custom/code_text.rb', line 16

def lexers
  require 'rouge'
  Rouge::Lexer.all.sort_by(&:title)
end

Instance Method Details

#code_text_widgetObject



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/glimmer/swt/custom/code_text.rb', line 139

def code_text_widget
  @styled_text_proxy = styled_text(swt_style) {
#             layout_data :fill, :fill, true, true if lines
#             text bind(self, :code_text_widget_text) if lines
#             top_pixel bind(self, :code_text_widget_top_pixel) if lines
    font name: @font_name, height: 15
    foreground rgb(75, 75, 75)
    left_margin 5
    top_margin 5
    right_margin 5
    bottom_margin 5
    
    on_modify_text { |event|
      # clear unnecessary syntax highlighting cache on text updates, and do it async to avoid affecting performance
      new_text = event.data
      async_exec {
        unless @syntax_highlighting.nil?
          lines = new_text.to_s.split("\n")
          line_diff = @syntax_highlighting.keys - lines
          line_diff.each do |line|
            @syntax_highlighting.delete(line)
          end
        end
      }
    }
          
    on_line_get_style { |line_style_event|
      begin
        styles = []
        style_data = nil
        syntax_highlighting(line_style_event.lineText).to_a.each do |token_hash|
          start_index = token_hash[:token_index]
          size = token_hash[:token_text].size
          style_data = Rouge::Theme.find(theme).new.style_for(token_hash[:token_type])
          foreground_color = hex_color_to_swt_color(style_data[:fg], [:black])
          background_color = hex_color_to_swt_color(style_data[:bg], [:white])
          font_styles = []
          font_styles << :bold if style_data[:bold]
          font_styles << :italic if style_data[:italic]
          font_style = SWTProxy[*font_styles]
          styles << StyleRange.new(line_style_event.lineOffset + start_index, size, foreground_color, background_color, font_style)
        end
        line_style_event.styles = styles.to_java(StyleRange) unless styles.empty?
      rescue => e
        Glimmer::Config.logger.error {"Error encountered with style data: #{style_data}"}
        Glimmer::Config.logger.error {e.message}
        Glimmer::Config.logger.error {e.full_message}
      end
    }
  }
end

#hex_color_to_swt_color(color_data, default_color) ⇒ Object



191
192
193
194
195
196
197
# File 'lib/glimmer/swt/custom/code_text.rb', line 191

def hex_color_to_swt_color(color_data, default_color)
  color_data = "##{color_data.chars.drop(1).map {|c| c*2}.join}" if color_data.is_a?(String) && color_data.start_with?('#') && color_data&.size == 4
  color_data = color_data.match(REGEX_COLOR_HEX6).to_a.drop(1).map {|c| "0x#{c}".hex}.to_a if color_data.is_a?(String) && color_data.start_with?('#')
  color_data = [color_data] unless color_data.nil? || color_data.empty? || color_data.is_a?(Array)
  color_data = default_color if color_data.nil? || color_data.empty?
  color(*color_data).swt_color
end

#lexerObject



80
81
82
83
# File 'lib/glimmer/swt/custom/code_text.rb', line 80

def lexer
  # TODO Try to use Rouge::Lexer.find_fancy('guess', code) in the future to guess the language or otherwise detect it from file extension
  @lexer ||= Rouge::Lexer.find_fancy(language)
end

#syntax_highlighting(text) ⇒ Object

def lines_width

  if lines == true
    4
  elsif lines.is_a?(Hash)
    lines[:width]
  end
end


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/glimmer/swt/custom/code_text.rb', line 64

def syntax_highlighting(text)
  return [] if text.to_s.strip.empty?
  @syntax_highlighting ||= {}
  unless @syntax_highlighting.keys.include?(text)
    lex = lexer.lex(text).to_a
    text_size = 0
    @syntax_highlighting[text] = lex.map do |pair|
      {token_type: pair.first, token_text: pair.last}
    end.each do |hash|
      hash[:token_index] = text_size
      text_size += hash[:token_text].size
    end
  end
  @syntax_highlighting[text]
end