Skip to content

Commit

Permalink
Optimizations to syntax highlighting in code_text:
Browse files Browse the repository at this point in the history
- Optimize code_text line style listener algorithm or avoid setting code_text style via listener for performance reasons
- Optimize code_text syntax highlighting by not lexing except when content changes (e.g. during scrolling, do not lex)
  • Loading branch information
AndyObtiva committed Oct 21, 2020
1 parent 561257d commit a528d34
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 14 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,10 @@
# Change Log

### 4.17.4.1

- Optimize code_text line style listener algorithm or avoid setting code_text style via listener for performance reasons
- Optimize code_text syntax highlighting by not lexing except when content changes (e.g. during scrolling, do not lex)

### 4.17.4.0

- Glimmer sample app to launch samples (sample of samples meta-sample)
Expand Down
4 changes: 2 additions & 2 deletions TODO.md
Expand Up @@ -4,10 +4,10 @@ Here is a list of tasks to do (moved to [CHANGELOG.md](CHANGELOG.md) once done).

## Next

- Support ExpandBar

## Soon

- Optimize code_text line style listener algorithm or avoid setting code_text style via listener for performance reasons
- Optimize code_text syntax highlighting by not lexing except when content changes (e.g. during scrolling, do not lex)
- Make code_text custom widget support multiple languages
- Make code_text custom widget auto-detect current language
- Have `glimmer samples` show the code of sample models too outside the main view just like `glimmer sample:code` did in the past
Expand Down
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
4.17.4.0
4.17.4.1
29 changes: 18 additions & 11 deletions lib/glimmer/swt/custom/code_text.rb
Expand Up @@ -38,9 +38,11 @@ def text
swt_widget&.text
end

def syntax_highlighting
def syntax_highlighting
return [] if text.to_s.strip.empty?
code = text
return @syntax_highlighting if @last_code == code
@last_code = code
lexer = Rouge::Lexer.find_fancy('ruby', code)
lex = lexer.lex(code).to_a
code_size = 0
Expand All @@ -50,7 +52,15 @@ def syntax_highlighting
hash[:token_index] = code_size
code_size += hash[:token_text].size
end
# TODO consider grouping by line to optimize performance for line get style listener
code_lines = code.split("\n")
line_index = 0
@syntax_highlighting = code_lines_map = code_lines.reduce({}) do |hash, line|
line_hashes = []
line_hashes << lex_hashes.shift while lex_hashes.any? && lex_hashes.first[:token_index].between?(line_index, line_index + line.size)
hash.merge(line_index => line_hashes).tap do
line_index += line.size + 1
end
end
end

before_body {
Expand All @@ -68,15 +78,12 @@ def syntax_highlighting

on_line_get_style { |line_style_event|
styles = []
line_style_event.lineOffset
syntax_highlighting.each do |token_hash|
if token_hash[:token_index] >= line_style_event.lineOffset && token_hash[:token_index] < (line_style_event.lineOffset + line_style_event.lineText.size)
start_index = token_hash[:token_index]
size = token_hash[:token_text].size
token_color = SYNTAX_COLOR_MAP[token_hash[:token_type].name] || [:black]
token_color = color(*token_color).swt_color
styles << StyleRange.new(start_index, size, token_color, nil)
end
syntax_highlighting[line_style_event.lineOffset].to_a.each do |token_hash|
start_index = token_hash[:token_index]
size = token_hash[:token_text].size
token_color = SYNTAX_COLOR_MAP[token_hash[:token_type].name] || [:black]
token_color = color(*token_color).swt_color
styles << StyleRange.new(start_index, size, token_color, nil)
end
line_style_event.styles = styles.to_java(StyleRange) unless styles.empty?
}
Expand Down

0 comments on commit a528d34

Please sign in to comment.