From fc47e2b6e7ec611208dc9cae260d9f3f29c0fa90 Mon Sep 17 00:00:00 2001 From: Guy Sartorelli Date: Thu, 20 Nov 2025 16:18:24 +1300 Subject: [PATCH 1/2] Add Silverstripe Templates language --- .gitmodules | 3 + grammars.yml | 2 + lib/linguist/languages.yml | 8 + samples/Scheme/load.ss | 33 +++ samples/Scheme/track.ss | 272 ++++++++++++++++++ .../CheckboxSetField.ss | 21 ++ samples/Silverstripe Templates/page.ss | 38 +++ vendor/README.md | 1 + vendor/grammars/atom-silverstripe | 1 + 9 files changed, 379 insertions(+) create mode 100644 samples/Scheme/load.ss create mode 100644 samples/Scheme/track.ss create mode 100644 samples/Silverstripe Templates/CheckboxSetField.ss create mode 100644 samples/Silverstripe Templates/page.ss create mode 160000 vendor/grammars/atom-silverstripe diff --git a/.gitmodules b/.gitmodules index f2c90a1cad..ea58029234 100644 --- a/.gitmodules +++ b/.gitmodules @@ -338,6 +338,9 @@ [submodule "vendor/grammars/atom-salt"] path = vendor/grammars/atom-salt url = https://github.com/saltstack/atom-salt +[submodule "vendor/grammars/atom-silverstripe"] + path = vendor/grammars/atom-silverstripe + url = https://github.com/gorriecoe/atom-silverstripe.git [submodule "vendor/grammars/ats"] path = vendor/grammars/ats url = https://github.com/steinwaywhw/ats-mode-sublimetext diff --git a/grammars.yml b/grammars.yml index 9da8a9b6a2..0d92f57020 100644 --- a/grammars.yml +++ b/grammars.yml @@ -278,6 +278,8 @@ vendor/grammars/atom-miniyaml: vendor/grammars/atom-salt: - source.python.salt - source.yaml.salt +vendor/grammars/atom-silverstripe: +- text.html.ss vendor/grammars/ats: - source.ats vendor/grammars/avro.tmLanguage: diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml index 971b8138eb..3f741b8710 100644 --- a/lib/linguist/languages.yml +++ b/lib/linguist/languages.yml @@ -6773,6 +6773,14 @@ SELinux Policy: - security_classes ace_mode: text language_id: 880010326 +Silverstripe Templates: + type: markup + color: "#005AE1" + extensions: + - ".ss" + tm_scope: text.html.ss + ace_mode: text + language_id: 332108002 SMT: type: programming extensions: diff --git a/samples/Scheme/load.ss b/samples/Scheme/load.ss new file mode 100644 index 0000000000..60c7273a82 --- /dev/null +++ b/samples/Scheme/load.ss @@ -0,0 +1,33 @@ +(unless (assoc "code" (library-directories)) + (library-directories (cons "code" (library-directories)))) + +(import (json) + (outils) + (lint) + (markdown)) + +(load "code/track.ss") + +;; file came from https://github.com/exercism/scheme/blob/main/load.ss +;; license is as follows +;; MIT License + +;; Copyright (c) 2021 Exercism + +;; Permission is hereby granted, free of charge, to any person obtaining a copy +;; of this software and associated documentation files (the "Software"), to deal +;; in the Software without restriction, including without limitation the rights +;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +;; copies of the Software, and to permit persons to whom the Software is +;; furnished to do so, subject to the following conditions: + +;; The above copyright notice and this permission notice shall be included in all +;; copies or substantial portions of the Software. + +;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +;; SOFTWARE. \ No newline at end of file diff --git a/samples/Scheme/track.ss b/samples/Scheme/track.ss new file mode 100644 index 0000000000..b62c25da71 --- /dev/null +++ b/samples/Scheme/track.ss @@ -0,0 +1,272 @@ +;;;; Main track tooling + +;;; Config + +;; config/config.ss => config.json +(define (make-config) + (let ((config.json "config.json")) + (when (file-exists? config.json) + (delete-file config.json)) + (with-output-to-file config.json + (lambda () + (json-write (processed-config)))))) + +;;; Problem Specifications + +;; List the files in the given problem's +;; problem-specifications/exercises/problem directory +(define (get-problem-specification problem) + (let* ((problem-dir (format "../problem-specifications/exercises/~a" problem)) + (spec (directory-list problem-dir))) + (map (lambda (file) + (format "~a/~a" problem-dir file)) + spec))) + +;; reads the test specification for a given problem +(define (get-test-specification problem) + (lookup problem (load-specifications))) + +;; parse the canonical-data.json file to scheme +(define (get-implemented-test-specification problem) + (let ((test-suite-file (find (lambda (spec) + (string=? "json" (path-extension spec))) + (get-problem-specification problem)))) + (and test-suite-file + (cons problem + (with-input-from-file test-suite-file json-read))))) + +;; name of the file containing all the persisted specifications +(define specification-file + "input/specifications.ss") + +;; read all the problems with canonical-data.json files and save as +;; a scheme datum +(define (persist-specifications) + (when (file-exists? specification-file) + (delete-file specification-file)) + (with-output-to-file specification-file + (lambda () + (pretty-print + (filter (lambda (x) x) + (map get-implemented-test-specification + (get-problem-list))))))) + +;; load saved specifications +(define (load-specifications) + (with-input-from-file specification-file read)) + +;; list all the problems in the problem-specifications directory +(define (get-problem-list) + (map string->symbol (directory-list "../problem-specifications/exercises"))) + +;;; Test suite + +;; read the input/test.ss file as s-expressions +(define *test-definitions* + (with-input-from-file "input/skeleton-test.ss" read-all)) + +;;; Problem Implementations + +(define (load-problem problem) + (load (format "input/exercises/~a/test.ss" problem))) + +;; table to hold problem implementations +(define *problem-table* + (make-hash-table)) + +;; log a problem and its implementation to the problem table. The +;; implementation is specified as an association list with tests, and +;; file paths to the problem skeleton and the problem example +;; solution. +(define (put-problem! problem implementation) + (for-each (lambda (aspect) + (unless (assoc aspect implementation) + (error 'put-test! "problem does not implement" problem aspect))) + ;; test is an sexpression. skeleton and solution are file paths + '(test skeleton solution)) + (hashtable-set! *problem-table* problem implementation)) + +;; look up the problem in the problem table. +(define (get-problem problem) + (let ((implementation (hashtable-ref *problem-table* problem #f))) + (or implementation + (begin + (load-problem problem) + (let ((implementation (hashtable-ref *problem-table* problem #f))) + (unless implementation + (error 'get-problem "no implementation" problem)) + implementation))))) + +;;; Stubbing, Building, and Testing problems + +;; Read the problem-specifications directory and generate a stub +;; implementation. +(define (stub-exercism problem) + (format #t "setting up ~a~%" problem) + (let* ((dir (format "input/exercises/~a" problem)) + (implementation (format "~a/test.ss" dir)) + ;; todo, add "properties" found in spec to stub skeleton and solution + (skeleton (format "~a/~a.scm" dir problem)) + (solution (format "~a/example.scm" dir)) + ;; see input/exercises/anagram/anagram.ss for more information + (stub-implementation + `(,@'((define (parse-test test) + `(test-success (lookup 'description test) + equal? + problem + (lookup 'input test) + (lookup 'expected test))) + (define (spec->tests spec) + (map parse-test (lookup 'cases spec)))) + (let ((spec (get-test-specification ',problem))) + (put-problem! ',problem + `((test . ,(spec->tests spec)) + (stubs ,problem) + (version . (lookup 'version spec)) + (skeleton . ,,(path-last skeleton)) + (solution . ,,(path-last solution)) + (markdown . (splice-exercism ,,problem))))))) + (stub-solution `((import (rnrs)) + (define (,problem) + 'implement-me!)))) + (when (file-exists? implementation) + (error 'setup-exercism "implementation already exists" problem)) + (system (format "mkdir -p ~a" dir)) + (format #t "~~ writing stub implementation~%") + (write-expression-to-file stub-implementation implementation) + (format #t "~~ writing stub solution~%") + (write-expression-to-file stub-solution skeleton) + (format #t "~~ writing stub skeleton~%") + (write-expression-to-file stub-solution solution))) + +;; output the problem as specified in input/exercises/problem/* to +;; _build/exercises/problem/*. This is a temporary location to first +;; test the problem before actually writing to exercises/problem/*. +(define (build-exercism problem) + (let ((implementation (get-problem problem))) + (let* ((dir (format "_build/exercises/~a" problem)) + (src (format "input/exercises/~a" problem)) + (test.scm (format "~a/test.scm" dir)) + (skeleton.scm (format "~a/~a" src (lookup 'skeleton implementation))) + (solution.scm (format "~a/~a" src (lookup 'solution implementation)))) + (format #t "writing _build/exercises/~a~%" problem) + (system + (format "mkdir -p ~a && cp ~a ~a && cp ~a ~a && cp ~a ~a/Makefile" + dir skeleton.scm dir solution.scm dir "input/skeleton-makefile" dir)) + (markdown-exercism problem) + (version-exercism problem) + (write-expression-to-file + (apply make-test-file + (lookup 'test implementation) + problem + (lookup 'stubs implementation)) + test.scm)))) + +;; splice the skeleton test file with the problem's test cases +(define (make-test-file tests problem . stub-defs) + `((import (except (rnrs) current-output-port)) + ,@*test-definitions* + ,@(map (lambda (stub-def) + `(define ,stub-def)) + stub-defs) + (define test-cases + (list + ,@(map (lambda (test) + `(lambda () + ,test)) + tests))) + (define (test . query) + (apply run-test-suite test-cases query)) + (let ((args (command-line))) + (cond ((null? (cdr args)) + (load ,(format "~a.scm" problem)) + (test 'input 'output)) + ((string=? (cadr args) "--docker") + (load ,(format "~a.scm" problem)) + (run-docker test-cases)) + (else + (load (cadr args)) + (test 'input 'output)))))) + +;; output the markdown for the problem +(define (markdown-exercism problem) + (let* ((markdown (lookup 'markdown (get-problem problem))) + (target (format "_build/exercises/~a/.meta/hints.md" problem)) + (meta-dir (path-parent target))) + (unless (file-exists? meta-dir) + (mkdir (path-parent target))) + (when (file-exists? target) + (delete-file target)) + (with-output-to-file target + (lambda () + (put-md markdown))))) + +;; if version field is specified, include .meta/version in exercise +;; directory. +(define (version-exercism problem) + (cond ((assoc 'version (get-problem problem)) => + (lambda (version) + (let* ((target (format "_build/exercises/~a/.meta/version" problem)) + (meta-dir (path-parent target))) + (unless (file-exists? meta-dir) + (mkdir (path-parent target))) + (when (file-exists? target) + (delete-file target)) + (with-output-to-file target + (lambda () + (display (cdr version))))))))) + +;; test the problem output in _build/exercises/problem/* by using the +;; skeleton makefile +(define (verify-exercism problem) + (let ((dir (format "_build/exercises/~a" problem))) + (check-config-for problem) + (let ((x (system (format "cd ~a && make check-all solution=example.scm" dir)))) + (unless (zero? x) + (error 'verify-exercism "example solution incorrect" problem))) + 'done)) + +;; called if the tests succeed. write the problem to exercises/problem/ +(define (include-exercism problem) + (format #t "including exercises/~a~%" problem) + (system (format "rm -rf exercises/~a && cp -r _build/exercises/~a exercises/~a" + problem problem problem)) + 'done) + +;; build all implementations in the problem table +(define (build-implementations) + (for-each build-exercism implementations)) + +;; test all problems as implemented +(define (verify-implementations) + (for-each verify-exercism implementations)) + +;; build/test/write problem +(define (make-exercism problem) + (build-exercism problem) + (verify-exercism problem) + (include-exercism problem)) + +;; file came from https://github.com/exercism/scheme/blob/main/code/track.ss +;; license is as follows +;; MIT License + +;; Copyright (c) 2021 Exercism + +;; Permission is hereby granted, free of charge, to any person obtaining a copy +;; of this software and associated documentation files (the "Software"), to deal +;; in the Software without restriction, including without limitation the rights +;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +;; copies of the Software, and to permit persons to whom the Software is +;; furnished to do so, subject to the following conditions: + +;; The above copyright notice and this permission notice shall be included in all +;; copies or substantial portions of the Software. + +;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +;; SOFTWARE. \ No newline at end of file diff --git a/samples/Silverstripe Templates/CheckboxSetField.ss b/samples/Silverstripe Templates/CheckboxSetField.ss new file mode 100644 index 0000000000..7066700a2a --- /dev/null +++ b/samples/Silverstripe Templates/CheckboxSetField.ss @@ -0,0 +1,21 @@ + +<%-- This example is from https://github.com/silverstripe/silverstripe-framework/blob/6/templates/SilverStripe/Forms/CheckboxSetField.ss --%> \ No newline at end of file diff --git a/samples/Silverstripe Templates/page.ss b/samples/Silverstripe Templates/page.ss new file mode 100644 index 0000000000..c59f138ffc --- /dev/null +++ b/samples/Silverstripe Templates/page.ss @@ -0,0 +1,38 @@ + + + + <% base_tag %> + <%-- Required meta tags --%> + + + $MetaTags(false) + + <% include Favicons %> + <% require themedCSS('startup') %> + + <% if $MetaTitle %>$MetaTitle<% else %>$Title<% end_if %> | $SiteConfig.Title + +dir="$i18nScriptDirection"<% end_if %>> + <% include Header %> +
+ <% if not $isHomePage %> + $Breadcrumbs + <% end_if %> +
+ $Layout +
+ <%t SilverStripe\\CMS\\Model\\SiteTree.ExampleLocalisation 'Too many children ({count})' count=$Children.Count %> +
+ + <% include Footer IncludeVar1=$Title IncludeVar2="raw string value" %> + <% if $HasPerm('CMS_ACCESS') || $SomeNumber >= 5 %> + $SilverStripeNavigator + <% else_if $OverridePermissions %> + Ooooh fancy permission override + <% else %> + Not authorised to see the navigator + <% end_if %> + + + +<%-- This example is from https://github.com/silverstripe/startup-theme/blob/1/templates/Page.ss but was modified for this example --%> \ No newline at end of file diff --git a/vendor/README.md b/vendor/README.md index a0ceb6b4e5..f77b88ecca 100644 --- a/vendor/README.md +++ b/vendor/README.md @@ -568,6 +568,7 @@ This is a list of grammars that Linguist selects to provide syntax highlighting - **ShellSession:** [atom/language-shellscript](https://github.com/atom/language-shellscript) - **Shen:** [rkoeninger/sublime-shen](https://github.com/rkoeninger/sublime-shen) - **Sieve:** [Alhadis/language-etc](https://github.com/Alhadis/language-etc) +- **Silverstripe Templates:** [gorriecoe/atom-silverstripe](https://github.com/gorriecoe/atom-silverstripe) - **Simple File Verification:** [Alhadis/language-etc](https://github.com/Alhadis/language-etc) - **Singularity:** [onnovalkering/vscode-singularity](https://github.com/onnovalkering/vscode-singularity) - **Slang:** [shader-slang/slang-vscode-extension](https://github.com/shader-slang/slang-vscode-extension) diff --git a/vendor/grammars/atom-silverstripe b/vendor/grammars/atom-silverstripe new file mode 160000 index 0000000000..f577dace44 --- /dev/null +++ b/vendor/grammars/atom-silverstripe @@ -0,0 +1 @@ +Subproject commit f577dace44e97b9c6c88a748cd548e9c5cd48462 From 0f93389f941173eb705583e48a851cffc27a7aa2 Mon Sep 17 00:00:00 2001 From: Colin Seymour Date: Fri, 12 Dec 2025 11:32:01 +0000 Subject: [PATCH 2/2] Add cached license --- .../git_submodule/atom-silverstripe.dep.yml | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 vendor/licenses/git_submodule/atom-silverstripe.dep.yml diff --git a/vendor/licenses/git_submodule/atom-silverstripe.dep.yml b/vendor/licenses/git_submodule/atom-silverstripe.dep.yml new file mode 100644 index 0000000000..45dacbf70d --- /dev/null +++ b/vendor/licenses/git_submodule/atom-silverstripe.dep.yml @@ -0,0 +1,39 @@ +--- +name: atom-silverstripe +version: f577dace44e97b9c6c88a748cd548e9c5cd48462 +type: git_submodule +homepage: https://github.com/gorriecoe/atom-silverstripe.git +license: other +licenses: +- sources: LICENSE.md + text: | + BSD 3-Clause License + + Copyright (c) 2020, gorriecoe + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +notices: []