ruco 0.1.14 → 0.2.0.beta

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,7 @@ module Ruco
2
2
  # everything that does not belong to a text-area
3
3
  # but is needed for Ruco::Editor
4
4
  class EditorArea < TextArea
5
+ include Ruco::Editor::Colors if defined? Ruco::Editor::Colors # only colorize if all color libs are loaded
5
6
  include Ruco::Editor::LineNumbers
6
7
  include Ruco::Editor::History
7
8
 
@@ -19,6 +19,28 @@ module Ruco
19
19
  deserialize File.binary_read(file) if File.exist?(file)
20
20
  end
21
21
 
22
+ def cache(key, &block)
23
+ value = get(key)
24
+ if value.nil?
25
+ value = yield
26
+ set(key, value)
27
+ end
28
+ value
29
+ end
30
+
31
+ def delete(key)
32
+ FileUtils.rm(file(key))
33
+ rescue Errno::ENOENT
34
+ end
35
+
36
+ def clear
37
+ FileUtils.rm_rf(@folder)
38
+ end
39
+
40
+ def file(key)
41
+ "#{@folder}/#{Digest::MD5.hexdigest(key)}.yml"
42
+ end
43
+
22
44
  private
23
45
 
24
46
  def entries
@@ -32,12 +54,8 @@ module Ruco
32
54
  delete.each{|f| File.delete(f) }
33
55
  end
34
56
 
35
- def file(key)
36
- "#{@folder}/#{Digest::MD5.hexdigest(key)}.yml"
37
- end
38
-
39
57
  def serialize(value)
40
- Marshal.dump(value)
58
+ @options[:string] ? value : Marshal.dump(value)
41
59
  end
42
60
 
43
61
  def deserialize(value)
data/lib/ruco/screen.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  module Ruco
2
2
  class Screen
3
+ @@styles = {}
4
+
3
5
  def initialize(options)
4
6
  @options = options
5
7
  @cache = []
@@ -10,12 +12,16 @@ module Ruco
10
12
  end
11
13
 
12
14
  def open(&block)
15
+ if $ruco_colors and ENV['TERM'] == 'xterm'
16
+ ENV['TERM'] += '-256color' # activate 256 colors
17
+ end
13
18
  Curses.noecho # do not show typed chars
14
19
  Curses.nonl # turn off newline translation
15
20
  Curses.stdscr.keypad(true) # enable arrow keys
16
21
  Curses.raw # give us all other keys
17
22
  Curses.stdscr.nodelay = 1 # do not block -> we can use timeouts
18
23
  Curses.init_screen
24
+ Curses.start_color if $ruco_colors and Curses.has_colors?
19
25
  yield self
20
26
  ensure
21
27
  Curses.clear # needed to clear the menu/status bar on windows
@@ -88,14 +94,62 @@ module Ruco
88
94
  yield # render the line
89
95
  end
90
96
 
91
- STYLES = {
92
- :normal => 0,
93
- :reverse => Curses::A_REVERSE
94
- }
95
-
96
97
  def self.curses_style(style)
97
- return 0 unless style
98
- STYLES[style] or raise("Unknown style #{style.inspect}")
98
+ @@styles[style] ||= begin
99
+ if $ruco_colors
100
+ foreground = $ruco_foreground || '#ffffff'
101
+ background = $ruco_background || '#000000'
102
+
103
+ foreground, background = if style == :normal
104
+ [foreground, background]
105
+ elsif style == :reverse
106
+ ['#000000', '#ffffff']
107
+ else
108
+ # :red or [:red, :blue]
109
+ f,b = style
110
+ b ||= background
111
+ [f,b]
112
+ end
113
+
114
+ foreground = html_to_terminal_color(foreground)
115
+ background = html_to_terminal_color(background)
116
+ color_id(foreground, background)
117
+ else # no colors
118
+ if style == :reverse
119
+ Curses::A_REVERSE
120
+ else
121
+ Curses::A_NORMAL
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ # create a new color from foreground+background or reuse old
128
+ # and return color-id
129
+ def self.color_id(foreground, background)
130
+ @@color_ids ||= {}
131
+ @@color_ids[[foreground, background]] ||= begin
132
+ # make a new pair with a unique id
133
+ @@max_color_id ||= 0
134
+ id = (@@max_color_id += 1)
135
+ unless defined? RSpec # stops normal text-output, do not use in tests
136
+ Curses::init_pair(id, foreground, background)
137
+ end
138
+ Curses.color_pair(id)
139
+ end
140
+ end
141
+
142
+ COLOR_SOURCE_VALUES = 256
143
+ COLOR_TARGET_VALUES = 5
144
+ COLOR_DIVIDE = COLOR_SOURCE_VALUES / COLOR_TARGET_VALUES
145
+ TERM_COLOR_BASE = 16
146
+
147
+ def self.html_to_terminal_color(html_color)
148
+ return unless html_color
149
+ r = (html_color[1..2].to_i(16) / COLOR_DIVIDE) * 36
150
+ g = (html_color[3..4].to_i(16) / COLOR_DIVIDE) * 6
151
+ b = (html_color[5..6].to_i(16) / COLOR_DIVIDE) * 1
152
+ TERM_COLOR_BASE + r + g + b
99
153
  end
100
154
  end
101
155
  end
@@ -1,6 +1,6 @@
1
1
  module Ruco
2
2
  class StyleMap
3
- attr_accessor :lines
3
+ attr_accessor :lines, :foreground, :background
4
4
 
5
5
  def initialize(lines)
6
6
  @lines = Array.new(lines)
@@ -20,20 +20,19 @@ module Ruco
20
20
  @lines.map do |styles|
21
21
  next unless styles
22
22
 
23
- # start and one after end of every column-range changes styles
24
- points_of_change = styles.map{|s,c| [c.first, c.last+1] }.flatten.uniq
23
+ # change to style at start and recalculate one after the end
24
+ points_of_change = styles.map{|s,c| [c.first, c.last_element+1] }.flatten.uniq
25
25
 
26
26
  flat = []
27
27
 
28
- styles.each do |style, columns|
29
- points_of_change.each do |point|
28
+ points_of_change.each do |point|
29
+ flat[point] = :normal # set default
30
+ styles.each do |style, columns|
30
31
  next unless columns.include?(point)
31
32
  flat[point] = style
32
33
  end
33
34
  end
34
35
 
35
- max = styles.map{|_,columns| columns.last }.max
36
- flat[max+1] = :normal
37
36
  flat
38
37
  end
39
38
  end
@@ -0,0 +1,33 @@
1
+ module Ruco
2
+ module SyntaxParser
3
+ # uv only offers certain syntax
4
+ UV_CONVERT = {
5
+ 'scss' => 'sass',
6
+ 'html+erb' => 'html_rails',
7
+ }
8
+
9
+ def self.syntax_for_lines(lines, languages)
10
+ if syntax = syntax_node(languages)
11
+ processor = syntax.parse(lines.join("\n"), Ruco::ArrayProcessor.new)
12
+ processor.lines
13
+ else
14
+ []
15
+ end
16
+ end
17
+
18
+ def self.syntax_node(languages)
19
+ @@syntax_node ||= {}
20
+ @@syntax_node[languages] ||= begin
21
+ found = nil
22
+ fallbacks = languages.map{|l| UV_CONVERT[l] }.compact
23
+
24
+ (languages + fallbacks).detect do |language|
25
+ syntax = File.join(Uv.syntax_path, "#{language}.syntax")
26
+ found = Textpow::SyntaxNode.load(syntax) if File.exist?(syntax)
27
+ end
28
+
29
+ found
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,45 @@
1
+ require 'plist'
2
+
3
+ module Ruco
4
+ class TMTheme
5
+ attr_accessor :background, :foreground, :styles
6
+
7
+ # TODO maybe later...
8
+ #attr_accessor :name, :uuid, :comment, :line_highlight
9
+
10
+ # not supported in Curses ...
11
+ #attr_accessor :invisibles, :caret, :selection
12
+
13
+ def initialize(file)
14
+ raw = Plist.parse_xml(file)
15
+ rules = raw['settings']
16
+ @styles = {}
17
+
18
+ # set global styles
19
+ global = rules.shift['settings']
20
+ self.background = global['background']
21
+ self.foreground = global['foreground']
22
+
23
+ # set scope styles
24
+ rules.each do |rules|
25
+ style = [
26
+ rules['settings']['foreground'],
27
+ rules['settings']['background'],
28
+ ]
29
+
30
+ next if style == [nil, nil] # some weird themes have rules without colors...
31
+ next unless scope = rules['scope'] # some weird themes have rules without scopes...
32
+
33
+ scope.split(/, ?/).map(&:strip).each do |scope|
34
+ @styles[scope] = style unless nested_scope?(scope)
35
+ end
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def nested_scope?(scope)
42
+ scope.include?(' ')
43
+ end
44
+ end
45
+ end
data/lib/ruco/window.rb CHANGED
@@ -50,9 +50,15 @@ module Ruco
50
50
  end
51
51
 
52
52
  def style_map(selection)
53
- mask = StyleMap.new(lines)
54
- return mask unless selection
53
+ map = StyleMap.new(lines)
54
+ if selection
55
+ add_selection_styles(map, selection)
56
+ else
57
+ map
58
+ end
59
+ end
55
60
 
61
+ def add_selection_styles(map, selection)
56
62
  lines.times do |line|
57
63
  visible = visible_area(line)
58
64
  next unless selection.overlap?(visible)
@@ -62,10 +68,9 @@ module Ruco
62
68
  last = [selection.last, visible.last].min
63
69
  last = last[1] - left
64
70
 
65
- mask.add(:reverse, line, first...last)
71
+ map.add(:reverse, line, first...last)
66
72
  end
67
-
68
- mask
73
+ map
69
74
  end
70
75
 
71
76
  def left=(x)
@@ -77,6 +82,14 @@ module Ruco
77
82
  @top = [[line, max_top].min, 0].max
78
83
  end
79
84
 
85
+ def visible_lines
86
+ @top..(@top+@lines-1)
87
+ end
88
+
89
+ def visible_columns
90
+ @left..(@left+@columns-1)
91
+ end
92
+
80
93
  private
81
94
 
82
95
  def adjustment(current, allowed, threshold, offset)
@@ -95,13 +108,5 @@ module Ruco
95
108
  end_of_line = [line, last_visible_column]
96
109
  start_of_line..end_of_line
97
110
  end
98
-
99
- def visible_lines
100
- @top..(@top+@lines-1)
101
- end
102
-
103
- def visible_columns
104
- @left..(@left+@columns-1)
105
- end
106
111
  end
107
- end
112
+ end
@@ -0,0 +1,23 @@
1
+ $LOAD_PATH << 'lib'
2
+ require 'oniguruma' if RUBY_VERSION < '1.9.0'
3
+ require 'language_sniffer'
4
+ gem 'plist'
5
+ require 'plist'
6
+ gem 'textpow1x'
7
+ require 'textpow'
8
+ gem 'ultraviolet1x'
9
+ require 'uv'
10
+
11
+ file = ARGV[0]
12
+ text = File.read(file)
13
+ language = LanguageSniffer.detect(file).language
14
+
15
+ require 'ruco/syntax_parser'
16
+ require 'ruco/array_processor'
17
+ t = Time.now.to_f
18
+ Ruco::SyntaxParser.syntax_for_lines(text.split("\n"), [language.name.downcase, language.lexer])
19
+ Ruco::SyntaxParser.syntax_for_lines(text.split("\n"), [language.name.downcase, language.lexer])
20
+ Ruco::SyntaxParser.syntax_for_lines(text.split("\n"), [language.name.downcase, language.lexer])
21
+ Ruco::SyntaxParser.syntax_for_lines(text.split("\n"), [language.name.downcase, language.lexer])
22
+ Ruco::SyntaxParser.syntax_for_lines(text.split("\n"), [language.name.downcase, language.lexer])
23
+ puts (Time.now.to_f - t)
data/ruco.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruco}
8
- s.version = "0.1.14"
8
+ s.version = "0.2.0.beta"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Michael Grosser"]
12
- s.date = %q{2011-09-02}
12
+ s.date = %q{2011-09-23}
13
13
  s.default_executable = %q{ruco}
14
14
  s.email = %q{michael@grosser.it}
15
15
  s.executables = ["ruco"]
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
  "bin/ruco",
23
23
  "lib/ruco.rb",
24
24
  "lib/ruco/application.rb",
25
+ "lib/ruco/array_processor.rb",
25
26
  "lib/ruco/command_bar.rb",
26
27
  "lib/ruco/core_ext/array.rb",
27
28
  "lib/ruco/core_ext/file.rb",
@@ -30,6 +31,7 @@ Gem::Specification.new do |s|
30
31
  "lib/ruco/core_ext/range.rb",
31
32
  "lib/ruco/core_ext/string.rb",
32
33
  "lib/ruco/editor.rb",
34
+ "lib/ruco/editor/colors.rb",
33
35
  "lib/ruco/editor/history.rb",
34
36
  "lib/ruco/editor/line_numbers.rb",
35
37
  "lib/ruco/editor_area.rb",
@@ -42,14 +44,22 @@ Gem::Specification.new do |s|
42
44
  "lib/ruco/screen.rb",
43
45
  "lib/ruco/status_bar.rb",
44
46
  "lib/ruco/style_map.rb",
47
+ "lib/ruco/syntax_parser.rb",
45
48
  "lib/ruco/text_area.rb",
46
49
  "lib/ruco/text_field.rb",
50
+ "lib/ruco/tm_theme.rb",
47
51
  "lib/ruco/version.rb",
48
52
  "lib/ruco/window.rb",
53
+ "playground/benchmark_syntax_parser.rb",
49
54
  "ruco.gemspec",
55
+ "spec/fixtures/railscasts.tmTheme",
56
+ "spec/fixtures/slow.js",
57
+ "spec/fixtures/test.tmTheme",
50
58
  "spec/ruco/application_spec.rb",
59
+ "spec/ruco/array_processor_spec.rb",
51
60
  "spec/ruco/command_bar_spec.rb",
52
61
  "spec/ruco/core_ext/array_spec.rb",
62
+ "spec/ruco/core_ext/range_spec.rb",
53
63
  "spec/ruco/core_ext/string_spec.rb",
54
64
  "spec/ruco/editor_spec.rb",
55
65
  "spec/ruco/file_store_spec.rb",
@@ -60,7 +70,9 @@ Gem::Specification.new do |s|
60
70
  "spec/ruco/screen_spec.rb",
61
71
  "spec/ruco/status_bar_spec.rb",
62
72
  "spec/ruco/style_map_spec.rb",
73
+ "spec/ruco/syntax_parser_spec.rb",
63
74
  "spec/ruco/text_area_spec.rb",
75
+ "spec/ruco/tm_theme_spec.rb",
64
76
  "spec/ruco/window_spec.rb",
65
77
  "spec/ruco_spec.rb",
66
78
  "spec/spec_helper.rb"
@@ -74,36 +86,23 @@ Gem::Specification.new do |s|
74
86
  s.require_paths = ["lib"]
75
87
  s.rubygems_version = %q{1.6.2}
76
88
  s.summary = %q{Commandline editor written in ruby}
77
- s.test_files = [
78
- "spec/ruco/application_spec.rb",
79
- "spec/ruco/command_bar_spec.rb",
80
- "spec/ruco/core_ext/array_spec.rb",
81
- "spec/ruco/core_ext/string_spec.rb",
82
- "spec/ruco/editor_spec.rb",
83
- "spec/ruco/file_store_spec.rb",
84
- "spec/ruco/form_spec.rb",
85
- "spec/ruco/history_spec.rb",
86
- "spec/ruco/keyboard_spec.rb",
87
- "spec/ruco/option_accessor_spec.rb",
88
- "spec/ruco/screen_spec.rb",
89
- "spec/ruco/status_bar_spec.rb",
90
- "spec/ruco/style_map_spec.rb",
91
- "spec/ruco/text_area_spec.rb",
92
- "spec/ruco/window_spec.rb",
93
- "spec/ruco_spec.rb",
94
- "spec/spec_helper.rb"
95
- ]
96
89
 
97
90
  if s.respond_to? :specification_version then
98
91
  s.specification_version = 3
99
92
 
100
93
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
101
94
  s.add_runtime_dependency(%q<clipboard>, [">= 0.9.8"])
95
+ s.add_runtime_dependency(%q<ultraviolet1x>, [">= 0"])
96
+ s.add_runtime_dependency(%q<language_sniffer>, [">= 0"])
102
97
  else
103
98
  s.add_dependency(%q<clipboard>, [">= 0.9.8"])
99
+ s.add_dependency(%q<ultraviolet1x>, [">= 0"])
100
+ s.add_dependency(%q<language_sniffer>, [">= 0"])
104
101
  end
105
102
  else
106
103
  s.add_dependency(%q<clipboard>, [">= 0.9.8"])
104
+ s.add_dependency(%q<ultraviolet1x>, [">= 0"])
105
+ s.add_dependency(%q<language_sniffer>, [">= 0"])
107
106
  end
108
107
  end
109
108