Skip to content

Commit fc47e2b

Browse files
committed
Add Silverstripe Templates language
1 parent 2409807 commit fc47e2b

9 files changed

Lines changed: 379 additions & 0 deletions

File tree

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,9 @@
338338
[submodule "vendor/grammars/atom-salt"]
339339
path = vendor/grammars/atom-salt
340340
url = https://github.com/saltstack/atom-salt
341+
[submodule "vendor/grammars/atom-silverstripe"]
342+
path = vendor/grammars/atom-silverstripe
343+
url = https://github.com/gorriecoe/atom-silverstripe.git
341344
[submodule "vendor/grammars/ats"]
342345
path = vendor/grammars/ats
343346
url = https://github.com/steinwaywhw/ats-mode-sublimetext

grammars.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ vendor/grammars/atom-miniyaml:
278278
vendor/grammars/atom-salt:
279279
- source.python.salt
280280
- source.yaml.salt
281+
vendor/grammars/atom-silverstripe:
282+
- text.html.ss
281283
vendor/grammars/ats:
282284
- source.ats
283285
vendor/grammars/avro.tmLanguage:

lib/linguist/languages.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6773,6 +6773,14 @@ SELinux Policy:
67736773
- security_classes
67746774
ace_mode: text
67756775
language_id: 880010326
6776+
Silverstripe Templates:
6777+
type: markup
6778+
color: "#005AE1"
6779+
extensions:
6780+
- ".ss"
6781+
tm_scope: text.html.ss
6782+
ace_mode: text
6783+
language_id: 332108002
67766784
SMT:
67776785
type: programming
67786786
extensions:

samples/Scheme/load.ss

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
(unless (assoc "code" (library-directories))
2+
(library-directories (cons "code" (library-directories))))
3+
4+
(import (json)
5+
(outils)
6+
(lint)
7+
(markdown))
8+
9+
(load "code/track.ss")
10+
11+
;; file came from https://github.com/exercism/scheme/blob/main/load.ss
12+
;; license is as follows
13+
;; MIT License
14+
15+
;; Copyright (c) 2021 Exercism
16+
17+
;; Permission is hereby granted, free of charge, to any person obtaining a copy
18+
;; of this software and associated documentation files (the "Software"), to deal
19+
;; in the Software without restriction, including without limitation the rights
20+
;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21+
;; copies of the Software, and to permit persons to whom the Software is
22+
;; furnished to do so, subject to the following conditions:
23+
24+
;; The above copyright notice and this permission notice shall be included in all
25+
;; copies or substantial portions of the Software.
26+
27+
;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28+
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29+
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30+
;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31+
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32+
;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33+
;; SOFTWARE.

samples/Scheme/track.ss

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
;;;; Main track tooling
2+
3+
;;; Config
4+
5+
;; config/config.ss => config.json
6+
(define (make-config)
7+
(let ((config.json "config.json"))
8+
(when (file-exists? config.json)
9+
(delete-file config.json))
10+
(with-output-to-file config.json
11+
(lambda ()
12+
(json-write (processed-config))))))
13+
14+
;;; Problem Specifications
15+
16+
;; List the files in the given problem's
17+
;; problem-specifications/exercises/problem directory
18+
(define (get-problem-specification problem)
19+
(let* ((problem-dir (format "../problem-specifications/exercises/~a" problem))
20+
(spec (directory-list problem-dir)))
21+
(map (lambda (file)
22+
(format "~a/~a" problem-dir file))
23+
spec)))
24+
25+
;; reads the test specification for a given problem
26+
(define (get-test-specification problem)
27+
(lookup problem (load-specifications)))
28+
29+
;; parse the canonical-data.json file to scheme
30+
(define (get-implemented-test-specification problem)
31+
(let ((test-suite-file (find (lambda (spec)
32+
(string=? "json" (path-extension spec)))
33+
(get-problem-specification problem))))
34+
(and test-suite-file
35+
(cons problem
36+
(with-input-from-file test-suite-file json-read)))))
37+
38+
;; name of the file containing all the persisted specifications
39+
(define specification-file
40+
"input/specifications.ss")
41+
42+
;; read all the problems with canonical-data.json files and save as
43+
;; a scheme datum
44+
(define (persist-specifications)
45+
(when (file-exists? specification-file)
46+
(delete-file specification-file))
47+
(with-output-to-file specification-file
48+
(lambda ()
49+
(pretty-print
50+
(filter (lambda (x) x)
51+
(map get-implemented-test-specification
52+
(get-problem-list)))))))
53+
54+
;; load saved specifications
55+
(define (load-specifications)
56+
(with-input-from-file specification-file read))
57+
58+
;; list all the problems in the problem-specifications directory
59+
(define (get-problem-list)
60+
(map string->symbol (directory-list "../problem-specifications/exercises")))
61+
62+
;;; Test suite
63+
64+
;; read the input/test.ss file as s-expressions
65+
(define *test-definitions*
66+
(with-input-from-file "input/skeleton-test.ss" read-all))
67+
68+
;;; Problem Implementations
69+
70+
(define (load-problem problem)
71+
(load (format "input/exercises/~a/test.ss" problem)))
72+
73+
;; table to hold problem implementations
74+
(define *problem-table*
75+
(make-hash-table))
76+
77+
;; log a problem and its implementation to the problem table. The
78+
;; implementation is specified as an association list with tests, and
79+
;; file paths to the problem skeleton and the problem example
80+
;; solution.
81+
(define (put-problem! problem implementation)
82+
(for-each (lambda (aspect)
83+
(unless (assoc aspect implementation)
84+
(error 'put-test! "problem does not implement" problem aspect)))
85+
;; test is an sexpression. skeleton and solution are file paths
86+
'(test skeleton solution))
87+
(hashtable-set! *problem-table* problem implementation))
88+
89+
;; look up the problem in the problem table.
90+
(define (get-problem problem)
91+
(let ((implementation (hashtable-ref *problem-table* problem #f)))
92+
(or implementation
93+
(begin
94+
(load-problem problem)
95+
(let ((implementation (hashtable-ref *problem-table* problem #f)))
96+
(unless implementation
97+
(error 'get-problem "no implementation" problem))
98+
implementation)))))
99+
100+
;;; Stubbing, Building, and Testing problems
101+
102+
;; Read the problem-specifications directory and generate a stub
103+
;; implementation.
104+
(define (stub-exercism problem)
105+
(format #t "setting up ~a~%" problem)
106+
(let* ((dir (format "input/exercises/~a" problem))
107+
(implementation (format "~a/test.ss" dir))
108+
;; todo, add "properties" found in spec to stub skeleton and solution
109+
(skeleton (format "~a/~a.scm" dir problem))
110+
(solution (format "~a/example.scm" dir))
111+
;; see input/exercises/anagram/anagram.ss for more information
112+
(stub-implementation
113+
`(,@'((define (parse-test test)
114+
`(test-success (lookup 'description test)
115+
equal?
116+
problem
117+
(lookup 'input test)
118+
(lookup 'expected test)))
119+
(define (spec->tests spec)
120+
(map parse-test (lookup 'cases spec))))
121+
(let ((spec (get-test-specification ',problem)))
122+
(put-problem! ',problem
123+
`((test . ,(spec->tests spec))
124+
(stubs ,problem)
125+
(version . (lookup 'version spec))
126+
(skeleton . ,,(path-last skeleton))
127+
(solution . ,,(path-last solution))
128+
(markdown . (splice-exercism ,,problem)))))))
129+
(stub-solution `((import (rnrs))
130+
(define (,problem)
131+
'implement-me!))))
132+
(when (file-exists? implementation)
133+
(error 'setup-exercism "implementation already exists" problem))
134+
(system (format "mkdir -p ~a" dir))
135+
(format #t "~~ writing stub implementation~%")
136+
(write-expression-to-file stub-implementation implementation)
137+
(format #t "~~ writing stub solution~%")
138+
(write-expression-to-file stub-solution skeleton)
139+
(format #t "~~ writing stub skeleton~%")
140+
(write-expression-to-file stub-solution solution)))
141+
142+
;; output the problem as specified in input/exercises/problem/* to
143+
;; _build/exercises/problem/*. This is a temporary location to first
144+
;; test the problem before actually writing to exercises/problem/*.
145+
(define (build-exercism problem)
146+
(let ((implementation (get-problem problem)))
147+
(let* ((dir (format "_build/exercises/~a" problem))
148+
(src (format "input/exercises/~a" problem))
149+
(test.scm (format "~a/test.scm" dir))
150+
(skeleton.scm (format "~a/~a" src (lookup 'skeleton implementation)))
151+
(solution.scm (format "~a/~a" src (lookup 'solution implementation))))
152+
(format #t "writing _build/exercises/~a~%" problem)
153+
(system
154+
(format "mkdir -p ~a && cp ~a ~a && cp ~a ~a && cp ~a ~a/Makefile"
155+
dir skeleton.scm dir solution.scm dir "input/skeleton-makefile" dir))
156+
(markdown-exercism problem)
157+
(version-exercism problem)
158+
(write-expression-to-file
159+
(apply make-test-file
160+
(lookup 'test implementation)
161+
problem
162+
(lookup 'stubs implementation))
163+
test.scm))))
164+
165+
;; splice the skeleton test file with the problem's test cases
166+
(define (make-test-file tests problem . stub-defs)
167+
`((import (except (rnrs) current-output-port))
168+
,@*test-definitions*
169+
,@(map (lambda (stub-def)
170+
`(define ,stub-def))
171+
stub-defs)
172+
(define test-cases
173+
(list
174+
,@(map (lambda (test)
175+
`(lambda ()
176+
,test))
177+
tests)))
178+
(define (test . query)
179+
(apply run-test-suite test-cases query))
180+
(let ((args (command-line)))
181+
(cond ((null? (cdr args))
182+
(load ,(format "~a.scm" problem))
183+
(test 'input 'output))
184+
((string=? (cadr args) "--docker")
185+
(load ,(format "~a.scm" problem))
186+
(run-docker test-cases))
187+
(else
188+
(load (cadr args))
189+
(test 'input 'output))))))
190+
191+
;; output the markdown for the problem
192+
(define (markdown-exercism problem)
193+
(let* ((markdown (lookup 'markdown (get-problem problem)))
194+
(target (format "_build/exercises/~a/.meta/hints.md" problem))
195+
(meta-dir (path-parent target)))
196+
(unless (file-exists? meta-dir)
197+
(mkdir (path-parent target)))
198+
(when (file-exists? target)
199+
(delete-file target))
200+
(with-output-to-file target
201+
(lambda ()
202+
(put-md markdown)))))
203+
204+
;; if version field is specified, include .meta/version in exercise
205+
;; directory.
206+
(define (version-exercism problem)
207+
(cond ((assoc 'version (get-problem problem)) =>
208+
(lambda (version)
209+
(let* ((target (format "_build/exercises/~a/.meta/version" problem))
210+
(meta-dir (path-parent target)))
211+
(unless (file-exists? meta-dir)
212+
(mkdir (path-parent target)))
213+
(when (file-exists? target)
214+
(delete-file target))
215+
(with-output-to-file target
216+
(lambda ()
217+
(display (cdr version)))))))))
218+
219+
;; test the problem output in _build/exercises/problem/* by using the
220+
;; skeleton makefile
221+
(define (verify-exercism problem)
222+
(let ((dir (format "_build/exercises/~a" problem)))
223+
(check-config-for problem)
224+
(let ((x (system (format "cd ~a && make check-all solution=example.scm" dir))))
225+
(unless (zero? x)
226+
(error 'verify-exercism "example solution incorrect" problem)))
227+
'done))
228+
229+
;; called if the tests succeed. write the problem to exercises/problem/
230+
(define (include-exercism problem)
231+
(format #t "including exercises/~a~%" problem)
232+
(system (format "rm -rf exercises/~a && cp -r _build/exercises/~a exercises/~a"
233+
problem problem problem))
234+
'done)
235+
236+
;; build all implementations in the problem table
237+
(define (build-implementations)
238+
(for-each build-exercism implementations))
239+
240+
;; test all problems as implemented
241+
(define (verify-implementations)
242+
(for-each verify-exercism implementations))
243+
244+
;; build/test/write problem
245+
(define (make-exercism problem)
246+
(build-exercism problem)
247+
(verify-exercism problem)
248+
(include-exercism problem))
249+
250+
;; file came from https://github.com/exercism/scheme/blob/main/code/track.ss
251+
;; license is as follows
252+
;; MIT License
253+
254+
;; Copyright (c) 2021 Exercism
255+
256+
;; Permission is hereby granted, free of charge, to any person obtaining a copy
257+
;; of this software and associated documentation files (the "Software"), to deal
258+
;; in the Software without restriction, including without limitation the rights
259+
;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
260+
;; copies of the Software, and to permit persons to whom the Software is
261+
;; furnished to do so, subject to the following conditions:
262+
263+
;; The above copyright notice and this permission notice shall be included in all
264+
;; copies or substantial portions of the Software.
265+
266+
;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
267+
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
268+
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
269+
;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
270+
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
271+
;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
272+
;; SOFTWARE.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<ul $AttributesHTML>
2+
<% if $Options.Count %>
3+
<% loop $Options %>
4+
<li class="$Class">
5+
<input id="$ID"
6+
class="checkbox"
7+
name="$Name"
8+
type="checkbox"
9+
role="$Role"
10+
value="$Value.ATT"
11+
<% if $isChecked %>checked="checked"<% end_if %>
12+
<% if $isDisabled %>disabled="disabled"<% end_if %>
13+
/>
14+
<label class="form-label" for="$ID">$Title</label>
15+
</li>
16+
<% end_loop %>
17+
<% else %>
18+
<li><%t SilverStripe\\Forms\\CheckboxSetField_ss.NOOPTIONSAVAILABLE 'No options available' %></li>
19+
<% end_if %>
20+
</ul>
21+
<%-- This example is from https://github.com/silverstripe/silverstripe-framework/blob/6/templates/SilverStripe/Forms/CheckboxSetField.ss --%>

0 commit comments

Comments
 (0)