angry_mob_common_targets 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +21 -0
- data/README.md +38 -0
- data/lib/common_mob.rb +9 -0
- data/lib/common_mob/digest.rb +43 -0
- data/lib/common_mob/erb.rb +72 -0
- data/lib/common_mob/file.rb +55 -0
- data/lib/common_mob/patch.rb +51 -0
- data/lib/common_mob/resource_locator.rb +9 -0
- data/lib/common_mob/shell.rb +323 -0
- data/lib/common_mob/template.rb +23 -0
- data/lib/common_mob/version.rb +3 -0
- data/targets/crontab_patch.rb +37 -0
- data/targets/extract.rb +40 -0
- data/targets/fetch.rb +40 -0
- data/targets/files.rb +244 -0
- data/targets/git.rb +84 -0
- data/targets/group.rb +33 -0
- data/targets/packages.rb +94 -0
- data/targets/ruby.rb +13 -0
- data/targets/services.rb +184 -0
- data/targets/shell.rb +43 -0
- data/targets/user.rb +108 -0
- data/vendor/mustache/CONTRIBUTORS +9 -0
- data/vendor/mustache/HISTORY.md +135 -0
- data/vendor/mustache/LICENSE +20 -0
- data/vendor/mustache/README.md +405 -0
- data/vendor/mustache/Rakefile +103 -0
- data/vendor/mustache/benchmarks/complex.erb +15 -0
- data/vendor/mustache/benchmarks/complex.haml +12 -0
- data/vendor/mustache/benchmarks/helper.rb +20 -0
- data/vendor/mustache/benchmarks/simple.erb +5 -0
- data/vendor/mustache/benchmarks/speed.rb +78 -0
- data/vendor/mustache/bin/mustache +90 -0
- data/vendor/mustache/contrib/mustache-mode.el +278 -0
- data/vendor/mustache/contrib/mustache.vim +69 -0
- data/vendor/mustache/examples/hash.rb +16 -0
- data/vendor/mustache/examples/hash.yml +5 -0
- data/vendor/mustache/examples/projects.mustache +26 -0
- data/vendor/mustache/examples/projects.yml +28 -0
- data/vendor/mustache/examples/self.mustache +4 -0
- data/vendor/mustache/examples/self.yml +3 -0
- data/vendor/mustache/examples/simple.mustache +10 -0
- data/vendor/mustache/examples/simple.rb +24 -0
- data/vendor/mustache/lib/mustache.rb +358 -0
- data/vendor/mustache/lib/mustache/context.rb +108 -0
- data/vendor/mustache/lib/mustache/generator.rb +160 -0
- data/vendor/mustache/lib/mustache/parser.rb +230 -0
- data/vendor/mustache/lib/mustache/sinatra.rb +180 -0
- data/vendor/mustache/lib/mustache/template.rb +59 -0
- data/vendor/mustache/lib/mustache/version.rb +3 -0
- data/vendor/mustache/lib/rack/bug/panels/mustache_panel.rb +81 -0
- data/vendor/mustache/lib/rack/bug/panels/mustache_panel/mustache_extension.rb +27 -0
- data/vendor/mustache/lib/rack/bug/panels/mustache_panel/view.mustache +46 -0
- data/vendor/mustache/man/mustache.1 +180 -0
- data/vendor/mustache/man/mustache.1.html +204 -0
- data/vendor/mustache/man/mustache.1.ron +127 -0
- data/vendor/mustache/man/mustache.5 +576 -0
- data/vendor/mustache/man/mustache.5.html +415 -0
- data/vendor/mustache/man/mustache.5.ron +324 -0
- data/vendor/mustache/mustache.gemspec +32 -0
- data/vendor/mustache/test/autoloading_test.rb +52 -0
- data/vendor/mustache/test/fixtures/comments.mustache +1 -0
- data/vendor/mustache/test/fixtures/comments.rb +14 -0
- data/vendor/mustache/test/fixtures/complex_view.mustache +17 -0
- data/vendor/mustache/test/fixtures/complex_view.rb +34 -0
- data/vendor/mustache/test/fixtures/crazy_recursive.mustache +9 -0
- data/vendor/mustache/test/fixtures/crazy_recursive.rb +31 -0
- data/vendor/mustache/test/fixtures/delimiters.mustache +8 -0
- data/vendor/mustache/test/fixtures/delimiters.rb +23 -0
- data/vendor/mustache/test/fixtures/double_section.mustache +7 -0
- data/vendor/mustache/test/fixtures/double_section.rb +14 -0
- data/vendor/mustache/test/fixtures/escaped.mustache +1 -0
- data/vendor/mustache/test/fixtures/escaped.rb +14 -0
- data/vendor/mustache/test/fixtures/inner_partial.mustache +1 -0
- data/vendor/mustache/test/fixtures/inner_partial.txt +1 -0
- data/vendor/mustache/test/fixtures/inverted_section.mustache +7 -0
- data/vendor/mustache/test/fixtures/inverted_section.rb +14 -0
- data/vendor/mustache/test/fixtures/lambda.mustache +7 -0
- data/vendor/mustache/test/fixtures/lambda.rb +31 -0
- data/vendor/mustache/test/fixtures/namespaced.mustache +1 -0
- data/vendor/mustache/test/fixtures/namespaced.rb +25 -0
- data/vendor/mustache/test/fixtures/nested_objects.mustache +17 -0
- data/vendor/mustache/test/fixtures/nested_objects.rb +35 -0
- data/vendor/mustache/test/fixtures/node.mustache +8 -0
- data/vendor/mustache/test/fixtures/partial_with_module.mustache +3 -0
- data/vendor/mustache/test/fixtures/partial_with_module.rb +37 -0
- data/vendor/mustache/test/fixtures/passenger.conf +5 -0
- data/vendor/mustache/test/fixtures/passenger.rb +27 -0
- data/vendor/mustache/test/fixtures/recursive.mustache +4 -0
- data/vendor/mustache/test/fixtures/recursive.rb +14 -0
- data/vendor/mustache/test/fixtures/simple.mustache +5 -0
- data/vendor/mustache/test/fixtures/simple.rb +26 -0
- data/vendor/mustache/test/fixtures/template_partial.mustache +2 -0
- data/vendor/mustache/test/fixtures/template_partial.rb +18 -0
- data/vendor/mustache/test/fixtures/template_partial.txt +4 -0
- data/vendor/mustache/test/fixtures/unescaped.mustache +1 -0
- data/vendor/mustache/test/fixtures/unescaped.rb +14 -0
- data/vendor/mustache/test/fixtures/utf8.mustache +3 -0
- data/vendor/mustache/test/fixtures/utf8_partial.mustache +1 -0
- data/vendor/mustache/test/helper.rb +7 -0
- data/vendor/mustache/test/mustache_test.rb +536 -0
- data/vendor/mustache/test/parser_test.rb +54 -0
- data/vendor/mustache/test/partial_test.rb +168 -0
- metadata +167 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
|
4
|
+
#
|
5
|
+
# Helpers
|
6
|
+
#
|
7
|
+
|
8
|
+
def command?(command)
|
9
|
+
system("type #{command} > /dev/null")
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
#
|
14
|
+
# Tests
|
15
|
+
#
|
16
|
+
|
17
|
+
task :default => :test
|
18
|
+
|
19
|
+
if command? :turn
|
20
|
+
desc "Run tests"
|
21
|
+
task :test do
|
22
|
+
suffix = "-n #{ENV['TEST']}" if ENV['TEST']
|
23
|
+
sh "turn test/*.rb #{suffix}"
|
24
|
+
end
|
25
|
+
else
|
26
|
+
Rake::TestTask.new do |t|
|
27
|
+
t.libs << 'lib'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
if command? :kicker
|
34
|
+
desc "Launch Kicker (like autotest)"
|
35
|
+
task :kicker do
|
36
|
+
puts "Kicking... (ctrl+c to cancel)"
|
37
|
+
exec "kicker -e rake test lib examples"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
#
|
43
|
+
# Ron
|
44
|
+
#
|
45
|
+
|
46
|
+
if command? :ronn
|
47
|
+
desc "Show the manual"
|
48
|
+
task :man => "man:build" do
|
49
|
+
exec "man man/mustache.1"
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "Build the manual"
|
53
|
+
task "man:build" do
|
54
|
+
sh "ronn -br5 --organization=DEFUNKT --manual='Mustache Manual' man/*.ron"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
#
|
60
|
+
# Gems
|
61
|
+
#
|
62
|
+
|
63
|
+
desc "Push a new version to Gemcutter and publish docs."
|
64
|
+
task :publish do
|
65
|
+
require File.dirname(__FILE__) + '/lib/mustache/version'
|
66
|
+
|
67
|
+
system "git tag v#{Mustache::Version}"
|
68
|
+
sh "gem build mustache.gemspec"
|
69
|
+
sh "gem push mustache-#{Mustache::Version}.gem"
|
70
|
+
sh "git push origin master --tags"
|
71
|
+
sh "git clean -fd"
|
72
|
+
exec "rake pages"
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# Documentation
|
77
|
+
#
|
78
|
+
|
79
|
+
begin
|
80
|
+
require 'sdoc_helpers'
|
81
|
+
rescue LoadError
|
82
|
+
warn "sdoc support not enabled. Please gem install sdoc-helpers."
|
83
|
+
end
|
84
|
+
|
85
|
+
desc "Publish to GitHub Pages"
|
86
|
+
task :pages => [ "man:build" ] do
|
87
|
+
Dir['man/*.html'].each do |f|
|
88
|
+
cp f, File.basename(f).sub('.html', '.newhtml')
|
89
|
+
end
|
90
|
+
|
91
|
+
`git commit -am 'generated manual'`
|
92
|
+
`git checkout site`
|
93
|
+
|
94
|
+
Dir['*.newhtml'].each do |f|
|
95
|
+
mv f, f.sub('.newhtml', '.html')
|
96
|
+
end
|
97
|
+
|
98
|
+
`git add .`
|
99
|
+
`git commit -m updated`
|
100
|
+
`git push site site:master`
|
101
|
+
`git checkout master`
|
102
|
+
puts :done
|
103
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<h1><%= header %></h1>
|
2
|
+
<% if not item.empty? %>
|
3
|
+
<ul>
|
4
|
+
<% for i in item %>
|
5
|
+
<% if i[:current] %>
|
6
|
+
<li><strong><%= i[:name] %></strong></li>
|
7
|
+
<% else %>
|
8
|
+
<li><a href="<%= i[:url] %>"><%= i[:name] %></a></li>
|
9
|
+
<% end %>
|
10
|
+
<% end %>
|
11
|
+
</ul>
|
12
|
+
<% end %>
|
13
|
+
<% if item.empty? %>
|
14
|
+
<p>The list is empty.</p>
|
15
|
+
<% end %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
|
3
|
+
count = (ENV['COUNT'] || 5000).to_i
|
4
|
+
|
5
|
+
$benches = []
|
6
|
+
def bench(name, &block)
|
7
|
+
$benches.push([name, block])
|
8
|
+
end
|
9
|
+
|
10
|
+
at_exit do
|
11
|
+
Benchmark.bmbm do |x|
|
12
|
+
$benches.each do |name, block|
|
13
|
+
x.report name.to_s do
|
14
|
+
count.times do
|
15
|
+
block.call
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
4
|
+
require 'helper'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../test/fixtures'
|
7
|
+
require 'complex_view'
|
8
|
+
|
9
|
+
## erb
|
10
|
+
unless ENV['NOERB']
|
11
|
+
template = File.read(File.dirname(__FILE__) + '/complex.erb')
|
12
|
+
|
13
|
+
erb = ERB.new(template)
|
14
|
+
erb_scope = ComplexView.new
|
15
|
+
erb_scope.instance_eval("def render_erb; #{erb.src}; end")
|
16
|
+
bench 'ERB w/ caching' do
|
17
|
+
erb_scope.render_erb
|
18
|
+
end
|
19
|
+
|
20
|
+
unless ENV['CACHED']
|
21
|
+
erb_nocache_scope = ComplexView.new.send(:binding)
|
22
|
+
bench 'ERB w/o caching' do
|
23
|
+
ERB.new(template).result(erb_nocache_scope)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
## haml
|
30
|
+
unless ENV['NOHAML']
|
31
|
+
require 'haml'
|
32
|
+
template = File.read(File.dirname(__FILE__) + '/complex.haml')
|
33
|
+
|
34
|
+
haml = Haml::Engine.new(template, :ugly => true)
|
35
|
+
haml_scope = ComplexView.new
|
36
|
+
haml.def_method(haml_scope, :render_haml)
|
37
|
+
bench 'HAML w/ caching' do
|
38
|
+
haml_scope.render_haml
|
39
|
+
end
|
40
|
+
|
41
|
+
unless ENV['CACHED']
|
42
|
+
haml_nocache_scope = ComplexView.new.send(:binding)
|
43
|
+
bench 'HAML w/o caching' do
|
44
|
+
Haml::Engine.new(template).render(haml_nocache_scope)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
## mustache
|
51
|
+
tpl = ComplexView.new
|
52
|
+
tpl.template
|
53
|
+
|
54
|
+
tpl[:header] = 'Chris'
|
55
|
+
tpl[:empty] = false
|
56
|
+
tpl[:list] = true
|
57
|
+
|
58
|
+
items = []
|
59
|
+
items << { :name => 'red', :current => true, :url => '#Red' }
|
60
|
+
items << { :name => 'green', :current => false, :url => '#Green' }
|
61
|
+
items << { :name => 'blue', :current => false, :url => '#Blue' }
|
62
|
+
|
63
|
+
tpl[:item] = items
|
64
|
+
|
65
|
+
bench '{{ w/ caching' do
|
66
|
+
tpl.to_html
|
67
|
+
end
|
68
|
+
|
69
|
+
content = File.read(ComplexView.template_file)
|
70
|
+
|
71
|
+
unless ENV['CACHED']
|
72
|
+
bench '{{ w/o caching' do
|
73
|
+
ctpl = ComplexView.new
|
74
|
+
ctpl.template = content
|
75
|
+
ctpl[:item] = items
|
76
|
+
ctpl.to_html
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
require 'mustache'
|
7
|
+
require 'mustache/version'
|
8
|
+
|
9
|
+
class Mustache
|
10
|
+
class CLI
|
11
|
+
# Return a structure describing the options.
|
12
|
+
def self.parse_options(args)
|
13
|
+
opts = OptionParser.new do |opts|
|
14
|
+
opts.banner = "Usage: mustache [-c] [-t] FILE ..."
|
15
|
+
|
16
|
+
opts.separator " "
|
17
|
+
|
18
|
+
opts.separator "Examples:"
|
19
|
+
opts.separator " $ mustache data.yml template.mustache"
|
20
|
+
opts.separator " $ cat data.yml | mustache - template.mustache"
|
21
|
+
opts.separator " $ mustache -c template.mustache"
|
22
|
+
|
23
|
+
opts.separator " "
|
24
|
+
|
25
|
+
opts.separator " See mustache(1) or " +
|
26
|
+
"http://mustache.github.com/mustache.1.html"
|
27
|
+
opts.separator " for more details."
|
28
|
+
|
29
|
+
opts.separator " "
|
30
|
+
opts.separator "Options:"
|
31
|
+
|
32
|
+
opts.on("-c", "--compile FILE",
|
33
|
+
"Print the compiled Ruby for a given template.") do |file|
|
34
|
+
puts Mustache::Template.new(File.read(file)).compile
|
35
|
+
exit
|
36
|
+
end
|
37
|
+
|
38
|
+
opts.on("-t", "--tokens FILE",
|
39
|
+
"Print the tokenized form of a given template.") do |file|
|
40
|
+
require 'pp'
|
41
|
+
pp Mustache::Template.new(File.read(file)).tokens
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.separator "Common Options:"
|
46
|
+
|
47
|
+
opts.on("-v", "--version", "Print the version") do |v|
|
48
|
+
puts "Mustache v#{Mustache::Version}"
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
53
|
+
puts opts
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.separator ""
|
59
|
+
|
60
|
+
opts.parse!(args)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Does the dirty work of reading files from STDIN and the command
|
64
|
+
# line then processing them. The meat of this script, if you will.
|
65
|
+
def self.process_files(input_stream)
|
66
|
+
doc = input_stream.read
|
67
|
+
|
68
|
+
if doc =~ /^(\s*---(.+)---\s*)/m
|
69
|
+
yaml = $2.strip
|
70
|
+
template = doc.sub($1, '')
|
71
|
+
|
72
|
+
YAML.each_document(yaml) do |data|
|
73
|
+
puts Mustache.render(template, data)
|
74
|
+
end
|
75
|
+
else
|
76
|
+
puts Mustache.render(doc)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Help is the default.
|
83
|
+
ARGV << '-h' if ARGV.empty? && $stdin.tty?
|
84
|
+
|
85
|
+
# Process options
|
86
|
+
Mustache::CLI.parse_options(ARGV) if $stdin.tty?
|
87
|
+
|
88
|
+
# Still here - process ARGF
|
89
|
+
Mustache::CLI.process_files(ARGF)
|
90
|
+
|
@@ -0,0 +1,278 @@
|
|
1
|
+
;;; tpl-mode.el -- a major mode for editing Google CTemplate files.
|
2
|
+
;;; By Tony Gentilcore, July 2006
|
3
|
+
;;;
|
4
|
+
;;; Very minor, backwards compatible changes added for Mustache compatibility
|
5
|
+
;;; by Chris Wanstrath, October 2009
|
6
|
+
;;;
|
7
|
+
;;; TO USE:
|
8
|
+
;;; 1) Copy this file somewhere you in emacs load-path. To see what
|
9
|
+
;;; your load-path is, run inside emacs: C-h v load-path<RET>
|
10
|
+
;;; 2) Add the following two lines to your .emacs file:
|
11
|
+
;;; (setq auto-mode-alist (cons '("\\.tpl$" . tpl-mode) auto-mode-alist))
|
12
|
+
;;; (autoload 'tpl-mode "tpl-mode" "Major mode for editing CTemplate files." t)
|
13
|
+
;;; 3) Optionally (but recommended), add this third line as well:
|
14
|
+
;;; (add-hook 'tpl-mode-hook '(lambda () (font-lock-mode 1)))
|
15
|
+
;;; ---
|
16
|
+
;;;
|
17
|
+
;;; While the Mustache language can be used for any types of text,
|
18
|
+
;;; this mode is intended for using Mustache to write HTML.
|
19
|
+
;;;
|
20
|
+
;;; The indentation still has minor bugs due to the fact that
|
21
|
+
;;; templates do not require valid HTML.
|
22
|
+
;;;
|
23
|
+
;;; It would be nice to be able to highlight attributes of HTML tags,
|
24
|
+
;;; however this is difficult due to the presence of CTemplate symbols
|
25
|
+
;;; embedded within attributes.
|
26
|
+
|
27
|
+
(eval-when-compile
|
28
|
+
(require 'font-lock))
|
29
|
+
|
30
|
+
(defgroup tpl-mode nil
|
31
|
+
"Major mode for editing Google CTemplate and Mustache files"
|
32
|
+
:group 'languages)
|
33
|
+
|
34
|
+
(defvar tpl-mode-version "1.1"
|
35
|
+
"Version of `tpl-mode.el'.")
|
36
|
+
|
37
|
+
(defvar tpl-mode-abbrev-table nil
|
38
|
+
"Abbrev table for use in tpl-mode buffers.")
|
39
|
+
|
40
|
+
(define-abbrev-table 'tpl-mode-abbrev-table ())
|
41
|
+
|
42
|
+
(defcustom tpl-mode-hook nil
|
43
|
+
"*Hook that runs upon entering tpl-mode."
|
44
|
+
:type 'hook)
|
45
|
+
|
46
|
+
(defvar tpl-mode-map nil
|
47
|
+
"Keymap for tpl-mode major mode")
|
48
|
+
|
49
|
+
(if tpl-mode-map
|
50
|
+
nil
|
51
|
+
(setq tpl-mode-map (make-sparse-keymap)))
|
52
|
+
|
53
|
+
(define-key tpl-mode-map "\t" 'tpl-indent-command)
|
54
|
+
(define-key tpl-mode-map "\C-m" 'reindent-then-newline-and-indent)
|
55
|
+
(define-key tpl-mode-map "\C-ct" 'tpl-insert-tag)
|
56
|
+
(define-key tpl-mode-map "\C-cv" 'tpl-insert-variable)
|
57
|
+
(define-key tpl-mode-map "\C-cs" 'tpl-insert-section)
|
58
|
+
|
59
|
+
|
60
|
+
(defvar tpl-mode-syntax-table nil
|
61
|
+
"Syntax table in use in tpl-mode buffers.")
|
62
|
+
|
63
|
+
;; Syntax table.
|
64
|
+
(if tpl-mode-syntax-table
|
65
|
+
nil
|
66
|
+
(setq tpl-mode-syntax-table (make-syntax-table text-mode-syntax-table))
|
67
|
+
(modify-syntax-entry ?< "(> " tpl-mode-syntax-table)
|
68
|
+
(modify-syntax-entry ?> ")< " tpl-mode-syntax-table)
|
69
|
+
(modify-syntax-entry ?\" ". " tpl-mode-syntax-table)
|
70
|
+
(modify-syntax-entry ?\\ ". " tpl-mode-syntax-table)
|
71
|
+
(modify-syntax-entry ?' "w " tpl-mode-syntax-table))
|
72
|
+
|
73
|
+
(defvar tpl-basic-offset 2
|
74
|
+
"The basic indentation offset.")
|
75
|
+
|
76
|
+
;; Constant regular expressions to identify template elements.
|
77
|
+
(defconst tpl-mode-tpl-token "[a-zA-Z_][a-zA-Z0-9_:=\?!-]*?")
|
78
|
+
(defconst tpl-mode-section (concat "\\({{[#^/]\s*"
|
79
|
+
tpl-mode-tpl-token
|
80
|
+
"\s*}}\\)"))
|
81
|
+
(defconst tpl-mode-open-section (concat "\\({{#\s*"
|
82
|
+
tpl-mode-tpl-token
|
83
|
+
"\s*}}\\)"))
|
84
|
+
(defconst tpl-mode-close-section (concat "{{/\\(\s*"
|
85
|
+
tpl-mode-tpl-token
|
86
|
+
"\s*\\)}}"))
|
87
|
+
;; TODO(tonyg) Figure out a way to support multiline comments.
|
88
|
+
(defconst tpl-mode-comment "\\({{!.*?}}\\)")
|
89
|
+
(defconst tpl-mode-include (concat "\\({{[><]\s*"
|
90
|
+
tpl-mode-tpl-token
|
91
|
+
"\s*}}\\)"))
|
92
|
+
(defconst tpl-mode-variable (concat "\\({{\s*"
|
93
|
+
tpl-mode-tpl-token
|
94
|
+
"\s*}}\\)"))
|
95
|
+
(defconst tpl-mode-builtins
|
96
|
+
(concat
|
97
|
+
"\\({{\\<\s*"
|
98
|
+
(regexp-opt
|
99
|
+
'("BI_NEWLINE" "BI_SPACE")
|
100
|
+
t)
|
101
|
+
"\s*\\>}}\\)"))
|
102
|
+
(defconst tpl-mode-close-section-at-start (concat "^[ \t]*?"
|
103
|
+
tpl-mode-close-section))
|
104
|
+
|
105
|
+
;; Constant regular expressions to identify html tags.
|
106
|
+
;; Taken from HTML 4.01 / XHTML 1.0 Reference found at:
|
107
|
+
;; http://www.w3schools.com/tags/default.asp.
|
108
|
+
(defconst tpl-mode-html-constant "\\(&#?[a-z0-9]\\{2,5\\};\\)")
|
109
|
+
(defconst tpl-mode-pair-tag
|
110
|
+
(concat
|
111
|
+
"\\<"
|
112
|
+
(regexp-opt
|
113
|
+
'("a" "abbr" "acronym" "address" "applet" "area" "b" "bdo"
|
114
|
+
"big" "blockquote" "body" "button" "caption" "center" "cite"
|
115
|
+
"code" "col" "colgroup" "dd" "del" "dfn" "dif" "div" "dl"
|
116
|
+
"dt" "em" "fieldset" "font" "form" "frame" "frameset" "h1"
|
117
|
+
"h2" "h3" "h4" "h5" "h6" "head" "html" "i" "iframe" "ins"
|
118
|
+
"kbd" "label" "legend" "li" "link" "map" "menu" "noframes"
|
119
|
+
"noscript" "object" "ol" "optgroup" "option" "p" "pre" "q"
|
120
|
+
"s" "samp" "script" "select" "small" "span" "strike"
|
121
|
+
"strong" "style" "sub" "sup" "table" "tbody" "td" "textarea"
|
122
|
+
"tfoot" "th" "thead" "title" "tr" "tt" "u" "ul" "var")
|
123
|
+
t)
|
124
|
+
"\\>"))
|
125
|
+
(defconst tpl-mode-standalone-tag
|
126
|
+
(concat
|
127
|
+
"\\<"
|
128
|
+
(regexp-opt
|
129
|
+
'("base" "br" "hr" "img" "input" "meta" "param")
|
130
|
+
t)
|
131
|
+
"\\>"))
|
132
|
+
(defconst tpl-mode-open-tag (concat "<\\("
|
133
|
+
tpl-mode-pair-tag
|
134
|
+
"\\)"))
|
135
|
+
(defconst tpl-mode-close-tag (concat "</\\("
|
136
|
+
tpl-mode-pair-tag
|
137
|
+
"\\)>"))
|
138
|
+
(defconst tpl-mode-close-tag-at-start (concat "^[ \t]*?"
|
139
|
+
tpl-mode-close-tag))
|
140
|
+
|
141
|
+
(defconst tpl-mode-blank-line "^[ \t]*?$")
|
142
|
+
(defconst tpl-mode-dangling-open (concat "\\("
|
143
|
+
tpl-mode-open-section
|
144
|
+
"\\)\\|\\("
|
145
|
+
tpl-mode-open-tag
|
146
|
+
"\\)[^/]*$"))
|
147
|
+
|
148
|
+
(defun tpl-indent-command ()
|
149
|
+
"Command for indenting text. Just calls tpl-indent."
|
150
|
+
(interactive)
|
151
|
+
(tpl-indent))
|
152
|
+
|
153
|
+
(defun tpl-insert-tag (tag)
|
154
|
+
"Inserts an HTML tag."
|
155
|
+
(interactive "sTag: ")
|
156
|
+
(tpl-indent)
|
157
|
+
(insert (concat "<" tag ">"))
|
158
|
+
(insert "\n\n")
|
159
|
+
(insert (concat "</" tag ">"))
|
160
|
+
(tpl-indent)
|
161
|
+
(forward-line -1)
|
162
|
+
(tpl-indent))
|
163
|
+
|
164
|
+
(defun tpl-insert-variable (variable)
|
165
|
+
"Inserts a tpl variable."
|
166
|
+
(interactive "sVariable: ")
|
167
|
+
(insert (concat "{{" variable "}}")))
|
168
|
+
|
169
|
+
(defun tpl-insert-section (section)
|
170
|
+
"Inserts a tpl section."
|
171
|
+
(interactive "sSection: ")
|
172
|
+
(tpl-indent)
|
173
|
+
(insert (concat "{{#" section "}}\n"))
|
174
|
+
(insert "\n")
|
175
|
+
(insert (concat "{{/" section "}}"))
|
176
|
+
(tpl-indent)
|
177
|
+
(forward-line -1)
|
178
|
+
(tpl-indent))
|
179
|
+
|
180
|
+
;; Function to control indenting.
|
181
|
+
(defun tpl-indent ()
|
182
|
+
"Indent current line"
|
183
|
+
;; Set the point to beginning of line.
|
184
|
+
(beginning-of-line)
|
185
|
+
;; If we are at the beginning of the file, indent to 0.
|
186
|
+
(if (bobp)
|
187
|
+
(indent-line-to 0)
|
188
|
+
(let ((tag-stack 1) (close-tag "") (cur-indent 0) (old-pnt (point-marker))
|
189
|
+
(close-at-start) (open-token) (dangling-open))
|
190
|
+
(progn
|
191
|
+
;; Determine if this is a template line or an html line.
|
192
|
+
(if (looking-at "^[ \t]*?{{")
|
193
|
+
(setq close-at-start tpl-mode-close-section-at-start
|
194
|
+
open-token "{{#")
|
195
|
+
(setq close-at-start tpl-mode-close-tag-at-start
|
196
|
+
open-token "<"))
|
197
|
+
;; If there is a closing tag at the start of the line, search back
|
198
|
+
;; for its opener and indent to that level.
|
199
|
+
(if (looking-at close-at-start)
|
200
|
+
(progn
|
201
|
+
(save-excursion
|
202
|
+
(setq close-tag (match-string 1))
|
203
|
+
;; Keep searching for a match for the close tag until
|
204
|
+
;; the tag-stack is 0.
|
205
|
+
(while (and (not (bobp))
|
206
|
+
(> tag-stack 0)
|
207
|
+
(re-search-backward (concat open-token
|
208
|
+
"\\(/?\\)"
|
209
|
+
close-tag) nil t))
|
210
|
+
(if (string-equal (match-string 1) "/")
|
211
|
+
;; We found another close tag, so increment tag-stack.
|
212
|
+
(setq tag-stack (+ tag-stack 1))
|
213
|
+
;; We found an open tag, so decrement tag-stack.
|
214
|
+
(setq tag-stack (- tag-stack 1)))
|
215
|
+
(setq cur-indent (current-indentation))))
|
216
|
+
(if (> tag-stack 0)
|
217
|
+
(save-excursion
|
218
|
+
(forward-line -1)
|
219
|
+
(setq cur-indent (current-indentation)))))
|
220
|
+
;; This was not a closing tag, so we check if the previous line
|
221
|
+
;; was an opening tag.
|
222
|
+
(save-excursion
|
223
|
+
;; Keep moving back until we find a line that is not blank
|
224
|
+
(while (progn
|
225
|
+
(forward-line -1)
|
226
|
+
(and (not (bobp)) (looking-at tpl-mode-blank-line))))
|
227
|
+
(setq cur-indent (current-indentation))
|
228
|
+
(if (re-search-forward tpl-mode-dangling-open old-pnt t)
|
229
|
+
(setq cur-indent (+ cur-indent tpl-basic-offset)))))
|
230
|
+
;; Finally, we execute the actual indentation.
|
231
|
+
(if (> cur-indent 0)
|
232
|
+
(indent-line-to cur-indent)
|
233
|
+
(indent-line-to 0))))))
|
234
|
+
|
235
|
+
;; controls highlighting
|
236
|
+
(defconst tpl-mode-font-lock-keywords
|
237
|
+
(list
|
238
|
+
(list tpl-mode-section
|
239
|
+
'(1 font-lock-keyword-face))
|
240
|
+
(list tpl-mode-comment
|
241
|
+
'(1 font-lock-comment-face))
|
242
|
+
(list tpl-mode-include
|
243
|
+
'(1 font-lock-function-name-face))
|
244
|
+
(list tpl-mode-builtins
|
245
|
+
'(1 font-lock-variable-name-face))
|
246
|
+
(list tpl-mode-variable
|
247
|
+
'(1 font-lock-reference-face))
|
248
|
+
(list (concat "</?\\(" tpl-mode-pair-tag "\\)")
|
249
|
+
'(1 font-lock-function-name-face))
|
250
|
+
(list (concat "<\\(" tpl-mode-standalone-tag "\\)")
|
251
|
+
'(1 font-lock-function-name-face))
|
252
|
+
(list tpl-mode-html-constant
|
253
|
+
'(1 font-lock-variable-name-face))))
|
254
|
+
|
255
|
+
(put 'tpl-mode 'font-lock-defaults '(tpl-font-lock-keywords nil t))
|
256
|
+
|
257
|
+
(defun tpl-mode ()
|
258
|
+
"Major mode for editing Google CTemplate file."
|
259
|
+
(interactive)
|
260
|
+
(kill-all-local-variables)
|
261
|
+
(use-local-map tpl-mode-map)
|
262
|
+
(setq major-mode 'tpl-mode)
|
263
|
+
(setq mode-name "tpl-mode")
|
264
|
+
(setq local-abbrev-table tpl-mode-abbrev-table)
|
265
|
+
(setq indent-tabs-mode nil)
|
266
|
+
(set-syntax-table tpl-mode-syntax-table)
|
267
|
+
;; show trailing whitespace, but only when the user can fix it
|
268
|
+
(setq show-trailing-whitespace (not buffer-read-only))
|
269
|
+
(make-local-variable 'indent-line-function)
|
270
|
+
(setq indent-line-function 'tpl-indent)
|
271
|
+
(setq font-lock-defaults '(tpl-mode-font-lock-keywords))
|
272
|
+
(run-hooks 'tpl-mode-hook))
|
273
|
+
|
274
|
+
;; Automatically load tpl-mode for .mustache files.
|
275
|
+
(add-to-list 'auto-mode-alist '("\\.mustache$" . tpl-mode))
|
276
|
+
(add-hook 'tpl-mode-hook '(lambda () (font-lock-mode 1)))
|
277
|
+
|
278
|
+
(provide 'mustache-mode)
|