radiant 0.6.6 → 0.6.7

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of radiant might be problematic. Click here for more details.

Files changed (208) hide show
  1. data/CHANGELOG +15 -0
  2. data/CONTRIBUTORS +8 -0
  3. data/app/controllers/admin/page_controller.rb +1 -11
  4. data/app/controllers/admin/welcome_controller.rb +5 -6
  5. data/app/controllers/application.rb +2 -0
  6. data/app/controllers/site_controller.rb +1 -0
  7. data/app/helpers/admin/page_helper.rb +36 -0
  8. data/app/helpers/admin/regions_helper.rb +28 -0
  9. data/app/helpers/admin/user_helper.rb +6 -0
  10. data/app/helpers/application_helper.rb +2 -1
  11. data/app/models/user.rb +7 -8
  12. data/app/views/admin/extension/index.html.haml +28 -0
  13. data/app/views/admin/layout/edit.html.haml +44 -0
  14. data/app/views/admin/layout/index.html.haml +25 -0
  15. data/app/views/admin/layout/remove.html.haml +16 -0
  16. data/app/views/admin/page/_meta_row.html.haml +6 -0
  17. data/app/views/admin/page/_node.html.haml +25 -0
  18. data/app/views/admin/page/_part.html.haml +17 -0
  19. data/app/views/admin/page/_tag_reference.html.haml +3 -0
  20. data/app/views/admin/page/children.html.haml +2 -0
  21. data/app/views/admin/page/edit.html.haml +114 -0
  22. data/app/views/admin/page/index.html.haml +28 -0
  23. data/app/views/admin/page/remove.html.haml +20 -0
  24. data/app/views/admin/snippet/edit.html.haml +36 -0
  25. data/app/views/admin/snippet/index.html.haml +20 -0
  26. data/app/views/admin/snippet/remove.html.haml +19 -0
  27. data/app/views/admin/user/edit.html.haml +80 -0
  28. data/app/views/admin/user/index.html.haml +23 -0
  29. data/app/views/admin/user/preferences.html.haml +28 -0
  30. data/app/views/admin/user/remove.html.haml +18 -0
  31. data/app/views/admin/welcome/login.html.haml +44 -0
  32. data/app/views/layouts/application.html.haml +54 -0
  33. data/app/views/site/not_found.html.haml +3 -0
  34. data/db/migrate/019_add_salt_to_users.rb +11 -0
  35. data/db/schema.rb +2 -1
  36. data/lib/login_system.rb +1 -0
  37. data/lib/radiant.rb +1 -1
  38. data/lib/radiant/admin_ui.rb +65 -0
  39. data/lib/radiant/admin_ui/region_partials.rb +18 -0
  40. data/lib/radiant/admin_ui/region_set.rb +35 -0
  41. data/lib/tasks/extensions.rake +33 -0
  42. data/public/javascripts/admin/admin.js +8 -2
  43. data/public/javascripts/admin/sitemap.js +2 -1
  44. data/public/stylesheets/admin/main.css +4 -0
  45. data/spec/controllers/admin/abstract_model_controller_spec.rb +2 -0
  46. data/spec/controllers/admin/page_controller_spec.rb +3 -28
  47. data/spec/controllers/admin/user_controller_spec.rb +1 -1
  48. data/spec/controllers/admin/welcome_controller_spec.rb +26 -0
  49. data/spec/helpers/admin/page_helper_spec.rb +4 -0
  50. data/spec/helpers/admin/regions_helper_spec.rb +47 -0
  51. data/spec/helpers/admin/user_helper_spec.rb +7 -0
  52. data/spec/helpers/application_helper_spec.rb +7 -3
  53. data/spec/lib/login_system_spec.rb +5 -0
  54. data/spec/lib/radiant/admin_ui/region_partials_spec.rb +35 -0
  55. data/spec/lib/radiant/admin_ui/region_set_spec.rb +61 -0
  56. data/spec/lib/radiant/admin_ui_spec.rb +74 -18
  57. data/spec/models/user_spec.rb +11 -4
  58. data/spec/scenarios/users_scenario.rb +2 -2
  59. data/vendor/plugins/haml/MIT-LICENSE +20 -0
  60. data/vendor/plugins/haml/README.rdoc +319 -0
  61. data/vendor/plugins/haml/Rakefile +158 -0
  62. data/vendor/plugins/haml/TODO +9 -0
  63. data/vendor/plugins/haml/VERSION +1 -0
  64. data/vendor/plugins/haml/bin/css2sass +7 -0
  65. data/vendor/plugins/haml/bin/haml +8 -0
  66. data/vendor/plugins/haml/bin/html2haml +7 -0
  67. data/vendor/plugins/haml/bin/sass +8 -0
  68. data/vendor/plugins/haml/extra/haml-mode.el +328 -0
  69. data/vendor/plugins/haml/extra/sass-mode.el +88 -0
  70. data/vendor/plugins/haml/init.rb +2 -0
  71. data/vendor/plugins/haml/lib/haml.rb +977 -0
  72. data/vendor/plugins/haml/lib/haml/buffer.rb +229 -0
  73. data/vendor/plugins/haml/lib/haml/engine.rb +274 -0
  74. data/vendor/plugins/haml/lib/haml/error.rb +23 -0
  75. data/vendor/plugins/haml/lib/haml/exec.rb +347 -0
  76. data/vendor/plugins/haml/lib/haml/filters.rb +249 -0
  77. data/vendor/plugins/haml/lib/haml/helpers.rb +413 -0
  78. data/vendor/plugins/haml/lib/haml/helpers/action_view_extensions.rb +45 -0
  79. data/vendor/plugins/haml/lib/haml/helpers/action_view_mods.rb +122 -0
  80. data/vendor/plugins/haml/lib/haml/html.rb +188 -0
  81. data/vendor/plugins/haml/lib/haml/precompiler.rb +757 -0
  82. data/vendor/plugins/haml/lib/haml/template.rb +43 -0
  83. data/vendor/plugins/haml/lib/haml/template/patch.rb +58 -0
  84. data/vendor/plugins/haml/lib/haml/template/plugin.rb +72 -0
  85. data/vendor/plugins/haml/lib/sass.rb +833 -0
  86. data/vendor/plugins/haml/lib/sass/constant.rb +245 -0
  87. data/vendor/plugins/haml/lib/sass/constant/color.rb +101 -0
  88. data/vendor/plugins/haml/lib/sass/constant/literal.rb +53 -0
  89. data/vendor/plugins/haml/lib/sass/constant/number.rb +87 -0
  90. data/vendor/plugins/haml/lib/sass/constant/operation.rb +30 -0
  91. data/vendor/plugins/haml/lib/sass/constant/string.rb +22 -0
  92. data/vendor/plugins/haml/lib/sass/css.rb +378 -0
  93. data/vendor/plugins/haml/lib/sass/engine.rb +459 -0
  94. data/vendor/plugins/haml/lib/sass/error.rb +35 -0
  95. data/vendor/plugins/haml/lib/sass/plugin.rb +165 -0
  96. data/vendor/plugins/haml/lib/sass/plugin/merb.rb +56 -0
  97. data/vendor/plugins/haml/lib/sass/plugin/rails.rb +24 -0
  98. data/vendor/plugins/haml/lib/sass/tree/attr_node.rb +53 -0
  99. data/vendor/plugins/haml/lib/sass/tree/comment_node.rb +20 -0
  100. data/vendor/plugins/haml/lib/sass/tree/directive_node.rb +46 -0
  101. data/vendor/plugins/haml/lib/sass/tree/node.rb +42 -0
  102. data/vendor/plugins/haml/lib/sass/tree/rule_node.rb +89 -0
  103. data/vendor/plugins/haml/lib/sass/tree/value_node.rb +16 -0
  104. data/vendor/plugins/haml/test/benchmark.rb +82 -0
  105. data/vendor/plugins/haml/test/haml/engine_test.rb +587 -0
  106. data/vendor/plugins/haml/test/haml/helper_test.rb +187 -0
  107. data/vendor/plugins/haml/test/haml/html2haml_test.rb +60 -0
  108. data/vendor/plugins/haml/test/haml/markaby/standard.mab +52 -0
  109. data/vendor/plugins/haml/test/haml/mocks/article.rb +6 -0
  110. data/vendor/plugins/haml/test/haml/results/content_for_layout.xhtml +16 -0
  111. data/vendor/plugins/haml/test/haml/results/eval_suppressed.xhtml +11 -0
  112. data/vendor/plugins/haml/test/haml/results/filters.xhtml +82 -0
  113. data/vendor/plugins/haml/test/haml/results/helpers.xhtml +94 -0
  114. data/vendor/plugins/haml/test/haml/results/helpful.xhtml +10 -0
  115. data/vendor/plugins/haml/test/haml/results/just_stuff.xhtml +64 -0
  116. data/vendor/plugins/haml/test/haml/results/list.xhtml +12 -0
  117. data/vendor/plugins/haml/test/haml/results/original_engine.xhtml +22 -0
  118. data/vendor/plugins/haml/test/haml/results/partials.xhtml +21 -0
  119. data/vendor/plugins/haml/test/haml/results/silent_script.xhtml +74 -0
  120. data/vendor/plugins/haml/test/haml/results/standard.xhtml +42 -0
  121. data/vendor/plugins/haml/test/haml/results/tag_parsing.xhtml +28 -0
  122. data/vendor/plugins/haml/test/haml/results/very_basic.xhtml +7 -0
  123. data/vendor/plugins/haml/test/haml/results/whitespace_handling.xhtml +94 -0
  124. data/vendor/plugins/haml/test/haml/rhtml/_av_partial_1.rhtml +12 -0
  125. data/vendor/plugins/haml/test/haml/rhtml/_av_partial_2.rhtml +8 -0
  126. data/vendor/plugins/haml/test/haml/rhtml/action_view.rhtml +62 -0
  127. data/vendor/plugins/haml/test/haml/rhtml/standard.rhtml +54 -0
  128. data/vendor/plugins/haml/test/haml/template_test.rb +168 -0
  129. data/vendor/plugins/haml/test/haml/templates/_av_partial_1.haml +9 -0
  130. data/vendor/plugins/haml/test/haml/templates/_av_partial_2.haml +5 -0
  131. data/vendor/plugins/haml/test/haml/templates/_partial.haml +8 -0
  132. data/vendor/plugins/haml/test/haml/templates/_text_area.haml +3 -0
  133. data/vendor/plugins/haml/test/haml/templates/action_view.haml +47 -0
  134. data/vendor/plugins/haml/test/haml/templates/breakage.haml +8 -0
  135. data/vendor/plugins/haml/test/haml/templates/content_for_layout.haml +10 -0
  136. data/vendor/plugins/haml/test/haml/templates/eval_suppressed.haml +11 -0
  137. data/vendor/plugins/haml/test/haml/templates/filters.haml +81 -0
  138. data/vendor/plugins/haml/test/haml/templates/helpers.haml +69 -0
  139. data/vendor/plugins/haml/test/haml/templates/helpful.haml +11 -0
  140. data/vendor/plugins/haml/test/haml/templates/just_stuff.haml +77 -0
  141. data/vendor/plugins/haml/test/haml/templates/list.haml +12 -0
  142. data/vendor/plugins/haml/test/haml/templates/original_engine.haml +17 -0
  143. data/vendor/plugins/haml/test/haml/templates/partialize.haml +1 -0
  144. data/vendor/plugins/haml/test/haml/templates/partials.haml +12 -0
  145. data/vendor/plugins/haml/test/haml/templates/silent_script.haml +40 -0
  146. data/vendor/plugins/haml/test/haml/templates/standard.haml +42 -0
  147. data/vendor/plugins/haml/test/haml/templates/tag_parsing.haml +24 -0
  148. data/vendor/plugins/haml/test/haml/templates/very_basic.haml +4 -0
  149. data/vendor/plugins/haml/test/haml/templates/whitespace_handling.haml +87 -0
  150. data/vendor/plugins/haml/test/haml/test_helper.rb +15 -0
  151. data/vendor/plugins/haml/test/profile.rb +65 -0
  152. data/vendor/plugins/haml/test/sass/engine_test.rb +276 -0
  153. data/vendor/plugins/haml/test/sass/plugin_test.rb +159 -0
  154. data/vendor/plugins/haml/test/sass/results/alt.css +4 -0
  155. data/vendor/plugins/haml/test/sass/results/basic.css +9 -0
  156. data/vendor/plugins/haml/test/sass/results/compact.css +5 -0
  157. data/vendor/plugins/haml/test/sass/results/complex.css +87 -0
  158. data/vendor/plugins/haml/test/sass/results/compressed.css +1 -0
  159. data/vendor/plugins/haml/test/sass/results/constants.css +14 -0
  160. data/vendor/plugins/haml/test/sass/results/expanded.css +19 -0
  161. data/vendor/plugins/haml/test/sass/results/import.css +29 -0
  162. data/vendor/plugins/haml/test/sass/results/mixins.css +95 -0
  163. data/vendor/plugins/haml/test/sass/results/multiline.css +24 -0
  164. data/vendor/plugins/haml/test/sass/results/nested.css +22 -0
  165. data/vendor/plugins/haml/test/sass/results/parent_ref.css +13 -0
  166. data/vendor/plugins/haml/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  167. data/vendor/plugins/haml/test/sass/results/subdir/subdir.css +1 -0
  168. data/vendor/plugins/haml/test/sass/templates/_partial.sass +2 -0
  169. data/vendor/plugins/haml/test/sass/templates/alt.sass +16 -0
  170. data/vendor/plugins/haml/test/sass/templates/basic.sass +23 -0
  171. data/vendor/plugins/haml/test/sass/templates/bork.sass +2 -0
  172. data/vendor/plugins/haml/test/sass/templates/bork2.sass +2 -0
  173. data/vendor/plugins/haml/test/sass/templates/compact.sass +17 -0
  174. data/vendor/plugins/haml/test/sass/templates/complex.sass +310 -0
  175. data/vendor/plugins/haml/test/sass/templates/compressed.sass +15 -0
  176. data/vendor/plugins/haml/test/sass/templates/constants.sass +97 -0
  177. data/vendor/plugins/haml/test/sass/templates/expanded.sass +17 -0
  178. data/vendor/plugins/haml/test/sass/templates/import.sass +11 -0
  179. data/vendor/plugins/haml/test/sass/templates/importee.sass +14 -0
  180. data/vendor/plugins/haml/test/sass/templates/mixins.sass +76 -0
  181. data/vendor/plugins/haml/test/sass/templates/multiline.sass +20 -0
  182. data/vendor/plugins/haml/test/sass/templates/nested.sass +25 -0
  183. data/vendor/plugins/haml/test/sass/templates/parent_ref.sass +25 -0
  184. data/vendor/plugins/haml/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  185. data/vendor/plugins/haml/test/sass/templates/subdir/subdir.sass +6 -0
  186. metadata +185 -24
  187. data/app/views/admin/extension/index.html.erb +0 -40
  188. data/app/views/admin/layout/edit.html.erb +0 -39
  189. data/app/views/admin/layout/index.html.erb +0 -38
  190. data/app/views/admin/layout/remove.html.erb +0 -17
  191. data/app/views/admin/page/_meta_row.html.erb +0 -4
  192. data/app/views/admin/page/_node.html.erb +0 -28
  193. data/app/views/admin/page/_part.html.erb +0 -13
  194. data/app/views/admin/page/_tag_reference.html.erb +0 -4
  195. data/app/views/admin/page/children.html.erb +0 -4
  196. data/app/views/admin/page/edit.html.erb +0 -140
  197. data/app/views/admin/page/index.html.erb +0 -31
  198. data/app/views/admin/page/remove.html.erb +0 -14
  199. data/app/views/admin/snippet/edit.html.erb +0 -29
  200. data/app/views/admin/snippet/index.html.erb +0 -36
  201. data/app/views/admin/snippet/remove.html.erb +0 -16
  202. data/app/views/admin/user/edit.html.erb +0 -54
  203. data/app/views/admin/user/index.html.erb +0 -43
  204. data/app/views/admin/user/preferences.html.erb +0 -29
  205. data/app/views/admin/user/remove.html.erb +0 -16
  206. data/app/views/admin/welcome/login.html.erb +0 -51
  207. data/app/views/layouts/application.html.erb +0 -83
  208. data/app/views/site/not_found.html.erb +0 -3
@@ -0,0 +1,158 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ volatile_requires = ['rcov/rcovtask']
5
+ not_loaded = []
6
+ volatile_requires.each do |file|
7
+ begin
8
+ require file
9
+ rescue LoadError
10
+ not_loaded.push file
11
+ end
12
+ end
13
+
14
+ # ----- Benchmarking -----
15
+
16
+ temp_desc = <<END
17
+ Benchmark haml against ERb.
18
+ TIMES=n sets the number of runs. Defaults to 100.
19
+ END
20
+
21
+ desc temp_desc.chomp
22
+ task :benchmark do
23
+ sh "ruby test/benchmark.rb #{ENV['TIMES']}"
24
+ end
25
+
26
+ # ----- Default: Testing ------
27
+
28
+ desc 'Default: run unit tests.'
29
+ task :default => :test
30
+
31
+ require 'rake/testtask'
32
+
33
+ Rake::TestTask.new do |t|
34
+ t.libs << 'lib'
35
+ t.pattern = 'test/**/*_test.rb'
36
+ t.verbose = true
37
+ end
38
+ Rake::Task[:test].send(:add_comment, <<END)
39
+ To run with an alternate version of Rails, make test/rails a symlink to that version.
40
+ END
41
+
42
+ # ----- Packaging -----
43
+
44
+ require 'rake/gempackagetask'
45
+ require 'lib/haml'
46
+ load 'haml.gemspec'
47
+
48
+ Rake::GemPackageTask.new(HAML_GEMSPEC) do |pkg|
49
+ if Rake.application.top_level_tasks.include?('release')
50
+ pkg.need_tar_gz = true
51
+ pkg.need_tar_bz2 = true
52
+ pkg.need_zip = true
53
+ end
54
+ end
55
+
56
+ desc "This is an internal task."
57
+ task :revision_file do
58
+ if Haml.version[:rev] && !Rake.application.top_level_tasks.include?('release')
59
+ File.open('REVISION', 'w') { |f| f.puts Haml.version[:rev] }
60
+ elsif Rake.application.top_level_tasks.include?('release')
61
+ File.open('REVISION', 'w') { |f| f.puts "(release)" }
62
+ else
63
+ File.open('REVISION', 'w') { |f| f.puts "(unknown)" }
64
+ end
65
+ end
66
+ Rake::Task[:package].prerequisites.insert(0, :revision_file)
67
+
68
+ # We also need to get rid of this file after packaging.
69
+ Rake::Task[:package].enhance { File.delete('REVISION') if File.exists?('REVISION') }
70
+
71
+ task :install => [:package] do
72
+ sudo = RUBY_PLATFORM =~ /win32/ ? '' : 'sudo'
73
+ sh %{#{sudo} gem install --no-ri pkg/haml-#{File.read('VERSION').strip}}
74
+ end
75
+
76
+ task :release => [:package] do
77
+ name, version = ENV['NAME'], ENV['VERSION']
78
+ raise "Must supply NAME and VERSION for release task." unless name && version
79
+ sh %{rubyforge login}
80
+ sh %{rubyforge add_release haml haml "#{name} (v#{version})" pkg/haml-#{version}.gem}
81
+ sh %{rubyforge add_file haml haml "#{name} (v#{version})" pkg/haml-#{version}.tar.gz}
82
+ sh %{rubyforge add_file haml haml "#{name} (v#{version})" pkg/haml-#{version}.tar.bz2}
83
+ sh %{rubyforge add_file haml haml "#{name} (v#{version})" pkg/haml-#{version}.zip}
84
+ end
85
+
86
+ # ----- Documentation -----
87
+
88
+ begin
89
+ require 'hanna/rdoctask'
90
+ rescue LoadError
91
+ require 'rake/rdoctask'
92
+ end
93
+
94
+ rdoc_task = Proc.new do |rdoc|
95
+ rdoc.title = 'Haml/Sass'
96
+ rdoc.options << '--line-numbers' << '--inline-source'
97
+ rdoc.rdoc_files.include('README.rdoc')
98
+ rdoc.rdoc_files.include('lib/**/*.rb')
99
+ rdoc.rdoc_files.exclude('lib/haml/buffer.rb')
100
+ rdoc.rdoc_files.exclude('lib/sass/tree/*')
101
+ end
102
+
103
+ Rake::RDocTask.new do |rdoc|
104
+ rdoc_task.call(rdoc)
105
+ rdoc.rdoc_dir = 'rdoc'
106
+ end
107
+
108
+ Rake::RDocTask.new(:rdoc_devel) do |rdoc|
109
+ rdoc_task.call(rdoc)
110
+ rdoc.rdoc_dir = 'rdoc_devel'
111
+ rdoc.options << '--all'
112
+ rdoc.rdoc_files.include('test/*.rb')
113
+
114
+ # Get rid of exclusion rules
115
+ rdoc.rdoc_files = Rake::FileList.new(*rdoc.rdoc_files.to_a)
116
+ rdoc.rdoc_files.include('lib/haml/buffer.rb')
117
+ rdoc.rdoc_files.include('lib/sass/tree/*')
118
+ end
119
+
120
+ # ----- Coverage -----
121
+
122
+ unless not_loaded.include? 'rcov/rcovtask'
123
+ Rcov::RcovTask.new do |t|
124
+ t.test_files = FileList['test/**/*_test.rb']
125
+ t.rcov_opts << '-x' << '"^\/"'
126
+ if ENV['NON_NATIVE']
127
+ t.rcov_opts << "--no-rcovrt"
128
+ end
129
+ t.verbose = true
130
+ end
131
+ end
132
+
133
+ # ----- Profiling -----
134
+
135
+ temp_desc = <<-END
136
+ Run a profile of haml.
137
+ ENGINE=str sets the engine to be profiled (Haml or Sass).
138
+ TIMES=n sets the number of runs. Defaults to 100.
139
+ FILE=n sets the file to profile. Defaults to 'standard'.
140
+ END
141
+ desc temp_desc.chomp
142
+ task :profile do
143
+ require 'test/profile'
144
+
145
+ engine = ENV['ENGINE'] && ENV['ENGINE'].downcase == 'sass' ? Sass : Haml
146
+
147
+ puts '-'*51, "Profiling #{engine}", '-'*51
148
+
149
+ args = []
150
+ args.push ENV['TIMES'].to_i if ENV['TIMES']
151
+ args.push ENV['FILE'] if ENV['FILE']
152
+
153
+ profiler = engine::Profiler.new
154
+ res = profiler.profile(*args)
155
+ puts res
156
+
157
+ puts '-'*51
158
+ end
@@ -0,0 +1,9 @@
1
+ Testing:
2
+ Test html2haml and css2sass
3
+
4
+ Features:
5
+ Sass should throw generic errors for undefined constants, not syntax errors
6
+ Sass::Plugin should log errors
7
+ There should be a way to make Haml tags not insert whitespace
8
+ "%li, %a"?
9
+ Sass::Engine load_paths option should be set by executable
@@ -0,0 +1 @@
1
+ 1.9.0
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/haml'
4
+ require 'haml/exec'
5
+
6
+ opts = Haml::Exec::CSS2Sass.new(ARGV)
7
+ opts.parse!
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # The command line Haml parser.
3
+
4
+ require File.dirname(__FILE__) + '/../lib/haml'
5
+ require 'haml/exec'
6
+
7
+ opts = Haml::Exec::Haml.new(ARGV)
8
+ opts.parse!
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/haml'
4
+ require 'haml/exec'
5
+
6
+ opts = Haml::Exec::HTML2Haml.new(ARGV)
7
+ opts.parse!
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # The command line Sass parser.
3
+
4
+ require File.dirname(__FILE__) + '/../lib/haml'
5
+ require 'haml/exec'
6
+
7
+ opts = Haml::Exec::Sass.new(ARGV)
8
+ opts.parse!
@@ -0,0 +1,328 @@
1
+ ;;; haml-mode.el -- Major mode for editing Haml files
2
+ ;;; Written by Nathan Weizenbaum
3
+
4
+ ;;; Because Haml's indentation schema is similar
5
+ ;;; to that of YAML and Python, many indentation-related
6
+ ;;; functions are similar to those in yaml-mode and python-mode.
7
+
8
+ ;;; To install, save this somewhere and add the following to your .emacs file:
9
+ ;;;
10
+ ;;; (add-to-list 'load-path "/path/to/haml-mode.el")
11
+ ;;; (require 'haml-mode nil 't)
12
+ ;;; (add-to-list 'auto-mode-alist '("\\.sass$" . sass-mode))
13
+ ;;;
14
+
15
+ ;;; Code:
16
+
17
+ (eval-when-compile (require 'cl))
18
+
19
+ ;; User definable variables
20
+
21
+ (defgroup haml nil
22
+ "Support for the Haml template language."
23
+ :group 'languages
24
+ :prefix "haml-")
25
+
26
+ (defcustom haml-mode-hook nil
27
+ "Hook run when entering Haml mode."
28
+ :type 'hook
29
+ :group 'haml)
30
+
31
+ (defcustom haml-indent-offset 2
32
+ "Amount of offset per level of indentation."
33
+ :type 'integer
34
+ :group 'haml)
35
+
36
+ (defcustom haml-backspace-backdents-nesting t
37
+ "Non-nil to have `haml-electric-backspace' re-indent all code
38
+ nested beneath the backspaced line be re-indented along with the
39
+ line itself."
40
+ :type 'boolean
41
+ :group 'haml)
42
+
43
+ (defface haml-tab-face
44
+ '((((class color)) (:background "hotpink"))
45
+ (t (:reverse-video t)))
46
+ "Face to use for highlighting tabs in Haml files."
47
+ :group 'faces
48
+ :group 'haml)
49
+
50
+ (defvar haml-indent-function 'haml-indent-p
51
+ "This function should look at the current line and return true
52
+ if the next line could be nested within this line.")
53
+
54
+ (defvar haml-block-openers
55
+ `("^ *\\([%\\.#][^ \t]*\\)\\(\\[.*\\]\\)?\\({.*}\\)?\\(\\[.*\\]\\)?[ \t]*$"
56
+ "^ *[-=].*do[ \t]*\\(|.*|[ \t]*\\)?$"
57
+ ,(concat "^ *-[ \t]*"
58
+ (regexp-opt '("else" "elsif" "rescue" "ensure" "when")))
59
+ "^ */\\(\\[.*\\]\\)?[ \t]*$"
60
+ "^ *-#"
61
+ "^ *:")
62
+ "A list of regexps that match lines of Haml that could have
63
+ text nested beneath them.")
64
+
65
+ ;; Font lock
66
+
67
+ (defconst haml-font-lock-keywords
68
+ '(("^ *\\(\t\\)" 1 'haml-tab-face)
69
+ ("^!!!.*" 0 font-lock-constant-face)
70
+ ("\\('[^']*'\\)" 1 font-lock-string-face append)
71
+ ("\\(\"[^\"]*\"\\)" 1 font-lock-string-face append)
72
+ ("&?:\\w+" 0 font-lock-constant-face append)
73
+ ("@[a-z0-9_]+" 0 font-lock-variable-name-face append)
74
+ ("| *$" 0 font-lock-string-face)
75
+ ("^[ \t]*\\(/.*\\)$" 1 font-lock-comment-face append)
76
+ ("^ *\\(#[a-z0-9_]+\/?\\)" 1 font-lock-keyword-face)
77
+ ("^ *\\(\\.[a-z0-9_]+\/?\\)" 1 font-lock-type-face)
78
+ ("^ *\\(%[a-z0-9_]+\/?\\)" 1 font-lock-function-name-face)
79
+ ("^ *\\(#[a-z0-9_]+\/?\\)" (1 font-lock-keyword-face)
80
+ ("\\.[a-z0-9_]+" nil nil (0 font-lock-type-face)))
81
+ ("^ *\\(\\.[a-z0-9_]+\/?\\)" (1 font-lock-type-face)
82
+ ("\\.[a-z0-9_]+" nil nil (0 font-lock-type-face)))
83
+ ("^ *\\(\\.[a-z0-9_]+\/?\\)" (1 font-lock-type-face)
84
+ ("\\#[a-z0-9_]+" nil nil (0 font-lock-keyword-face)))
85
+ ("^ *\\(%[a-z0-9_]+\/?\\)" (1 font-lock-function-name-face)
86
+ ("\\.[a-z0-9_]+" nil nil (0 font-lock-type-face)))
87
+ ("^ *\\(%[a-z0-9_]+\/?\\)" (1 font-lock-function-name-face)
88
+ ("\\#[a-z0-9_]+" nil nil (0 font-lock-keyword-face)))
89
+ ("^ *\\([~=-] .*\\)" 1 font-lock-preprocessor-face prepend)
90
+ ("^ *[\\.#%a-z0-9_]+\\([~=-] .*\\)" 1 font-lock-preprocessor-face prepend)
91
+ ("^ *[\\.#%a-z0-9_]+\\({[^}]+}\\)" 1 font-lock-preprocessor-face prepend)
92
+ ("^ *[\\.#%a-z0-9_]+\\(\\[[^]]+\\]\\)" 1 font-lock-preprocessor-face prepend)))
93
+
94
+ ;; Mode setup
95
+
96
+ (defvar haml-mode-syntax-table
97
+ (let ((table (make-syntax-table)))
98
+ (modify-syntax-entry ?: "." table)
99
+ (modify-syntax-entry ?_ "w" table)
100
+ table)
101
+ "Syntax table in use in haml-mode buffers.")
102
+
103
+ (defvar haml-mode-map
104
+ (let ((map (make-sparse-keymap)))
105
+ (define-key map [backspace] 'haml-electric-backspace)
106
+ (define-key map "\C-?" 'haml-electric-backspace)
107
+ (define-key map "\C-\M-f" 'haml-forward-sexp)
108
+ (define-key map "\C-\M-b" 'haml-backward-sexp)
109
+ (define-key map "\C-\M-u" 'haml-up-list)
110
+ (define-key map "\C-\M-d" 'haml-down-list)
111
+ (define-key map "\C-C\C-k" 'haml-kill-line-and-indent)
112
+ map))
113
+
114
+ (define-derived-mode haml-mode fundamental-mode "Haml"
115
+ "Major mode for editing Haml files.
116
+
117
+ \\{haml-mode-map}"
118
+ (set-syntax-table haml-mode-syntax-table)
119
+ (set (make-local-variable 'indent-line-function) 'haml-indent-line)
120
+ (set (make-local-variable 'indent-region-function) 'haml-indent-region)
121
+ (set (make-local-variable 'forward-sexp-function) 'haml-forward-sexp)
122
+ (setq font-lock-defaults '((haml-font-lock-keywords) nil t)))
123
+
124
+ ;; Navigation
125
+
126
+ (defun haml-forward-through-whitespace (&optional backward)
127
+ "Move the point forward at least one line, until it reaches
128
+ either the end of the buffer or a line with no whitespace.
129
+
130
+ If `backward' is non-nil, move the point backward instead."
131
+ (let ((arg (if backward -1 1))
132
+ (endp (if backward 'bobp 'eobp)))
133
+ (loop do (forward-line arg)
134
+ while (and (not (funcall endp))
135
+ (looking-at "^[ \t]*$")))))
136
+
137
+ (defun haml-at-indent-p ()
138
+ "Returns whether or not the point is at the first
139
+ non-whitespace character in a line or whitespace preceding that
140
+ character."
141
+ (let ((opoint (point)))
142
+ (save-excursion
143
+ (back-to-indentation)
144
+ (>= (point) opoint))))
145
+
146
+ (defun haml-forward-sexp (&optional arg)
147
+ "Move forward across one nested expression.
148
+ With `arg', do it that many times. Negative arg -N means move
149
+ backward across N balanced expressions.
150
+
151
+ A sexp in Haml is defined as a line of Haml code as well as any
152
+ lines nested beneath it."
153
+ (interactive "p")
154
+ (or arg (setq arg 1))
155
+ (if (and (< arg 0) (not (haml-at-indent-p)))
156
+ (back-to-indentation)
157
+ (while (/= arg 0)
158
+ (let ((indent (current-indentation)))
159
+ (loop do (haml-forward-through-whitespace (< arg 0))
160
+ while (and (not (eobp))
161
+ (not (bobp))
162
+ (> (current-indentation) indent)))
163
+ (back-to-indentation)
164
+ (setq arg (+ arg (if (> arg 0) -1 1)))))))
165
+
166
+ (defun haml-backward-sexp (&optional arg)
167
+ "Move backward across one nested expression.
168
+ With ARG, do it that many times. Negative arg -N means move
169
+ forward across N balanced expressions.
170
+
171
+ A sexp in Haml is defined as a line of Haml code as well as any
172
+ lines nested beneath it."
173
+ (interactive "p")
174
+ (haml-forward-sexp (if arg (- arg) -1)))
175
+
176
+ (defun haml-up-list (&optional arg)
177
+ "Move out of one level of nesting.
178
+ With ARG, do this that many times."
179
+ (interactive "p")
180
+ (or arg (setq arg 1))
181
+ (while (> arg 0)
182
+ (let ((indent (current-indentation)))
183
+ (loop do (haml-forward-through-whitespace t)
184
+ while (and (not (bobp))
185
+ (>= (current-indentation) indent)))
186
+ (setq arg (- arg 1))))
187
+ (back-to-indentation))
188
+
189
+ (defun haml-down-list (&optional arg)
190
+ "Move down one level of nesting.
191
+ With ARG, do this that many times."
192
+ (interactive "p")
193
+ (or arg (setq arg 1))
194
+ (while (> arg 0)
195
+ (let ((indent (current-indentation)))
196
+ (haml-forward-through-whitespace)
197
+ (when (<= (current-indentation) indent)
198
+ (haml-forward-through-whitespace t)
199
+ (back-to-indentation)
200
+ (error "Nothing is nested beneath this line"))
201
+ (setq arg (- arg 1))))
202
+ (back-to-indentation))
203
+
204
+ (defun haml-mark-sexp-but-not-next-line ()
205
+ "Marks the next Haml sexp, but puts the mark at the end of the
206
+ last line of the sexp rather than the first non-whitespace
207
+ character of the next line."
208
+ (mark-sexp)
209
+ (set-mark
210
+ (save-excursion
211
+ (goto-char (mark))
212
+ (forward-line -1)
213
+ (end-of-line)
214
+ (point))))
215
+
216
+ ;; Indentation and electric keys
217
+
218
+ (defun haml-indent-p ()
219
+ "Returns true if the current line can have lines nested beneath it."
220
+ (loop for opener in haml-block-openers
221
+ if (looking-at opener) return t
222
+ return nil))
223
+
224
+ (defun haml-compute-indentation ()
225
+ "Calculate the maximum sensible indentation for the current line."
226
+ (save-excursion
227
+ (beginning-of-line)
228
+ (if (bobp) 0
229
+ (haml-forward-through-whitespace t)
230
+ (+ (current-indentation)
231
+ (if (funcall haml-indent-function) haml-indent-offset
232
+ 0)))))
233
+
234
+ (defun haml-indent-region (start end)
235
+ "Indent each nonblank line in the region.
236
+ This is done by indenting the first line based on
237
+ `haml-compute-indentation' and preserving the relative
238
+ indentation of the rest of the region.
239
+
240
+ If this command is used multiple times in a row, it will cycle
241
+ between possible indentations."
242
+ (save-excursion
243
+ (goto-char end)
244
+ (setq end (point-marker))
245
+ (goto-char start)
246
+ (let (this-line-column current-column
247
+ (next-line-column
248
+ (if (and (equal last-command this-command) (/= (current-indentation) 0))
249
+ (* (/ (- (current-indentation) 1) haml-indent-offset) haml-indent-offset)
250
+ (haml-compute-indentation))))
251
+ (while (< (point) end)
252
+ (setq this-line-column next-line-column
253
+ current-column (current-indentation))
254
+ ;; Delete whitespace chars at beginning of line
255
+ (delete-horizontal-space)
256
+ (unless (eolp)
257
+ (setq next-line-column (save-excursion
258
+ (loop do (forward-line 1)
259
+ while (and (not (eobp)) (looking-at "^[ \t]*$")))
260
+ (+ this-line-column
261
+ (- (current-indentation) current-column))))
262
+ ;; Don't indent an empty line
263
+ (unless (eolp) (indent-to this-line-column)))
264
+ (forward-line 1)))
265
+ (move-marker end nil)))
266
+
267
+ (defun haml-indent-line ()
268
+ "Indent the current line.
269
+ The first time this command is used, the line will be indented to the
270
+ maximum sensible indentation. Each immediately subsequent usage will
271
+ back-dent the line by `haml-indent-offset' spaces. On reaching column
272
+ 0, it will cycle back to the maximum sensible indentation."
273
+ (interactive "*")
274
+ (let ((ci (current-indentation))
275
+ (cc (current-column))
276
+ (need (haml-compute-indentation)))
277
+ (save-excursion
278
+ (beginning-of-line)
279
+ (delete-horizontal-space)
280
+ (if (and (equal last-command this-command) (/= ci 0))
281
+ (indent-to (* (/ (- ci 1) haml-indent-offset) haml-indent-offset))
282
+ (indent-to need)))
283
+ (if (< (current-column) (current-indentation))
284
+ (forward-to-indentation 0))))
285
+
286
+ (defun haml-reindent-region-by (n)
287
+ "Add N spaces to the beginning of each line in the region.
288
+ If N is negative, will remove the spaces instead. Assumes all
289
+ lines in the region have indentation >= that of the first line."
290
+ (let ((ci (current-indentation)))
291
+ (save-excursion
292
+ (replace-regexp (concat "^" (make-string ci ? ))
293
+ (make-string (max 0 (+ ci n)) ? )
294
+ nil (point) (mark)))))
295
+
296
+ (defun haml-electric-backspace (arg)
297
+ "Delete characters or back-dent the current line.
298
+ If invoked following only whitespace on a line, will back-dent
299
+ the line and all nested lines to the immediately previous
300
+ multiple of `haml-indent-offset' spaces.
301
+
302
+ Set `haml-backspace-backdents-nesting' to nil to just back-dent
303
+ the current line."
304
+ (interactive "*p")
305
+ (if (or (/= (current-indentation) (current-column))
306
+ (bolp)
307
+ (looking-at "^[ \t]+$"))
308
+ (backward-delete-char arg)
309
+ (let ((ci (current-column)))
310
+ (beginning-of-line)
311
+ (if haml-backspace-backdents-nesting
312
+ (haml-mark-sexp-but-not-next-line)
313
+ (set-mark (save-excursion (end-of-line) (point))))
314
+ (haml-reindent-region-by (* (- arg) haml-indent-offset))
315
+ (back-to-indentation)
316
+ (pop-mark))))
317
+
318
+ (defun haml-kill-line-and-indent ()
319
+ "Kill the current line, and re-indent all lines nested beneath it."
320
+ (interactive)
321
+ (beginning-of-line)
322
+ (haml-mark-sexp-but-not-next-line)
323
+ (kill-line 1)
324
+ (haml-reindent-region-by (* -1 haml-indent-offset)))
325
+
326
+ ;; Setup/Activation
327
+
328
+ (provide 'haml-mode)