diff -Nru ruby-rouge-3.21.0/CHANGELOG.md ruby-rouge-3.26.1/CHANGELOG.md --- ruby-rouge-3.21.0/CHANGELOG.md 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/CHANGELOG.md 2021-09-17 19:59:49.000000000 +0000 @@ -4,6 +4,120 @@ Rouge follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html). +## version 3.26.1: 2021-09-17 + +[Comparison with the previous version](https://github.com/rouge-ruby/rouge/compare/v3.26.0...v3.26.1) + +- CPP Lexer + - Add year and date chrono literals, add std::complex literals, fix chrono literals with digit separator ([#1665](https://github.com/rouge-ruby/rouge/pull/1665/) by swheaton) +- Factor and GHC Core Lexer + - Fix catastrophic backtrack ([#1690](https://github.com/rouge-ruby/rouge/pull/1690) by Ravlen) +- JSL Lexer + - Fix single line block comments, scoped variables and functions ([#1663](https://github.com/rouge-ruby/rouge/pull/1663) by BenPH) +- YAML Lexer + - Fix YAML key containing special character ([#1667](https://github.com/rouge-ruby/rouge/pull/1667) by tancnle) +- Fix Ruby 2.7 keyword parameter deprecation warning ([#1597](https://github.com/rouge-ruby/rouge/pull/1666) by stanhu) +- Updated README ([#1666](https://github.com/rouge-ruby/rouge/pull/1666) by dchacke) + +## version 3.26.0: 2020-12-09 + +[Comparison with the previous version](https://github.com/rouge-ruby/rouge/compare/v3.25.0...v3.26.0) + +- CMake Lexer + - Add missing CMake commands to CMake lexer ([#1630](https://github.com/rouge-ruby/rouge/pull/1630/) by gnaggnoyil) +- Crystal Lexer + - Improve visual sample and macro support for Crystal lexer ([#1644](https://github.com/rouge-ruby/rouge/pull/1644/) by Michael Camilleri) + - Support floor division operator in Crystal lexer ([#1639](https://github.com/rouge-ruby/rouge/pull/1639/) by Rymiel) +- JSL Lexer + - Fix lexing of messages, nested comments, missing operators and decimals in JSL lexer ([#1638](https://github.com/rouge-ruby/rouge/pull/1638/) by Ben Peachey Higdon) +- OCL Lexer (**NEW**) + - Add OCL lexer ([#1637](https://github.com/rouge-ruby/rouge/pull/1637/) by Gerson Sunyé) +- Python Lexer + - Use String::Affix token for string prefixes in Python lexer ([#1635](https://github.com/rouge-ruby/rouge/pull/1635/) by Tan Le) +- ReasonML Lexer + - Improve support for comments in ReasonML lexer ([#1641](https://github.com/rouge-ruby/rouge/pull/1641/) by Amirali Esmaeili) +- ReScript Lexer (**NEW**) + - Add ReScript lexer ([#1633](https://github.com/rouge-ruby/rouge/pull/1633/) by Amirali Esmaeili) +- Rust Lexer + - Add support for octal literals to Rust lexer ([#1643](https://github.com/rouge-ruby/rouge/pull/1643/) by nsfisis) + +## version 3.25.0: 2020-11-11 + +[Comparison with the previous version](https://github.com/rouge-ruby/rouge/compare/v3.24.0...v3.25.0) + +- General + - Use `Enumerator#with_index` to detect line numbers ([#1615](https://github.com/rouge-ruby/rouge/pull/1615/) by takafumi.suzuki) +- Batchfile Lexer + - Add support for long options to Batchfile lexer ([#1626](https://github.com/rouge-ruby/rouge/pull/1626/) by Michael Camilleri) +- C++ Lexer + - Fix binary literal digit separator in C++ lexer ([#1620](https://github.com/rouge-ruby/rouge/pull/1620/) by swheaton) +- Docker Lexer + - Add `Dockerfile` as an alias for the Docker lexer ([#1609](https://github.com/rouge-ruby/rouge/pull/1609/) by Konnor Rogers) +- JavaScript Lexer + - Fix template string lexing in JavaScript lexer ([#1623](https://github.com/rouge-ruby/rouge/pull/1623/) by Michael Camilleri) +- Kotlin Lexer + - Ensure word break follows keywords in Kotlin lexer ([#1621](https://github.com/rouge-ruby/rouge/pull/1621/) by Michael Camilleri) +- Perl Lexer + - Improve support for sigils in Perl lexer ([#1625](https://github.com/rouge-ruby/rouge/pull/1625/) by Michael Camilleri) +- PowerShell Lexer + - Improve lexing of nested data structures in PowerShell lexer ([#1622](https://github.com/rouge-ruby/rouge/pull/1622/) by Michael Camilleri) + - Improve handling of data structure literals in PowerShell lexer ([#1595](https://github.com/rouge-ruby/rouge/pull/1595/) by Jeanine Adkisson) +- Ruby Lexer + - Revert empty patterns in Ruby lexer ([#1624](https://github.com/rouge-ruby/rouge/pull/1624/) by Michael Camilleri) +- Rust Lexer + - Add continue to keywords in Rust lexer ([#1617](https://github.com/rouge-ruby/rouge/pull/1617/) by Aleksey Kladov) +- Velocity Lexer + - Fix lexing of brackets in Velocity lexer ([#1605](https://github.com/rouge-ruby/rouge/pull/1605/) by domRowan) + +## version 3.24.0: 2020-10-14 + +[Comparison with the previous version](https://github.com/rouge-ruby/rouge/compare/v3.23.0...v3.24.0) + +- General + - Fix errors from new empty regex requirements ([#1606](https://github.com/rouge-ruby/rouge/pull/1606/) by Michael Camilleri) + - Restrict the use of empty-matching regular expressions ([#1548](https://github.com/rouge-ruby/rouge/pull/1548/) by Jeanine Adkisson) + - Add a CLI debug command that provides reasonable defaults ([#1593](https://github.com/rouge-ruby/rouge/pull/1593/) by Jeanine Adkisson) + - Update documentation to use bundle config set path ([#1583](https://github.com/rouge-ruby/rouge/pull/1583/) by ComFreek) + - Add line highlighting option ([#1426](https://github.com/rouge-ruby/rouge/pull/1426/) by Dan Allen) + - Add Lexer#with and Lexer.lookup_fancy ([#1565](https://github.com/rouge-ruby/rouge/pull/1565/) by Jeanine Adkisson) +- Apex Lexer + - Fix invalid use of String#casecmp in Apex lexer ([#1596](https://github.com/rouge-ruby/rouge/pull/1596/) by Jeanine Adkisson) +- E-mail Lexer (**NEW**) + - Add e-mail lexer ([#1567](https://github.com/rouge-ruby/rouge/pull/1567/) by Steve Mokris) +- HTTP Lexer + - Add a :content option to HTTP lexer ([#1592](https://github.com/rouge-ruby/rouge/pull/1592/) by Jeanine Adkisson) +- J Lexer (**NEW**) + - Add J lexer ([#1584](https://github.com/rouge-ruby/rouge/pull/1584/) by unsigned-wrong-wrong-int) +- Janet Lexer + - Improve handling of quoted forms in Janet lexer ([#1586](https://github.com/rouge-ruby/rouge/pull/1586/) by Michael Camilleri) +- JavaScript Lexer + - Improve optional chaining in JavaScript lexer ([#1594](https://github.com/rouge-ruby/rouge/pull/1594/) by Jeanine Adkisson) +- Rust Lexer + - Fix lexing of await in Rust lexer ([#1587](https://github.com/rouge-ruby/rouge/pull/1587/) by nsfisis) + +## version 3.23.0: 2020-09-09 + +[Comparison with the previous version](https://github.com/rouge-ruby/rouge/compare/v3.22.0...v3.23.0) + +- Kotlin Lexer + - Fix handling of ::class in Kotlin lexer ([#1572](https://github.com/rouge-ruby/rouge/pull/1572/) by Manuel Dossinger) +- PostScript Lexer (**NEW**) + - Add PostScript lexer ([#1578](https://github.com/rouge-ruby/rouge/pull/1578/) by Liam Cooke) +- Ruby Lexer + - Handle % like / in Ruby lexer ([#1563](https://github.com/rouge-ruby/rouge/pull/1563/) by Jeanine Adkisson) +- Rust Lexer + - Support tuple index expressions in Rust lexer ([#1580](https://github.com/rouge-ruby/rouge/pull/1580/) by Hugo Peixoto) + - Fix floating point separators in Rust lexer ([#1581](https://github.com/rouge-ruby/rouge/pull/1581/) by Hugo Peixoto) +- systemd Lexer (**NEW**) + - Add systemd lexer ([#1568](https://github.com/rouge-ruby/rouge/pull/1568/) by Jean-Louis Jouannic) + +## version 3.22.0: 2020-08-12 + +[Comparison with the previous version](https://github.com/rouge-ruby/rouge/compare/v3.21.0...v3.22.0) + +- PHP Lexer + - Rewrite PHP lexer to support use statements, function declarations and type declarations ([#1489](https://github.com/rouge-ruby/rouge/pull/1489/) by Michael Camilleri) + ## version 3.21.0: 2020-07-15 [Comparison with the previous version](https://github.com/rouge-ruby/rouge/compare/v3.20.0...v3.21.0) @@ -35,7 +149,7 @@ - Fix & selector matching in Sass/SCSS lexer ([#1554](https://github.com/rouge-ruby/rouge/pull/1554/) by Michael Camilleri) - SCSS Lexer - Fix & selector matching in Sass/SCSS lexer ([#1554](https://github.com/rouge-ruby/rouge/pull/1554/) by Michael Camilleri) -- SSH Config Lexer +- SSH Config Lexer (**NEW**) - Add SSH config lexer ([#1543](https://github.com/rouge-ruby/rouge/pull/1543/) by Chris Buckley) - Twig Lexer - Fix nesting of raw and verbatim tags in Jinja/Twig lexers ([#1552](https://github.com/rouge-ruby/rouge/pull/1552/) by Michael Camilleri) diff -Nru ruby-rouge-3.21.0/debian/changelog ruby-rouge-3.26.1/debian/changelog --- ruby-rouge-3.21.0/debian/changelog 2020-07-22 10:17:01.000000000 +0000 +++ ruby-rouge-3.26.1/debian/changelog 2021-09-22 20:04:47.000000000 +0000 @@ -1,3 +1,29 @@ +ruby-rouge (3.26.1-1) unstable; urgency=medium + + * New upstream release. + * d/control (Standards-Version): Bump to 4.6.0 without further changes. + * d/copyright (Copyright): Update. + + -- Daniel Leidert Wed, 22 Sep 2021 22:04:47 +0200 + +ruby-rouge (3.26.0-1) unstable; urgency=medium + + * Team upload. + * New upstream release. + * d/control: Add Breaks against versions of jekyll, ruby-kramdown, and + asciidoctor affected by the rewrite of the PHP lexer (closes: #971841). + (Standards-Version): Bump to 4.5.1 without further changes. + * d/copyright (Copyright): Fix author's name and update team's copyright. + * d/rules: Enable gem installation layout. + (override_dh_auto_install): Fix path to demos. + * d/TODO: Remove item related to enabling tests (done in 3.17.0-1). + * d/patches/*.patch: Update patches. + * d/patches/0006-Fix-tests-and-disable-bundler.patch: Add patch. + - Drop bundler usage to fix tests. + * d/patches/series: Enable new patch. + + -- Daniel Leidert Fri, 10 Sep 2021 01:25:34 +0200 + ruby-rouge (3.21.0-1) unstable; urgency=medium * Team upload diff -Nru ruby-rouge-3.21.0/debian/control ruby-rouge-3.26.1/debian/control --- ruby-rouge-3.21.0/debian/control 2020-07-22 10:17:01.000000000 +0000 +++ ruby-rouge-3.26.1/debian/control 2021-09-22 20:04:47.000000000 +0000 @@ -9,7 +9,7 @@ ruby-bundler, ruby-minitest-power-assert, ruby-sinatra -Standards-Version: 4.5.0 +Standards-Version: 4.6.0 Vcs-Git: https://salsa.debian.org/ruby-team/ruby-rouge.git Vcs-Browser: https://salsa.debian.org/ruby-team/ruby-rouge Homepage: http://rouge.jneen.net/ @@ -23,6 +23,9 @@ Depends: ${misc:Depends}, ${ruby:Depends}, ${shlibs:Depends} +Breaks: asciidoctor (<< 2.0.12-3~), + jekyll (<< 3.9.0+dfsg-2~), + ruby-kramdown (<< 2.3.1-1~) Description: pure-Ruby syntax highlighter compatible with pygments Rouge is a pure-Ruby syntax highlighter. It can highlight over 60 languages, and output HTML or ANSI 256-color text. Its HTML output is diff -Nru ruby-rouge-3.21.0/debian/copyright ruby-rouge-3.26.1/debian/copyright --- ruby-rouge-3.21.0/debian/copyright 2020-07-22 10:17:01.000000000 +0000 +++ ruby-rouge-3.26.1/debian/copyright 2021-09-22 20:04:47.000000000 +0000 @@ -1,15 +1,15 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: rouge -Source: https://github.com/jneen/rouge Upstream-Contact: https://github.com/rouge-ruby/rouge/issues +Source: https://github.com/jneen/rouge Files: * -Copyright: 2012 Jay Adkisson +Copyright: 2012 Jeanine Adkisson License: Expat Files: debian/* Copyright: 2014-2017 Youhei SASAKI - 2015-2019, Debian Ruby Extras Maintainers + 2015-2021 Debian Ruby Extras Maintainers License: Expat Comment: The Debian packaging is licensed under the same terms as the source. diff -Nru ruby-rouge-3.21.0/debian/patches/0001_Fix_PATH_rougify.patch ruby-rouge-3.26.1/debian/patches/0001_Fix_PATH_rougify.patch --- ruby-rouge-3.21.0/debian/patches/0001_Fix_PATH_rougify.patch 2020-07-22 10:17:01.000000000 +0000 +++ ruby-rouge-3.26.1/debian/patches/0001_Fix_PATH_rougify.patch 2021-09-22 20:04:47.000000000 +0000 @@ -1,11 +1,14 @@ -From: =?utf-8?q?C=C3=A9dric_Boutillier?= +From: Cédric Boutillier Date: Mon, 20 Jul 2015 07:13:23 +0200 Subject: Fix PATH: rougify +Forwarded: not-needed --- bin/rougify | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) +diff --git a/bin/rougify b/bin/rougify +index 13f2b10..eaf68eb 100755 --- a/bin/rougify +++ b/bin/rougify @@ -2,9 +2,8 @@ diff -Nru ruby-rouge-3.21.0/debian/patches/0002_Fix_location_of_demo.path ruby-rouge-3.26.1/debian/patches/0002_Fix_location_of_demo.path --- ruby-rouge-3.21.0/debian/patches/0002_Fix_location_of_demo.path 2020-07-22 10:17:01.000000000 +0000 +++ ruby-rouge-3.26.1/debian/patches/0002_Fix_location_of_demo.path 2021-09-22 20:04:47.000000000 +0000 @@ -9,10 +9,10 @@ 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/rouge/lexer.rb b/lib/rouge/lexer.rb -index 703c5e6..4fcc6f3 100644 +index d2f0888..a6ff74d 100644 --- a/lib/rouge/lexer.rb +++ b/lib/rouge/lexer.rb -@@ -117,7 +117,11 @@ module Rouge +@@ -127,7 +127,11 @@ module Rouge def demo_file(arg=:absent) return @demo_file = Pathname.new(arg) unless arg == :absent diff -Nru ruby-rouge-3.21.0/debian/patches/0003-Fix-perl-demo-shebang.patch ruby-rouge-3.26.1/debian/patches/0003-Fix-perl-demo-shebang.patch --- ruby-rouge-3.21.0/debian/patches/0003-Fix-perl-demo-shebang.patch 2020-07-22 10:17:01.000000000 +0000 +++ ruby-rouge-3.26.1/debian/patches/0003-Fix-perl-demo-shebang.patch 2021-09-22 20:04:47.000000000 +0000 @@ -2,6 +2,8 @@ Date: Thu, 18 Jul 2019 16:52:37 +0200 Subject: Fix perl demo shebang policy violation +Forwarded: not-needed + Last-Updated: 2019-01-04 --- lib/rouge/demos/perl | 2 +- diff -Nru ruby-rouge-3.21.0/debian/patches/0004-Disable-all-non-essential-gems.patch ruby-rouge-3.26.1/debian/patches/0004-Disable-all-non-essential-gems.patch --- ruby-rouge-3.21.0/debian/patches/0004-Disable-all-non-essential-gems.patch 2020-07-22 10:17:01.000000000 +0000 +++ ruby-rouge-3.26.1/debian/patches/0004-Disable-all-non-essential-gems.patch 2021-09-22 20:04:47.000000000 +0000 @@ -8,11 +8,11 @@ 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Gemfile b/Gemfile -index 12095db..fc2ee41 100644 +index 0669849..3e6bedb 100644 --- a/Gemfile +++ b/Gemfile -@@ -10,25 +10,25 @@ gem 'minitest', '>= 5.0' - gem 'minitest-power_assert' +@@ -11,25 +11,25 @@ gem 'minitest-power_assert' + gem 'power_assert', '~> 1.2' gem 'parallel', '~> 1.13.0' if RUBY_VERSION < '2.2.0' -gem 'rubocop', '~> 0.49.1' @@ -44,7 +44,7 @@ # for visual tests if RUBY_VERSION < '2.2.0' -@@ -36,5 +36,5 @@ group :development do +@@ -37,5 +37,5 @@ group :development do else gem 'sinatra' end diff -Nru ruby-rouge-3.21.0/debian/patches/0005-Fix-gemspec-requiring-lib.patch ruby-rouge-3.26.1/debian/patches/0005-Fix-gemspec-requiring-lib.patch --- ruby-rouge-3.21.0/debian/patches/0005-Fix-gemspec-requiring-lib.patch 2020-07-22 10:17:01.000000000 +0000 +++ ruby-rouge-3.26.1/debian/patches/0005-Fix-gemspec-requiring-lib.patch 2021-09-22 20:04:47.000000000 +0000 @@ -2,6 +2,7 @@ Date: Fri, 3 Apr 2020 03:41:28 +0200 Subject: Fix gemspec requiring lib +Forwarded: not-needed --- rouge.gemspec | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff -Nru ruby-rouge-3.21.0/debian/patches/0006-Fix-tests-and-disable-bundler.patch ruby-rouge-3.26.1/debian/patches/0006-Fix-tests-and-disable-bundler.patch --- ruby-rouge-3.21.0/debian/patches/0006-Fix-tests-and-disable-bundler.patch 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/debian/patches/0006-Fix-tests-and-disable-bundler.patch 2021-09-22 20:04:47.000000000 +0000 @@ -0,0 +1,27 @@ +From: Daniel Leidert +Date: Fri, 10 Sep 2021 00:26:04 +0200 +Subject: Fix tests and disable bundler + +Forwarded: not-needed +--- + spec/spec_helper.rb | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb +index f0d65c7..ecbfec5 100644 +--- a/spec/spec_helper.rb ++++ b/spec/spec_helper.rb +@@ -1,12 +1,10 @@ + # -*- coding: utf-8 -*- # + # frozen_string_literal: true + +-require 'rubygems' +-require 'bundler' +-Bundler.require + require 'rouge' + require 'minitest/spec' + require 'minitest/autorun' ++require 'minitest/power_assert' + + Token = Rouge::Token + diff -Nru ruby-rouge-3.21.0/debian/patches/series ruby-rouge-3.26.1/debian/patches/series --- ruby-rouge-3.21.0/debian/patches/series 2020-07-22 10:17:01.000000000 +0000 +++ ruby-rouge-3.26.1/debian/patches/series 2021-09-22 20:04:47.000000000 +0000 @@ -3,3 +3,4 @@ 0003-Fix-perl-demo-shebang.patch 0004-Disable-all-non-essential-gems.patch 0005-Fix-gemspec-requiring-lib.patch +0006-Fix-tests-and-disable-bundler.patch diff -Nru ruby-rouge-3.21.0/debian/rules ruby-rouge-3.26.1/debian/rules --- ruby-rouge-3.21.0/debian/rules 2020-07-22 10:17:01.000000000 +0000 +++ ruby-rouge-3.26.1/debian/rules 2021-09-22 20:04:47.000000000 +0000 @@ -1,6 +1,7 @@ #!/usr/bin/make -f export GEM2DEB_TEST_RUNNER = --check-dependencies +export DH_RUBY = --gem-install %: dh $@ --buildsystem=ruby --with ruby @@ -8,4 +9,4 @@ override_dh_auto_install: dh_install lib/rouge/demos /usr/share/ruby-rouge dh_auto_install - rm -rf debian/ruby-rouge/usr/lib/ruby/vendor_ruby/rouge/demos + rm -rf debian/ruby-rouge/usr/share/rubygems-integration/all/gems/rouge-*/lib/rouge/demos/ diff -Nru ruby-rouge-3.21.0/debian/TODO ruby-rouge-3.26.1/debian/TODO --- ruby-rouge-3.21.0/debian/TODO 2020-07-22 10:17:01.000000000 +0000 +++ ruby-rouge-3.26.1/debian/TODO 2021-09-22 20:04:47.000000000 +0000 @@ -1,6 +1,2 @@ -* enable the tests: - requires the packaging of the 'wrong' gem, which needs the 'predicated' gem * automate the creation of the rougify manpage use help2man in the override_dh_installman target of debian/rules - - diff -Nru ruby-rouge-3.21.0/docs/DevEnvironment.md ruby-rouge-3.26.1/docs/DevEnvironment.md --- ruby-rouge-3.21.0/docs/DevEnvironment.md 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/docs/DevEnvironment.md 2021-09-17 19:59:49.000000000 +0000 @@ -127,13 +127,15 @@ you're at the top level of your clone of your repository and type: ```shell -bundle install --path vendor +bundle config set path 'vendor' +bundle install ``` -This command tells Bundler to install the gems in the Gemfile into a directory -called `vendor/`. This has one drawback (explained below) but means the gems we -use for Rouge are isolated from the other gems we may have installed on our -system. This will be tremendously helpful in avoiding conflicts that arise +This first command tells Bundler to register the directory `vendor/` as +the project-specific install location for dependencies, and the second command +installs all dependencies. This has one drawback (explained below) but means the +gems we use for Rouge are isolated from the other gems we may have installed on +our system. This will be tremendously helpful in avoiding conflicts that arise because of the use of incompatible versions of a gem. The one drawback is that we will need to tell Ruby every time we run our Rouge diff -Nru ruby-rouge-3.21.0/Gemfile ruby-rouge-3.26.1/Gemfile --- ruby-rouge-3.21.0/Gemfile 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/Gemfile 2021-09-17 19:59:49.000000000 +0000 @@ -8,6 +8,7 @@ gem 'minitest', '>= 5.0' gem 'minitest-power_assert' +gem 'power_assert', '~> 1.2' gem 'parallel', '~> 1.13.0' if RUBY_VERSION < '2.2.0' gem 'rubocop', '~> 0.49.1' diff -Nru ruby-rouge-3.21.0/lib/rouge/cli.rb ruby-rouge-3.26.1/lib/rouge/cli.rb --- ruby-rouge-3.21.0/lib/rouge/cli.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/cli.rb 2021-09-17 19:59:49.000000000 +0000 @@ -44,6 +44,7 @@ yield %|| yield %|where is one of:| yield %| highlight #{Highlight.desc}| + yield %| debug #{Debug.desc}| yield %| help #{Help.desc}| yield %| style #{Style.desc}| yield %| list #{List.desc}| @@ -104,6 +105,8 @@ Help when 'highlight', 'hi' Highlight + when 'debug' + Debug when 'style' Style when 'list' @@ -215,7 +218,7 @@ end end - def self.parse(argv) + def self.parse_opts(argv) opts = { :formatter => supports_truecolor? ? 'terminal-truecolor' : 'terminal256', :theme => 'thankful_eyes', @@ -256,7 +259,11 @@ end end - new(opts) + opts + end + + def self.parse(argv) + new(parse_opts(argv)) end def input_stream @@ -344,6 +351,29 @@ end end + class Debug < Highlight + def self.desc + end + + def self.doc + return enum_for(:doc) unless block_given? + + yield %|usage: rougify debug []| + yield %|| + yield %|Debug a lexer. Similar options to `rougify highlight`, but| + yield %|defaults to the `null` formatter, and ensures the `debug`| + yield %|option is enabled, to print debugging information to stdout.| + end + + def self.parse_opts(argv) + out = super(argv) + out[:lexer_opts]['debug'] = '1' + out[:formatter] = 'null' + + out + end + end + class Style < CLI def self.desc "print CSS styles" diff -Nru ruby-rouge-3.21.0/lib/rouge/demos/email ruby-rouge-3.26.1/lib/rouge/demos/email --- ruby-rouge-3.21.0/lib/rouge/demos/email 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/demos/email 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,11 @@ +From: Me +To: You +Date: Tue, 21 Jul 2020 15:14:03 +0000 +Subject: A very important message + +> Please investigate. Thank you. + +I have investigated. + +-- +This message is highly confidential and will self-destruct. diff -Nru ruby-rouge-3.21.0/lib/rouge/demos/j ruby-rouge-3.26.1/lib/rouge/demos/j --- ruby-rouge-3.21.0/lib/rouge/demos/j 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/demos/j 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,12 @@ +NB. Procedural programming +fizzbuzz=: monad define + for_i. >:i.y do. + if. 0 = 15 | i do. echo'FizzBuzz' + elseif. 0 = 3 | i do. echo'Fizz' + elseif. 0 = 5 | i do. echo'Buzz' + else. echo i + end. + end. +) +NB. Loopless programming +fizzbuzz=: echo@(, ::] ('Fizz' ; 'Buzz') ;@#~ 0 = 3 5&|)@>:@i. diff -Nru ruby-rouge-3.21.0/lib/rouge/demos/ocl ruby-rouge-3.26.1/lib/rouge/demos/ocl --- ruby-rouge-3.21.0/lib/rouge/demos/ocl 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/demos/ocl 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,4 @@ +context Compagnie::toEuros() : Collection(Real) +body: self.employees->collect(each: Employee| each.salary/ 6.55957) +-- OR +body: self.employees->collect(salary) -> collect(x | x/6.55957) diff -Nru ruby-rouge-3.21.0/lib/rouge/demos/postscript ruby-rouge-3.26.1/lib/rouge/demos/postscript --- ruby-rouge-3.21.0/lib/rouge/demos/postscript 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/demos/postscript 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,9 @@ +%!PS +/Courier % name the desired font +20 selectfont % choose the size in points and establish + % the font as the current one +72 500 moveto % position the current point at + % coordinates 72, 500 (the origin is at the + % lower-left corner of the page) +(Hello world!) show % stroke the text in parentheses +showpage % print all on the page diff -Nru ruby-rouge-3.21.0/lib/rouge/demos/rescript ruby-rouge-3.26.1/lib/rouge/demos/rescript --- ruby-rouge-3.21.0/lib/rouge/demos/rescript 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/demos/rescript 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,26 @@ +module Person = { + type t = Teacher | Director | Student(string) + + let greeting = person => + switch person { + | Teacher => "Hey Professor!" + | Director => "Hello Director." + | Student("Richard") => "Still here Ricky?" + | Student(other) => "Hey, " ++ other ++ "." + } +} + +module Button = { + @react.component + let make = (~count: int, ~onClick) => { + let times = switch count { + | 1 => "once" + | 2 => "twice" + | n => Belt.Int.toString(n) ++ " times" + } + + let msg = "Click me " ++ times + + + } +} diff -Nru ruby-rouge-3.21.0/lib/rouge/demos/systemd ruby-rouge-3.26.1/lib/rouge/demos/systemd --- ruby-rouge-3.21.0/lib/rouge/demos/systemd 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/demos/systemd 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,4 @@ +[Unit] +Description=Snap Daemon +Requires=snapd.socket +OnFailure=snapd.failure.service diff -Nru ruby-rouge-3.21.0/lib/rouge/formatter.rb ruby-rouge-3.26.1/lib/rouge/formatter.rb --- ruby-rouge-3.21.0/lib/rouge/formatter.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/formatter.rb 2021-09-17 19:59:49.000000000 +0000 @@ -42,8 +42,8 @@ end # Format a token stream. Delegates to {#format}. - def self.format(tokens, *a, &b) - new(*a).format(tokens, &b) + def self.format(tokens, *args, **kwargs, &b) + new(*args, **kwargs).format(tokens, &b) end def initialize(opts={}) diff -Nru ruby-rouge-3.21.0/lib/rouge/formatters/html_line_highlighter.rb ruby-rouge-3.26.1/lib/rouge/formatters/html_line_highlighter.rb --- ruby-rouge-3.21.0/lib/rouge/formatters/html_line_highlighter.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/formatters/html_line_highlighter.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +module Rouge + module Formatters + class HTMLLineHighlighter < Formatter + tag 'html_line_highlighter' + + def initialize(delegate, opts = {}) + @delegate = delegate + @highlight_line_class = opts.fetch(:highlight_line_class, 'hll') + @highlight_lines = opts[:highlight_lines] || [] + end + + def stream(tokens) + token_lines(tokens).with_index(1) do |line_tokens, lineno| + line = %(#{@delegate.format(line_tokens)}\n) + line = %(#{line}) if @highlight_lines.include? lineno + yield line + end + end + end + end +end diff -Nru ruby-rouge-3.21.0/lib/rouge/formatters/html_line_table.rb ruby-rouge-3.26.1/lib/rouge/formatters/html_line_table.rb --- ruby-rouge-3.21.0/lib/rouge/formatters/html_line_table.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/formatters/html_line_table.rb 2021-09-17 19:59:49.000000000 +0000 @@ -32,10 +32,8 @@ end def stream(tokens, &b) - lineno = @start_line - 1 buffer = [%()] - token_lines(tokens) do |line_tokens| - lineno += 1 + token_lines(tokens).with_index(@start_line) do |line_tokens, lineno| buffer << %() buffer << %(
) + token_lines(tokens).with_index(1) do |line_tokens, lineno| + yield %(<#{@tag_name} class="#{sprintf @class_format, lineno}">) @formatter.stream(line_tokens) {|formatted| yield formatted } yield %(\n) end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexer.rb ruby-rouge-3.26.1/lib/rouge/lexer.rb --- ruby-rouge-3.21.0/lib/rouge/lexer.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexer.rb 2021-09-17 19:59:49.000000000 +0000 @@ -38,28 +38,15 @@ registry[name.to_s] end - # Find a lexer, with fancy shiny features. - # - # * The string you pass can include CGI-style options - # - # Lexer.find_fancy('erb?parent=tex') - # - # * You can pass the special name 'guess' so we guess for you, - # and you can pass a second argument of the code to guess by - # - # Lexer.find_fancy('guess', "#!/bin/bash\necho Hello, world") + # Same as ::find_fancy, except instead of returning an instantiated + # lexer, returns a pair of [lexer_class, options], so that you can + # modify or provide additional options to the lexer. # - # If the code matches more than one lexer then Guesser::Ambiguous - # is raised. - # - # This is used in the Redcarpet plugin as well as Rouge's own - # markdown lexer for highlighting internal code blocks. - # - def find_fancy(str, code=nil, additional_options={}) - + # Please note: the lexer class might be nil! + def lookup_fancy(str, code=nil, default_options={}) if str && !str.include?('?') && str != 'guess' lexer_class = find(str) - return lexer_class && lexer_class.new(additional_options) + return [lexer_class, default_options] end name, opts = str ? str.split('?', 2) : [nil, ''] @@ -75,7 +62,7 @@ [ k.to_s, val ] end - opts = additional_options.merge(Hash[opts]) + opts = default_options.merge(Hash[opts]) lexer_class = case name when 'guess', nil @@ -84,6 +71,29 @@ self.find(name) end + [lexer_class, opts] + end + + # Find a lexer, with fancy shiny features. + # + # * The string you pass can include CGI-style options + # + # Lexer.find_fancy('erb?parent=tex') + # + # * You can pass the special name 'guess' so we guess for you, + # and you can pass a second argument of the code to guess by + # + # Lexer.find_fancy('guess', "#!/bin/bash\necho Hello, world") + # + # If the code matches more than one lexer then Guesser::Ambiguous + # is raised. + # + # This is used in the Redcarpet plugin as well as Rouge's own + # markdown lexer for highlighting internal code blocks. + # + def find_fancy(str, code=nil, default_options={}) + lexer_class, opts = lookup_fancy(str, code, default_options) + lexer_class && lexer_class.new(opts) end @@ -317,6 +327,14 @@ @debug = Lexer.debug_enabled? && bool_option('debug') end + # Returns a new lexer with the given options set. Useful for e.g. setting + # debug flags post hoc, or providing global overrides for certain options + def with(opts={}) + new_options = @options.dup + opts.each { |k, v| new_options[k.to_s] = v } + self.class.new(new_options) + end + def as_bool(val) case val when nil, false, 0, '0', 'false', 'off' diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/apex.rb ruby-rouge-3.26.1/lib/rouge/lexers/apex.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/apex.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/apex.rb 2021-09-17 19:59:49.000000000 +0000 @@ -49,7 +49,7 @@ state :root do rule %r/\s+/m, Text - + rule %r(//.*?$), Comment::Single rule %r(/\*.*?\*/)m, Comment::Multiline @@ -57,17 +57,19 @@ rule %r/import\b/, Keyword::Namespace, :import rule %r/([@$.]?)(#{id})([:(]?)/io do |m| - if self.class.keywords.include? m[0].downcase + lowercased = m[0].downcase + uppercased = m[0].upcase + if self.class.keywords.include? lowercased token Keyword - elsif self.class.soql.include? m[0].upcase + elsif self.class.soql.include? uppercased token Keyword - elsif self.class.declarations.include? m[0].downcase + elsif self.class.declarations.include? lowercased token Keyword::Declaration - elsif self.class.types.include? m[0].downcase + elsif self.class.types.include? lowercased token Keyword::Type - elsif self.class.constants.include? m[0].downcase + elsif self.class.constants.include? lowercased token Keyword::Constant - elsif 'package'.casecmp m[0] + elsif lowercased == 'package' token Keyword::Namespace elsif m[1] == "@" token Name::Decorator diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/batchfile.rb ruby-rouge-3.26.1/lib/rouge/lexers/batchfile.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/batchfile.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/batchfile.rb 2021-09-17 19:59:49.000000000 +0000 @@ -79,6 +79,7 @@ state :basic do # Comments rule %r/@?\brem\b.*$/i, Comment + # Empty Labels rule %r/^::.*$/, Comment @@ -105,7 +106,7 @@ end end - rule %r/([\/\-+][a-z]+)\s*/i, Name::Attribute + rule %r/((?:[\/\+]|--?)[a-z]+)\s*/i, Name::Attribute mixin :expansions diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/cmake.rb ruby-rouge-3.26.1/lib/rouge/lexers/cmake.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/cmake.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/cmake.rb 2021-09-17 19:59:49.000000000 +0000 @@ -22,6 +22,7 @@ } BUILTIN_COMMANDS = Set.new %w[ + add_compile_definitions add_compile_options add_custom_command add_custom_target @@ -29,6 +30,7 @@ add_dependencies add_executable add_library + add_link_options add_subdirectory add_test aux_source_directory @@ -36,7 +38,9 @@ build_command build_name cmake_host_system_information + cmake_language cmake_minimum_required + cmake_parse_arguments cmake_policy configure_file create_test_sourcelist @@ -74,6 +78,7 @@ include include_directories include_external_msproject + include_guard include_regular_expression install install_files @@ -110,9 +115,14 @@ subdir_depends subdirs target_compile_definitions + target_compile_features target_compile_options target_include_directories + target_link_directories target_link_libraries + target_link_options + target_precompile_headers + target_sources try_compile try_run unset diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/cpp.rb ruby-rouge-3.26.1/lib/rouge/lexers/cpp.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/cpp.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/cpp.rb 2021-09-17 19:59:49.000000000 +0000 @@ -59,11 +59,11 @@ prepend :statements do rule %r/(class|struct)\b/, Keyword, :classname rule %r/template\b/, Keyword, :template - rule %r/\d+(\.\d+)?(?:h|(?:min)|s|(?:ms)|(?:us)|(?:ns))/, Num::Other + rule %r/#{dq}(\.#{dq})?(?:y|d|h|(?:min)|s|(?:ms)|(?:us)|(?:ns)|i|(?:if)|(?:il))\b/, Num::Other rule %r((#{dq}[.]#{dq}?|[.]#{dq})(e[+-]?#{dq}[lu]*)?)i, Num::Float rule %r(#{dq}e[+-]?#{dq}[lu]*)i, Num::Float rule %r/0x\h('?\h)*[lu]*/i, Num::Hex - rule %r/0b[01]+(?:_[01]+)*/, Num::Bin + rule %r/0b[01]+('[01]+)*/, Num::Bin rule %r/0[0-7]('?[0-7])*[lu]*/i, Num::Oct rule %r/#{dq}[lu]*/i, Num::Integer rule %r/\bnullptr\b/, Name::Builtin diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/crystal.rb ruby-rouge-3.26.1/lib/rouge/lexers/crystal.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/crystal.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/crystal.rb 2021-09-17 19:59:49.000000000 +0000 @@ -25,8 +25,7 @@ )xi, Str::Symbol # special symbols - rule %r(:(?:\*\*|[-+]@|[/\%&\|^`~]|\[\]=?|<<|>>|<=?>|<=?|===?)), - Str::Symbol + rule %r(:(?:===|=?~|\[\][=?]?|\*\*=?|\/\/=?|[=^*/+-]=?|&[&*+-]?=?|\|\|?=?|![=~]?|%=?|<=>|<>?=?|\.\.\.?)), Str::Symbol rule %r/:'(\\\\|\\'|[^'])*'/, Str::Symbol rule %r/:"/, Str::Symbol, :simple_sym @@ -36,7 +35,7 @@ # %-sigiled strings # %(abc), %[abc], %, %.abc., %r.abc., etc delimiter_map = { '{' => '}', '[' => ']', '(' => ')', '<' => '>' } - rule %r/%([rqswQWxiI])?([^\w\s])/ do |m| + rule %r/%([rqswQWxiI])?([^\w\s}])/ do |m| open = Regexp.escape(m[2]) close = Regexp.escape(delimiter_map[m[2]] || m[2]) interp = /[rQWxI]/ === m[1] @@ -79,9 +78,11 @@ state :strings do mixin :symbols rule %r/\b[a-z_]\w*?[?!]?:\s+/, Str::Symbol, :expr_start - rule %r/'(\\\\|\\'|[^'])*'/, Str::Single rule %r/"/, Str::Double, :simple_string rule %r/(?>?|>=|<=|<=>|=~|={3}|!~|&&?|\|\||\./, + rule %r/\*\*|\/\/|>=|<=|<=>|<>?|=~|={3}|!~|&&?|\|\||\./, Operator, :expr_start + rule %r/{%|%}/, Punctuation rule %r/[-+\/*%=<>&!^|~]=?/, Operator, :expr_start rule(/[?]/) { token Punctuation; push :ternary; push :expr_start } rule %r<[\[({,:\\;/]>, Punctuation, :expr_start @@ -346,6 +350,7 @@ mixin :string_intp rule %r/\\([\\abefnrstv#"']|x[a-fA-F0-9]{1,2}|[0-7]{1,3})/, Str::Escape + rule %r/\\u([a-fA-F0-9]{4}|\{[^}]+\})/, Str::Escape rule %r/\\./, Str::Escape end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/docker.rb ruby-rouge-3.26.1/lib/rouge/lexers/docker.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/docker.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/docker.rb 2021-09-17 19:59:49.000000000 +0000 @@ -7,7 +7,7 @@ title "Docker" desc "Dockerfile syntax" tag 'docker' - aliases 'dockerfile' + aliases 'dockerfile', 'Dockerfile' filenames 'Dockerfile', '*.Dockerfile', '*.docker' mimetypes 'text/x-dockerfile-config' diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/elm.rb ruby-rouge-3.26.1/lib/rouge/lexers/elm.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/elm.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/elm.rb 2021-09-17 19:59:49.000000000 +0000 @@ -78,13 +78,13 @@ rule %r/"/, Str::Double, :pop! end - # Multiple line string with tripple double quotes, e.g. """ multi """ + # Multiple line string with triple double quotes, e.g. """ multi """ state :multiline_string do - rule %r/\s*"""/, Str, :pop! - rule %r/.*/, Str - rule %r/\s*/, Str + rule %r/\\"/, Str::Escape + rule %r/"""/, Str, :pop! + rule %r/[^"]+/, Str + rule %r/"/, Str end - end end end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/email.rb ruby-rouge-3.26.1/lib/rouge/lexers/email.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/email.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/email.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +module Rouge + module Lexers + class Email < RegexLexer + tag 'email' + aliases 'eml', 'e-mail' + filenames '*.eml' + mimetypes 'message/rfc822' + + title "Email" + desc "An email message" + + start do + push :fields + end + + state :fields do + rule %r/[:]/, Operator, :field_body + rule %r/[^\n\r:]+/, Name::Tag + rule %r/[\n\r]/, Name::Tag + end + + state :field_body do + rule(/(\r?\n){2}/) { token Text; pop!(2) } + rule %r/\r?\n(?![ \v\t\f])/, Text, :pop! + rule %r/[^\n\r]+/, Name::Attribute + rule %r/[\n\r]/, Name::Attribute + end + + state :root do + rule %r/\n/, Text + rule %r/^>.*/, Comment + rule %r/.+/, Text + end + end + end +end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/factor.rb ruby-rouge-3.26.1/lib/rouge/lexers/factor.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/factor.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/factor.rb 2021-09-17 19:59:49.000000000 +0000 @@ -243,8 +243,8 @@ end # strings - rule %r/"""\s+.*?\s+"""/, Str - rule %r/"(\\.|[^\\])*?"/, Str + rule %r/"(?:\\\\|\\"|[^"])*"/, Str + rule %r/\S+"\s+(?:\\\\|\\"|[^"])*"/, Str rule %r/(CHAR:)(\s+)(\\[\\abfnrstv]*|\S)(?=\s)/, Str::Char # comments diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/ghc_core.rb ruby-rouge-3.26.1/lib/rouge/lexers/ghc_core.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/ghc_core.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/ghc_core.rb 2021-09-17 19:59:49.000000000 +0000 @@ -17,7 +17,7 @@ rule %r/^=====.*=====$/, Generic::Heading # timestamps rule %r/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ UTC$/, Comment::Single - rule %r/^Result size of .+\s*.*}/, Comment::Multiline + rule %r/^Result size of .+\n.+{[^}]*}/, Comment::Multiline rule %r/--.*$/, Comment::Single rule %r/\[/, Comment::Special, :annotation @@ -27,8 +27,9 @@ mixin :function # rest is Text + # TODO: this is really inefficient rule %r/\s/m, Text - rule %r/.*/, Text + rule %r/./, Text end state :expression do diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/graphql.rb ruby-rouge-3.26.1/lib/rouge/lexers/graphql.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/graphql.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/graphql.rb 2021-09-17 19:59:49.000000000 +0000 @@ -20,7 +20,7 @@ end rule %r/\bfragment\b/, Keyword, :fragment_definition - + rule %r/\bscalar\b/, Keyword, :value rule %r/\b(?:type|interface|enum)\b/, Keyword, :type_definition diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/hack.rb ruby-rouge-3.26.1/lib/rouge/lexers/hack.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/hack.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/hack.rb 2021-09-17 19:59:49.000000000 +0000 @@ -32,7 +32,7 @@ ) end - prepend :template do + prepend :root do rule %r/<\?hh(\s*\/\/\s*(strict|decl|partial))?$/, Comment::Preproc, :php end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/http.rb ruby-rouge-3.26.1/lib/rouge/lexers/http.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/http.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/http.rb 2021-09-17 19:59:49.000000000 +0000 @@ -8,16 +8,22 @@ title "HTTP" desc 'http requests and responses' + option :content, "the language for the content (default: auto-detect)" + def self.http_methods @http_methods ||= %w(GET POST PUT DELETE HEAD OPTIONS TRACE PATCH) end def content_lexer + @content_lexer ||= (lexer_option(:content) || guess_content_lexer) + end + + def guess_content_lexer return Lexers::PlainText unless @content_type - @content_lexer ||= Lexer.guess_by_mimetype(@content_type) + Lexer.guess_by_mimetype(@content_type) rescue Lexer::AmbiguousGuess - @content_lexer = Lexers::PlainText + Lexers::PlainText end start { @content_type = 'text/plain' } diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/isbl.rb ruby-rouge-3.26.1/lib/rouge/lexers/isbl.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/isbl.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/isbl.rb 2021-09-17 19:59:49.000000000 +0000 @@ -41,7 +41,7 @@ state :dotted do mixin :whitespace - rule %r/[a-zа-яё_0-9]*/i do |m| + rule %r/[a-zа-яё_0-9]+/i do |m| name = m[0] if self.class.constants.include? name.downcase token Name::Builtin @@ -56,7 +56,7 @@ state :type do mixin :whitespace - rule %r/[a-zа-яё_0-9]*/i do |m| + rule %r/[a-zа-яё_0-9]+/i do |m| name = m[0] if self.class.interfaces.include? name.downcase token Keyword::Type diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/janet.rb ruby-rouge-3.26.1/lib/rouge/lexers/janet.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/janet.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/janet.rb 2021-09-17 19:59:49.000000000 +0000 @@ -114,7 +114,7 @@ end end - punctuation = %r/[_!@$%^&*+=~<>.?\/-]/o + punctuation = %r/[_!$%^&*+=~<>.?\/-]/o symbol = %r/([[:alpha:]]|#{punctuation})([[:word:]]|#{punctuation}|:)*/o state :root do @@ -143,20 +143,19 @@ rule %r/\(/, Punctuation, :function - rule %r/(')([\(\[])/ do + rule %r/(')(@?[(\[{])/ do groups Operator, Punctuation push :quote end - rule %r/(~)([\(\[])/ do + rule %r/(~)(@?[(\[{])/ do groups Operator, Punctuation push :quasiquote end rule %r/[\#~,';\|]/, Operator - rule %r/@?[({\[]/, Punctuation, :push - rule %r/[)}\]]/, Punctuation, :pop! + rule %r/@?[(){}\[\]]/, Punctuation rule symbol, Name end @@ -169,6 +168,8 @@ end state :function do + rule %r/[\)]/, Punctuation, :pop! + rule symbol do |m| case m[0] when "quote" @@ -187,8 +188,9 @@ end state :quote do - rule %r/[\(\[]/, Punctuation, :push - rule symbol, Str::Symbol + rule %r/[(\[{]/, Punctuation, :push + rule %r/[)\]}]/, Punctuation, :pop! + rule symbol, Str::Escape mixin :root end @@ -199,7 +201,6 @@ end rule %r/(\()(\s*)(unquote)(\s+)(\()/ do groups Punctuation, Text, Keyword, Text, Punctuation - push :root push :function end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/javascript.rb ruby-rouge-3.26.1/lib/rouge/lexers/javascript.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/javascript.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/javascript.rb 2021-09-17 19:59:49.000000000 +0000 @@ -162,6 +162,10 @@ push :template_string end + # special case for the safe navigation operator ?. + # so that we don't start detecting a ternary expr + rule %r/[?][.]/, Punctuation + rule %r/[?]/ do token Punctuation push :ternary @@ -265,9 +269,11 @@ # template strings state :template_string do - rule %r/\${/, Punctuation, :template_string_expr + rule %r/[$]{/, Punctuation, :template_string_expr rule %r/`/, Str::Double, :pop! - rule %r/(\\\\|\\[\$`]|[^\$`]|\$(?!{))*/, Str::Double + rule %r/\\[$`]/, Str::Escape + rule %r/[^$`\\]+/, Str::Double + rule %r/[\\$]/, Str::Double end state :template_string_expr do diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/j.rb ruby-rouge-3.26.1/lib/rouge/lexers/j.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/j.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/j.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,244 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +module Rouge + module Lexers + class J < RegexLexer + title 'J' + desc "The J programming language (jsoftware.com)" + tag 'j' + filenames '*.ijs', '*.ijt' + + # For J-specific terms we use, see: + # https://code.jsoftware.com/wiki/Vocabulary/AET + # https://code.jsoftware.com/wiki/Vocabulary/Glossary + + # https://code.jsoftware.com/wiki/Vocabulary/PartsOfSpeech + def self.token_map + @token_map ||= { + noun: Keyword::Constant, + verb: Name::Function, + modifier: Operator, + name: Name, + param: Name::Builtin::Pseudo, + other: Punctuation, + nil => Error, + } + end + + # https://code.jsoftware.com/wiki/NuVoc + def self.inflection_list + @inflection_list ||= ['', '.', ':', '..', '.:', ':.', '::'] + end + + def self.primitive_table + @primitive_table ||= Hash.new([:name]).tap do |h| + { + '()' => [:other], + '=' => [:verb, :other, :other], + '<>+-*%$|,#' => [:verb, :verb, :verb], + '^' => [:verb, :verb, :modifier], + '~"' => [:modifier, :verb, :verb], + '.:@' => [:modifier, :modifier, :modifier], + ';' => [:verb, :modifier, :verb], + '!' => [:verb, :modifier, :modifier], + '/\\' => [:modifier, :modifier, :verb], + '[' => [:verb, nil, :verb], + ']' => [:verb], + '{' => [:verb, :verb, :verb, nil, nil, nil, :verb], + '}' => [:modifier, :verb, :verb, nil, nil, nil, :modifier], + '`' => [:modifier, nil, :modifier], + '&' => [:modifier, :modifier, :modifier, nil, :modifier], + '?' => [:verb, :verb], + 'a' => [:name, :noun, :noun], + 'ACeEIjorv' => [:name, :verb], + 'bdfHMT' => [:name, :modifier], + 'Dt' => [:name, :modifier, :modifier], + 'F' => [:name, :modifier, :modifier, :modifier, :modifier, + :modifier, :modifier], + 'iu' => [:name, :verb, :verb], + 'L' => [:name, :verb, :modifier], + 'mny' => [:param], + 'p' => [:name, :verb, :verb, :verb], + 'qsZ' => [:name, nil, :verb], + 'S' => [:name, nil, :modifier], + 'u' => [:param, :verb, :verb], + 'v' => [:param, :verb], + 'x' => [:param, nil, :verb], + }.each {|k, v| k.each_char {|c| h[c] = v } } + end + end + + def self.primitive(char, inflection) + i = inflection_list.index(inflection) or return Error + token_map[primitive_table[char][i]] + end + + def self.control_words + @control_words ||= Set.new %w( + assert break case catch catchd catcht continue do else elseif end + fcase for if return select throw try while whilst + ) + end + + def self.control_words_id + @control_words_id ||= Set.new %w(for goto label) + end + + state :expr do + rule %r/\s+/, Text + + rule %r'([!-&(-/:-@\[-^`{-~]|[A-Za-z]\b)([.:]*)' do |m| + token J.primitive(m[1], m[2]) + end + + rule %r/(?:\d|_\d?):([.:]*)/ do |m| + token m[1].empty? ? J.token_map[:verb] : Error + end + + rule %r/[\d_][\w.]*([.:]*)/ do |m| + token m[1].empty? ? Num : Error + end + + rule %r/'/, Str::Single, :str + + rule %r/NB\.(?![.:]).*/, Comment::Single + + rule %r/([A-Za-z]\w*)([.:]*)/ do |m| + if m[2] == '.' + word, sep, id = m[1].partition '_' + list = if sep.empty? + J.control_words + elsif not id.empty? + J.control_words_id + end + if list and list.include? word + token Keyword, word + sep + token((word == 'for' ? Name : Name::Label), id) + token Keyword, m[2] + else + token Error + end + else + token m[2].empty? ? Name : Error + end + end + end + + state :str do + rule %r/''/, Str::Escape + rule %r/[^'\n]+/, Str::Single + rule %r/'|$/, Str::Single, :pop! + end + + start do + @note_next = false + end + + state :root do + rule %r/\n/ do + token Text + if @note_next + push :note + @note_next = false + end + end + + # https://code.jsoftware.com/wiki/Vocabulary/com + # https://code.jsoftware.com/wiki/Vocabulary/NounExplicitDefinition + rule %r/ + ([0-4]|13|adverb|conjunction|dyad|monad|noun|verb)([\ \t]+) + (def(?:ine)?\b|:)(?![.:])([\ \t]*) + /x do |m| + groups Keyword::Pseudo, Text, Keyword::Pseudo, Text + @def_body = (m[1] == '0' || m[1] == 'noun') ? :noun : :code + if m[3] == 'define' + # stack: [:root] + # or [:root, ..., :def_next] + pop! if stack.size > 1 + push @def_body + push :def_next # [:root, ..., @def_body, :def_next] + else + push :expl_def + end + end + + rule %r/^([ \t]*)(Note\b(?![.:]))([ \t\r]*)(?!=[.:]|$)/ do + groups Text, Name, Text + @note_next = true + end + + rule %r/[mnuvxy]\b(?![.:])/, Name + mixin :expr + end + + state :def_next do + rule %r/\n/, Text, :pop! + mixin :root + end + + state :expl_def do + rule %r/0\b(?![.:])/ do + token Keyword::Pseudo + # stack: [:root, :expl_def] + # or [:root, ..., :def_next, :expl_def] + pop! if stack.size > 2 + goto @def_body + push :def_next # [:root, ..., @def_body, :def_next] + end + rule %r/'/ do + if @def_body == :noun + token Str::Single + goto :str + else + token Punctuation + goto :q_expr + end + end + rule(//) { pop! } + end + + # `q_expr` lexes the content of a string literal which is a part of an + # explicit definition. + # e.g. dyad def 'x + y' + state :q_expr do + rule %r/''/, Str::Single, :q_str + rule %r/'|$/, Punctuation, :pop! + rule %r/NB\.(?![.:])([^'\n]|'')*/, Comment::Single + mixin :expr + end + + state :q_str do + rule %r/''''/, Str::Escape + rule %r/[^'\n]+/, Str::Single + rule %r/''/, Str::Single, :pop! + rule(/'|$/) { token Punctuation; pop! 2 } + end + + state :note do + mixin :delimiter + rule %r/.+\n?/, Comment::Multiline + end + + state :noun do + mixin :delimiter + rule %r/.+\n?/, Str::Heredoc + end + + state :code do + mixin :delimiter + rule %r/^([ \t]*)(:)([ \t\r]*)$/ do + groups Text, Punctuation, Text + end + mixin :expr + end + + state :delimiter do + rule %r/^([ \t]*)(\))([ \t\r]*$\n?)/ do + groups Text, Punctuation, Text + pop! + end + end + end + end +end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/jsl.rb ruby-rouge-3.26.1/lib/rouge/lexers/jsl.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/jsl.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/jsl.rb 2021-09-17 19:59:49.000000000 +0000 @@ -14,41 +14,52 @@ rule %r/\s+/m, Text::Whitespace rule %r(//.*?$), Comment::Single - rule %r(/\*.*?\*/)m, Comment::Multiline + rule %r'/[*].*?', Comment::Multiline, :comment # multiline block comment # messages - rule %r/(<<)(.*?)(\(|;)/ do |m| - groups Operator, Name::Function, Punctuation - end + rule %r/<\|=:]/, Operator + rule %r/[-+*\/!%&<>\|=:`^]/, Operator rule %r/[\[\](){},;]/, Punctuation end + state :message do + rule %r/\s+/m, Text::Whitespace + rule %r/[a-z_][\w\s'%.\\]*/i, Name::Function + rule %r/[(),;]/, Punctuation, :pop! + rule %r/[&|!=<>]/, Operator, :pop! + end + state :dq do rule %r/\\![btrnNf0\\"]/, Str::Escape rule %r/\\/, Str::Double rule %r/"/, Str::Double, :pop! - rule %r/[^\\"]*/m, Str::Double + rule %r/[^\\"]+/m, Str::Double + end + + state :comment do + rule %r'/[*]', Comment::Multiline, :comment + rule %r'[*]/', Comment::Multiline, :pop! + rule %r'[^/*]+', Comment::Multiline + rule %r'[/*]', Comment::Multiline end end end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/jsonnet.rb ruby-rouge-3.26.1/lib/rouge/lexers/jsonnet.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/jsonnet.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/jsonnet.rb 2021-09-17 19:59:49.000000000 +0000 @@ -126,6 +126,7 @@ state :string do rule %r/\\([\\\/bfnrt]|(u[0-9a-fA-F]{4}))/, Str::Escape + rule %r/\\./, Str::Escape end state :string_double do @@ -137,15 +138,15 @@ state :string_single do mixin :string - rule %r/\\'/, Str::Escape rule %r/'/, Str, :pop! rule %r/[^\\']+/, Str end state :string_block do mixin :string - rule %r/\|\|\|/, Str, :pop! - rule %r/.*/, Str + rule %r/[|][|][|]/, Str, :pop! + rule %r/[^|\\]+/, Str + rule %r/[|]/, Str end end end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/jsp.rb ruby-rouge-3.26.1/lib/rouge/lexers/jsp.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/jsp.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/jsp.rb 2021-09-17 19:59:49.000000000 +0000 @@ -112,9 +112,8 @@ state :jsp_interp_literal_start do rule %r/'/, Literal, :pop! - rule %r/[^']*/, Literal + rule %r/[^']+/, Literal end - end end -end \ No newline at end of file +end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/kotlin.rb ruby-rouge-3.26.1/lib/rouge/lexers/kotlin.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/kotlin.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/kotlin.rb 2021-09-17 19:59:49.000000000 +0000 @@ -53,7 +53,7 @@ groups Keyword::Declaration, Text push :property end - rule %r'(return|continue|break|this|super)(@#{name})?' do + rule %r'(return|continue|break|this|super)(@#{name})?\b' do groups Keyword, Name::Decorator end rule %r'\bfun\b', Keyword @@ -65,6 +65,9 @@ rule %r'/[*].*[*]/', Comment::Multiline # single line block comment rule %r'/[*].*', Comment::Multiline, :comment # multiline block comment rule %r'\n', Text + rule %r'(::)(class)' do + groups Operator, Keyword + end rule %r'::|!!|\?[:.]', Operator rule %r"(\.\.)", Operator # Number literals @@ -130,9 +133,10 @@ end state :comment do - rule %r'\s*/[*].*', Comment::Multiline, :comment - rule %r'.*[*]/', Comment::Multiline, :pop! - rule %r'.*', Comment::Multiline + rule %r'/[*]', Comment::Multiline, :comment + rule %r'[*]/', Comment::Multiline, :pop! + rule %r'[^/*]+', Comment::Multiline + rule %r'[/*]', Comment::Multiline end end end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/ocaml/common.rb ruby-rouge-3.26.1/lib/rouge/lexers/ocaml/common.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/ocaml/common.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/ocaml/common.rb 2021-09-17 19:59:49.000000000 +0000 @@ -3,7 +3,7 @@ module Rouge module Lexers - # shared states with Reasonml + # shared states with Reasonml and ReScript class OCamlCommon < RegexLexer def self.keywords @keywords ||= Set.new %w( diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/ocl.rb ruby-rouge-3.26.1/lib/rouge/lexers/ocl.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/ocl.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/ocl.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,85 @@ +module Rouge + module Lexers + class OCL < RegexLexer + title "OCL" + desc "OMG Object Constraint Language (omg.org/spec/OCL)" + tag 'ocl' + aliases 'OCL' + filenames '*.ocl' + mimetypes 'text/x-ocl' + + def self.keywords + @keywords ||= Set.new %w( + context pre post inv init body def derive if then else endif import + package endpackage let in + ) + end + + def self.keywords_type + @keywords_type ||= Set.new %w( + Boolean Integer UnlimitedNatural Real String OrderedSet Tuple Bag Set + Sequence OclInvalid OclVoid TupleType OclState Collection OclMessage + ) + end + + def self.builtins + @builtins ||= Set.new %w( + self null result true false invalid @pre + ) + end + + def self.operators + @operators ||= Set.new %w( + or xor and not implies + ) + end + + def self.functions + @functions ||= Set.new %w( + oclAsSet oclIsNew oclIsUndefined oclIsInvalid oclAsType oclIsTypeOf + oclIsKindOf oclInState oclType oclLocale hasReturned result + isSignalSent isOperationCallabs floor round max min toString div mod + size substring concat toInteger toReal toUpperCase toLowerCase + indexOf equalsIgnoreCase at characters toBoolean includes excludes + count includesAll excludesAll isEmpty notEmpty sum product + selectByKind selectByType asBag asSequence asOrderedSet asSet flatten + union intersection including excluding symmetricDifferencecount + append prepend insertAt subOrderedSet first last reverse subSequence + any closure collect collectNested exists forAll isUnique iterate one + reject select sortedBy allInstances average conformsTo + ) + end + + state :single_string do + rule %r/\\./, Str::Escape + rule %r/'/, Str::Single, :pop! + rule %r/[^\\']+/, Str::Single + end + + state :root do + rule %r/\s+/m, Text + rule %r/--.*/, Comment::Single + rule %r/\d+/, Num::Integer + rule %r/'/, Str::Single, :single_string + rule %r([->|+*/<>=~!@#%&|?^-]), Operator + rule %r/[;:()\[\],.]/, Punctuation + rule %r/\w[\w\d]*/ do |m| + if self.class.operators.include? m[0] + token Operator + elsif self.class.keywords_type.include? m[0] + token Keyword::Declaration + elsif self.class.keywords.include? m[0] + token Keyword + elsif self.class.builtins.include? m[0] + token Name::Builtin + elsif self.class.functions.include? m[0] + token Name::Function + else + token Name + end + end + end + end + end +end + diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/opentype_feature_file.rb ruby-rouge-3.26.1/lib/rouge/lexers/opentype_feature_file.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/opentype_feature_file.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/opentype_feature_file.rb 2021-09-17 19:59:49.000000000 +0000 @@ -91,7 +91,6 @@ state :strings do rule %r/"/, Str, :pop! rule %r/[^"%\n]+/, Str - rule %r/(\([a-z0-9_]+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?/i, Str end end end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/perl.rb ruby-rouge-3.26.1/lib/rouge/lexers/perl.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/perl.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/perl.rb 2021-09-17 19:59:49.000000000 +0000 @@ -110,9 +110,10 @@ rule %r/(__(END|DATA)__)\b/, Comment::Preproc, :end_part rule %r/\$\^[ADEFHILMOPSTWX]/, Name::Variable::Global - rule %r/\$[\\"'\[\]&`+*.,;=%~?@$!<>(^\|\/-](?!\w)/, Name::Variable::Global + rule %r/\$[\\"'\[\]&`+*.,;=%~?@$!<>(^\|\/_-](?!\w)/, Name::Variable::Global + rule %r/[$@%&*][$@%&*#_]*(?=[a-z{\[;])/i, Name::Variable, :varname + rule %r/[-+\/*%=<>&^\|!\\~]=?/, Operator - rule %r/[$@%#]+/, Name::Variable, :varname rule %r/0_?[0-7]+(_[0-7]+)*/, Num::Oct rule %r/0x[0-9A-Fa-f]+(_[0-9A-Fa-f]+)*/, Num::Hex @@ -159,8 +160,9 @@ state :varname do rule %r/\s+/, Text - rule %r/\{/, Punctuation, :pop! # hash syntax - rule %r/\)|,/, Punctuation, :pop! # arg specifier + rule %r/[{\[]/, Punctuation, :pop! # hash syntax + rule %r/[),]/, Punctuation, :pop! # arg specifier + rule %r/[;]/, Punctuation, :pop! # postfix mixin :name_common end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/php.rb ruby-rouge-3.26.1/lib/rouge/lexers/php.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/php.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/php.rb 2021-09-17 19:59:49.000000000 +0000 @@ -28,6 +28,26 @@ @disabledmodules = list_option(:disabledmodules) end + def self.detect?(text) + return true if text.shebang?('php') + return false if /^<\?hh/ =~ text + return true if /^<\?php/ =~ text + end + + def self.keywords + @keywords ||= Set.new %w( + old_function cfunction + __class__ __dir__ __file__ __function__ __halt_compiler __line__ + __method__ __namespace__ __trait__ abstract and array as break case + catch clone continue declare default die do echo else elseif + enddeclare endfor endforeach endif endswitch endwhile eval exit + extends final finally fn for foreach global goto if implements + include include_once instanceof insteadof isset list new or parent + print private protected public require require_once return self + static switch throw try var while xor yield + ) + end + def self.builtins Kernel::load File.join(Lexers::BASE_DIR, 'php/keywords.rb') builtins @@ -44,188 +64,314 @@ end end - # source: http://php.net/manual/en/language.variables.basics.php - # the given regex is invalid utf8, so... we're using the unicode - # "Letter" property instead. id = /[\p{L}_][\p{L}\p{N}_]*/ - nsid = /#{id}(?:\\#{id})*/ + ns = /(?:#{id}\\)+/ + id_with_ns = /(?:#{ns})?#{id}/ start do case @start_inline when true - push :template push :php - when false - push :template when :guess - # pass + push :start end end - def self.keywords - # (echo parent ; echo self ; sed -nE 's/"((__)?[[:alpha:]_]+(__)?)".*/\1/p' zend_language_scanner.l | tr '[A-Z]' '[a-z]') | sort -u | grep -Fwv -e isset -e unset -e empty -e const -e use -e function -e namespace - # - isset, unset and empty are actually keywords (directly handled by PHP's lexer but let's pretend these are functions, you use them like so) - # - self and parent are kind of keywords, they are not handled by PHP's lexer - # - use, const, namespace and function are handled by specific rules to highlight what's next to the keyword - # - class is also listed here, in addition to the rule below, to handle anonymous classes - @keywords ||= Set.new %w( - old_function cfunction - __class__ __dir__ __file__ __function__ __halt_compiler - __line__ __method__ __namespace__ __trait__ abstract and - array as break callable case catch class clone continue - declare default die do echo else elseif enddeclare - endfor endforeach endif endswitch endwhile eval exit - extends final finally fn for foreach global goto if - implements include include_once instanceof insteadof - interface list new or parent print private protected - public require require_once return self static switch - throw trait try var while xor yield - ) + state :escape do + rule %r/\?>/ do + token Comment::Preproc + reset_stack + end end - def self.detect?(text) - return true if text.shebang?('php') - return false if /^<\?hh/ =~ text - return true if /^<\?php/ =~ text + state :return do + rule(//) { pop! } end - state :root do - # some extremely rough heuristics to decide whether to start inline or not - rule(/\s*(?=<)/m) { delegate parent; push :template } - rule(/[^$]+(?=<\?(php|=))/i) { delegate parent; push :template } - - rule(//) { push :template; push :php } - end + state :start do + # We enter this state if we aren't sure whether the PHP in the text is + # delimited by /, Comment::Preproc, :pop! - # heredocs - rule %r/<<<(["']?)(#{id})\1\n.*?\n\s*\2;?/im, Str::Heredoc - rule %r/\s+/, Text - rule %r/#.*?$/, Comment::Single - rule %r(//.*?$), Comment::Single - rule %r(/\*\*(?!/).*?\*/)m, Comment::Doc - rule %r(/\*.*?\*/)m, Comment::Multiline - - rule %r/(->|::)(\s*)(#{id})/ do - groups Operator, Text, Name::Attribute + state :names do + rule %r/#{id_with_ns}(?=\s*\()/ do |m| + name = m[0].downcase + if self.class.keywords.include? name + token Keyword + elsif self.builtins.include? name + token Name::Builtin + else + token Name::Function + end end - rule %r/(void|\??(int|float|bool|string|iterable|self|callable))\b/i, Keyword::Type - rule %r/[~!%^&*+=\|:.<>\/@-]+/, Operator - rule %r/\?/, Operator - rule %r/[\[\]{}();,]/, Punctuation - rule %r/(class|interface|trait)(\s+)(#{nsid})/i do - groups Keyword::Declaration, Text, Name::Class - end - rule %r/(use)(\s+)(function|const|)(\s*)(#{nsid})/i do - groups Keyword::Namespace, Text, Keyword::Namespace, Text, Name::Namespace - push :use - end - rule %r/(namespace)(\s+)(#{nsid})/i do - groups Keyword::Namespace, Text, Name::Namespace - end - # anonymous functions - rule %r/(function)(\s*)(?=\()/i do - groups Keyword, Text + rule id_with_ns do |m| + name = m[0].downcase + if name == "use" + push :in_use + token Keyword::Namespace + elsif name == "const" + push :in_const + token Keyword + elsif name == "catch" + push :in_catch + token Keyword + elsif %w(public protected private).include? name + push :in_visibility + token Keyword + elsif name == "stdClass" + token Name::Class + elsif self.class.keywords.include? name + token Keyword + elsif m[0] =~ /^__.*?__$/ + token Name::Builtin + elsif m[0] =~ /^(E|PHP)(_[[:upper:]]+)+$/ + token Keyword::Constant + elsif m[0] =~ /(\\|^)[[:upper:]][[[:upper:]][[:digit:]]_]+$/ + token Name::Constant + elsif m[0] =~ /(\\|^)[[:upper:]][[:alnum:]]*?$/ + token Name::Class + else + token Name + end end + end - # named functions - rule %r/(function)(\s+)(&?)(\s*)/i do - groups Keyword, Text, Operator, Text - push :funcname - end + state :operators do + rule %r/[~!%^&*+\|:.<>\/@-]+/, Operator + end - rule %r/(const)(\s+)(#{id})/i do - groups Keyword, Text, Name::Constant - end + state :string do + rule %r/"/, Str::Double, :pop! + rule %r/[^\\{$"]+/, Str::Double + rule %r/\\u\{[0-9a-fA-F]+\}/, Str::Escape + rule %r/\\([efrntv\"$\\]|[0-7]{1,3}|[xX][0-9a-fA-F]{1,2})/, Str::Escape + rule %r/\$#{id}(\[\S+\]|->#{id})?/, Name::Variable - rule %r/stdClass\b/i, Name::Class - rule %r/(true|false|null)\b/i, Keyword::Constant - rule %r/(E|PHP)(_[[:upper:]]+)+\b/, Keyword::Constant - rule %r/\$\{\$+#{id}\}/i, Name::Variable - rule %r/\$+#{id}/i, Name::Variable - rule %r/(yield)([ \n\r\t]+)(from)/i do - groups Keyword, Text, Keyword + rule %r/\{\$\{/, Str::Interpol, :string_interp_double + rule %r/\{(?=\$)/, Str::Interpol, :string_interp_single + rule %r/(\{)(\S+)(\})/ do + groups Str::Interpol, Name::Variable, Str::Interpol end - # may be intercepted for builtin highlighting - rule %r/\\?#{nsid}/i do |m| - name = m[0].downcase + rule %r/[${\\]+/, Str::Double + end - if self.class.keywords.include? name - token Keyword - elsif self.builtins.include? name - token Name::Builtin - else - token Name::Other - end - end + state :string_interp_double do + rule %r/\}\}/, Str::Interpol, :pop! + mixin :php + end + + state :string_interp_single do + rule %r/\}/, Str::Interpol, :pop! + mixin :php + end + + state :values do + # heredocs + rule %r/<<<(["']?)(#{id})\1\n.*?\n\s*\2;?/im, Str::Heredoc + # numbers rule %r/(\d[_\d]*)?\.(\d[_\d]*)?(e[+-]?\d[_\d]*)?/i, Num::Float rule %r/0[0-7][0-7_]*/, Num::Oct rule %r/0b[01][01_]*/i, Num::Bin rule %r/0x[a-f0-9][a-f0-9_]*/i, Num::Hex rule %r/\d[_\d]*/, Num::Integer + + # strings rule %r/'([^'\\]*(?:\\.[^'\\]*)*)'/, Str::Single rule %r/`([^`\\]*(?:\\.[^`\\]*)*)`/, Str::Backtick rule %r/"/, Str::Double, :string - end - state :use do - rule %r/(\s+)(as)(\s+)(#{id})/i do - groups Text, Keyword, Text, Name - :pop! + # functions + rule %r/(function|fn)\b/i do + push :in_function_return + push :in_function_params + push :in_function_name + token Keyword end - rule %r/\\\{/, Operator, :uselist - rule %r/;/, Punctuation, :pop! + + # constants + rule %r/(true|false|null)\b/i, Keyword::Constant + + # objects + rule %r/new\b/i, Keyword, :in_new + end + + state :variables do + rule %r/\$\{\$+#{id}\}/, Name::Variable + rule %r/\$+#{id}/, Name::Variable end - state :uselist do + state :whitespace do rule %r/\s+/, Text - rule %r/,/, Operator - rule %r/\}/, Operator, :pop! - rule %r/(as)(\s+)(#{id})/i do - groups Keyword, Text, Name - end - rule %r/#{id}/, Name::Namespace + rule %r/#.*?$/, Comment::Single + rule %r(//.*?$), Comment::Single + rule %r(/\*\*(?!/).*?\*/)m, Comment::Doc + rule %r(/\*.*?\*/)m, Comment::Multiline end - state :funcname do - rule %r/#{id}/, Name::Function, :pop! + state :root do + rule %r/<\?(php|=)?/i, Comment::Preproc, :php + rule(/.*?(?=<\?)|.*/m) { delegate parent } end - state :string do - rule %r/"/, Str::Double, :pop! - rule %r/[^\\{$"]+/, Str::Double - rule %r/\\u\{[0-9a-fA-F]+\}/, Str::Escape - rule %r/\\([efrntv\"$\\]|[0-7]{1,3}|[xX][0-9a-fA-F]{1,2})/, - Str::Escape - rule %r/\$#{id}(\[\S+\]|->#{id})?/, Name::Variable + state :php do + mixin :escape - rule %r/\{\$\{/, Str::Interpol, :interp_double - rule %r/\{(?=\$)/, Str::Interpol, :interp_single - rule %r/(\{)(\S+)(\})/ do - groups Str::Interpol, Name::Variable, Str::Interpol + mixin :whitespace + mixin :variables + mixin :values + + rule %r/(namespace) + (\s+) + (#{id_with_ns})/ix do |m| + groups Keyword::Namespace, Text, Name::Namespace end - rule %r/[${\\]+/, Str::Double + rule %r/(class|interface|trait|extends|implements) + (\s+) + (#{id_with_ns})/ix do |m| + groups Keyword::Declaration, Text, Name::Class + end + + mixin :names + + rule %r/[;,\(\)\{\}\[\]]/, Punctuation + + mixin :operators + rule %r/[=?]/, Operator end - state :interp_double do - rule %r/\}\}/, Str::Interpol, :pop! + state :in_assign do + rule %r/,/, Punctuation, :pop! + rule %r/[\[\]]/, Punctuation + rule %r/\(/, Punctuation, :in_assign_function + mixin :escape + mixin :whitespace + mixin :values + mixin :variables + mixin :names + mixin :operators + mixin :return + end + + state :in_assign_function do + rule %r/\)/, Punctuation, :pop! + rule %r/,/, Punctuation + mixin :in_assign + end + + state :in_catch do + rule %r/\(/, Punctuation + rule %r/\|/, Operator + rule id, Name::Class + mixin :escape + mixin :whitespace + mixin :return + end + + state :in_const do + rule id, Name::Constant + rule %r/=/, Operator, :in_assign + mixin :escape + mixin :whitespace + mixin :return + end + + state :in_function_body do + rule %r/{/, Punctuation, :push + rule %r/}/, Punctuation, :pop! mixin :php end - state :interp_single do - rule %r/\}/, Str::Interpol, :pop! + state :in_function_name do + rule %r/&/, Operator + rule id, Name + rule %r/\(/, Punctuation, :pop! + mixin :escape + mixin :whitespace + mixin :return + end + + state :in_function_params do + rule %r/\)/, Punctuation, :pop! + rule %r/,/, Punctuation + rule %r/[.]{3}/, Punctuation + rule %r/=/, Operator, :in_assign + rule %r/\??#{id}/, Keyword::Type, :in_assign + mixin :escape + mixin :whitespace + mixin :variables + mixin :return + end + + state :in_function_return do + rule %r/:/, Punctuation + rule %r/use\b/i, Keyword, :in_function_use + rule %r/\??#{id}/, Keyword::Type, :in_assign + rule %r/\{/ do + token Punctuation + goto :in_function_body + end + mixin :escape + mixin :whitespace + mixin :return + end + + state :in_function_use do + rule %r/[,\(]/, Punctuation + rule %r/&/, Operator + rule %r/\)/, Punctuation, :pop! + mixin :escape + mixin :whitespace + mixin :variables + mixin :return + end + + state :in_new do + rule %r/class\b/i do + token Keyword::Declaration + goto :in_new_class + end + rule id_with_ns, Name::Class, :pop! + mixin :escape + mixin :whitespace + mixin :return + end + + state :in_new_class do + rule %r/\}/, Punctuation, :pop! + rule %r/\{/, Punctuation mixin :php end + + state :in_use do + rule %r/[,\}]/, Punctuation + rule %r/(function|const)\b/i, Keyword + rule %r/(#{ns})(\{)/ do + groups Name::Namespace, Punctuation + end + rule %r/#{id_with_ns}(_#{id})+/, Name::Function + mixin :escape + mixin :whitespace + mixin :names + mixin :return + end + + state :in_visibility do + rule %r/(?=(abstract|const|function|static)\b)/i, Keyword, :pop! + rule %r/\??#{id}/, Keyword::Type, :pop! + mixin :escape + mixin :whitespace + mixin :return + end end end end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/postscript.rb ruby-rouge-3.26.1/lib/rouge/lexers/postscript.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/postscript.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/postscript.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +# Adapted from pygments PostScriptLexer +module Rouge + module Lexers + class PostScript < RegexLexer + title "PostScript" + desc "The PostScript language (adobe.com/devnet/postscript.html)" + tag "postscript" + aliases "postscr", "postscript", "ps", "eps" + filenames "*.ps", "*.eps" + mimetypes "application/postscript" + + def self.detect?(text) + return true if /^%!/ =~ text + end + + delimiter = %s"()<>\[\]{}/%\s" + delimiter_end = Regexp.new("(?=[#{delimiter}])") + valid_name_chars = Regexp.new("[^#{delimiter}]") + valid_name = /#{valid_name_chars}+#{delimiter_end}/ + + # These keywords taken from + # + # Is there an authoritative list anywhere that doesn't involve + # trawling documentation? + keywords = %w/abs add aload arc arcn array atan begin + bind ceiling charpath clip closepath concat + concatmatrix copy cos currentlinewidth currentmatrix + currentpoint curveto cvi cvs def defaultmatrix + dict dictstackoverflow div dtransform dup end + exch exec exit exp fill findfont floor get + getinterval grestore gsave identmatrix idiv + idtransform index invertmatrix itransform length + lineto ln load log loop matrix mod moveto + mul neg newpath pathforall pathbbox pop print + pstack put quit rand rangecheck rcurveto repeat + restore rlineto rmoveto roll rotate round run + save scale scalefont setdash setfont setgray + setlinecap setlinejoin setlinewidth setmatrix + setrgbcolor shfill show showpage sin sqrt + stack stringwidth stroke strokepath sub syntaxerror + transform translate truncate typecheck undefined + undefinedfilename undefinedresult/ + + state :root do + # All comment types + rule %r'^%!.+?$', Comment::Preproc + rule %r'%%.*?$', Comment::Special + rule %r'(^%.*?$){2,}', Comment::Multiline + rule %r'%.*?$', Comment::Single + + # String literals are awkward; enter separate state. + rule %r'\(', Str, :stringliteral + + # References + rule %r'/#{valid_name}', Name::Variable + + rule %r'[{}<>\[\]]', Punctuation + + rule %r'(?:#{keywords.join('|')})#{delimiter_end}', Name::Builtin + + # Conditionals / flow control + rule %r'(eq|ne|g[et]|l[et]|and|or|not|if(?:else)?|for(?:all)?)#{delimiter_end}', Keyword::Reserved + rule %r'(false|true)#{delimiter_end}', Keyword::Constant + + # Numbers + rule %r'<[0-9A-Fa-f]+>#{delimiter_end}', Num::Hex + # Slight abuse: use Oct to signify any explicit base system + rule %r'[0-9]+\#(\-|\+)?([0-9]+\.?|[0-9]*\.[0-9]+|[0-9]+\.[0-9]*)((e|E)[0-9]+)?#{delimiter_end}', Num::Oct + rule %r'(\-|\+)?([0-9]+\.?|[0-9]*\.[0-9]+|[0-9]+\.[0-9]*)((e|E)[0-9]+)?#{delimiter_end}', Num::Float + rule %r'(\-|\+)?[0-9]+#{delimiter_end}', Num::Integer + + # Names + rule valid_name, Name::Function # Anything else is executed + + rule %r'\s+', Text + end + + state :stringliteral do + rule %r'[^()\\]+', Str + rule %r'\\', Str::Escape, :escape + rule %r'\(', Str, :stringliteral + rule %r'\)', Str, :pop! + end + + state :escape do + rule %r'[0-8]{3}|n|r|t|b|f|\\|\(|\)', Str::Escape, :pop! + end + end + end +end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/powershell.rb ruby-rouge-3.26.1/lib/rouge/lexers/powershell.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/powershell.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/powershell.rb 2021-09-17 19:59:49.000000000 +0000 @@ -131,34 +131,50 @@ rule %r/[:,]/, Punctuation end - state :hasht do - rule %r/\s+/, Text::Whitespace - rule %r/\}/, Punctuation, :pop! + state :expr do + mixin :comments rule %r/"/, Str::Double, :dq rule %r/'/, Str::Single, :sq - rule %r/\w+/, Name::Other + rule %r/@"/, Str::Heredoc, :heredoc + rule %r/@'.*?'@/m, Str::Heredoc + rule %r/\d*\.\d+/, Num::Float + rule %r/\d+/, Num::Integer + rule %r/@\{/, Punctuation, :hasht + rule %r/@\(/, Punctuation, :array + rule %r/{/, Punctuation, :brace + rule %r/\[/, Punctuation, :bracket + end + + state :hasht do + rule %r/\}/, Punctuation, :pop! rule %r/=/, Operator - rule %r/,/, Punctuation + rule %r/[,;]/, Punctuation + mixin :expr + rule %r/\w+/, Name::Other mixin :variable end state :array do rule %r/\s+/, Text::Whitespace rule %r/\)/, Punctuation, :pop! - rule %r/"/, Str::Double, :dq - rule %r/'/, Str::Single, :sq - rule %r/,/, Punctuation + rule %r/[,;]/, Punctuation + mixin :expr mixin :variable end + state :brace do + rule %r/[}]/, Punctuation, :pop! + mixin :root + end + state :bracket do rule %r/\]/, Punctuation, :pop! - rule %r/[A-Za-z]\w+\./, Name::Constant + rule %r/[A-Za-z]\w+\./, Name rule %r/([A-Za-z]\w+)/ do |m| if ATTRIBUTES.include? m[0] token Name::Builtin::Pseudo else - token Keyword::Type + token Name end end mixin :root @@ -174,20 +190,15 @@ mixin :root end - state :root do + state :comments do rule %r/\s+/, Text::Whitespace - - rule %r/#requires\s-version \d(?:\.\d+)?/, Comment::Preproc rule %r/#.*/, Comment rule %r/<#/, Comment::Multiline, :multiline + end - rule %r/"/, Str::Double, :dq - rule %r/'/, Str::Single, :sq - rule %r/@"/, Str::Heredoc, :heredoc - rule %r/@'.*?'@/m, Str::Heredoc - - rule %r/\d*\.\d+/, Num::Float - rule %r/\d+/, Num::Integer + state :root do + mixin :comments + rule %r/#requires\s-version \d(?:\.\d+)?/, Comment::Preproc rule %r/\.\.(?=\.?\d)/, Operator rule %r/(?:#{OPERATORS})\b/i, Operator @@ -204,28 +215,27 @@ rule %r/-{1,2}\w+/, Name::Tag rule %r/(\.)?([-\w]+)(\[)/ do |m| - groups Operator, Name::Function, Punctuation + groups Operator, Name, Punctuation push :bracket end - rule %r/([\/\\~\w][-.:\/\\~\w]*)(\n)?/ do |m| - groups Name::Function, Text::Whitespace + rule %r/([\/\\~[a-z]][-.:\/\\~\w]*)(\n)?/i do |m| + groups Name, Text::Whitespace push :parameters end - rule %r/(\.)?([-\w]+)(?:(\()|(\n))?/ do |m| + rule %r/(\.)([-\w]+)(?:(\()|(\n))?/ do |m| groups Operator, Name::Function, Punctuation, Text::Whitespace push :parameters unless m[3].nil? end rule %r/\?/, Name::Function, :parameters - rule %r/[-+*\/%=!.&|]/, Operator - rule %r/@\{/, Punctuation, :hasht - rule %r/@\(/, Punctuation, :array - rule %r/\[/, Punctuation, :bracket - rule %r/[{}(),:;]/, Punctuation + mixin :expr mixin :variable + + rule %r/[-+*\/%=!.&|]/, Operator + rule %r/[{}(),:;]/, Punctuation end end end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/python.rb ruby-rouge-3.26.1/lib/rouge/lexers/python.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/python.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/python.rb 2021-09-17 19:59:49.000000000 +0000 @@ -115,7 +115,7 @@ # TODO: not in python 3 rule %r/`.*?`/, Str::Backtick rule %r/([rfbu]{0,2})('''|"""|['"])/i do |m| - token Str + groups Str::Affix, Str current_string.register type: m[1].downcase, delim: m[2] push :generic_string end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/q.rb ruby-rouge-3.26.1/lib/rouge/lexers/q.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/q.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/q.rb 2021-09-17 19:59:49.000000000 +0000 @@ -118,7 +118,7 @@ end state :bottom do - rule %r/.*\z/m, Comment::Multiline + rule %r/.+\z/m, Comment::Multiline end end end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/reasonml.rb ruby-rouge-3.26.1/lib/rouge/lexers/reasonml.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/reasonml.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/reasonml.rb 2021-09-17 19:59:49.000000000 +0000 @@ -24,7 +24,8 @@ rule %r/#{@@upper_id}(?=\s*[.])/, Name::Namespace, :dotted rule %r/`#{@@id}/, Name::Tag rule @@upper_id, Name::Class - rule %r/[\/][*](?![\/])/, Comment, :comment + rule %r(//.*), Comment::Single + rule %r(/\*), Comment::Multiline, :comment rule @@id do |m| match = m[0] if self.class.keywords.include? match @@ -55,10 +56,10 @@ end state :comment do - rule %r|[^/*)]+|, Comment - rule %r|[/][*]|, Comment, :push - rule %r|[*][/]|, Comment, :pop! - rule %r|[*/]|, Comment + rule %r([^/*]+), Comment::Multiline + rule %r(/\*), Comment::Multiline, :comment + rule %r(\*/), Comment::Multiline, :pop! + rule %r([*/]), Comment::Multiline end end end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/rescript.rb ruby-rouge-3.26.1/lib/rouge/lexers/rescript.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/rescript.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/rescript.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +module Rouge + module Lexers + load_lexer 'ocaml/common.rb' + + class ReScript < OCamlCommon + title "ReScript" + desc "The ReScript programming language (rescript-lang.org)" + tag 'rescript' + filenames '*.res', '*.resi' + mimetypes 'text/x-rescript' + + def self.keywords + @keywords ||= Set.new(%w( + open let rec and as exception assert lazy if else + for in to downto while switch when external type private + mutable constraint include module of with try import export + )) + end + + def self.types + @types ||= Set.new(%w( + bool int float char string + unit list array option ref exn format + )) + end + + def self.word_operators + @word_operators ||= Set.new(%w(mod land lor lxor lsl lsr asr or)) + end + + state :root do + rule %r/\s+/m, Text + rule %r([,.:?~\\]), Text + + # Boolean Literal + rule %r/\btrue|false\b/, Keyword::Constant + + # Module chain + rule %r/#{@@upper_id}(?=\s*[.])/, Name::Namespace, :dotted + + # Decorator + rule %r/@#{@@id}(\.#{@@id})*/, Name::Decorator + + # Poly variant + rule %r/\##{@@id}/, Name::Class + + # Variant or Module + rule @@upper_id, Name::Class + + # Comments + rule %r(//.*), Comment::Single + rule %r(/\*), Comment::Multiline, :comment + + # Keywords and identifiers + rule @@id do |m| + match = m[0] + if self.class.keywords.include? match + token Keyword + elsif self.class.word_operators.include? match + token Operator::Word + elsif self.class.types.include? match + token Keyword::Type + else + token Name + end + end + + # Braces + rule %r/[(){}\[\];]+/, Punctuation + + # Operators + rule %r([;_!$%&*+/<=>@^|-]+), Operator + + # Numbers + rule %r/-?\d[\d_]*(.[\d_]*)?(e[+-]?\d[\d_]*)/i, Num::Float + rule %r/0x\h[\h_]*/i, Num::Hex + rule %r/0o[0-7][0-7_]*/i, Num::Oct + rule %r/0b[01][01_]*/i, Num::Bin + rule %r/\d[\d_]*/, Num::Integer + + # String and Char + rule %r/'(?:(\\[\\"'ntbr ])|(\\[0-9]{3})|(\\x\h{2}))'/, Str::Char + rule %r/'[^'\/]'/, Str::Char + rule %r/'/, Keyword + rule %r/"/, Str::Double, :string + + # Interpolated string + rule %r/`/ do + token Str::Double + push :interpolated_string + end + end + + state :comment do + rule %r([^/\*]+), Comment::Multiline + rule %r(/\*), Comment::Multiline, :comment + rule %r(\*/), Comment::Multiline, :pop! + rule %r([*/]), Comment::Multiline + end + + state :interpolated_string do + rule %r/[$]{/, Punctuation, :interpolated_expression + rule %r/`/, Str::Double, :pop! + rule %r/\\[$`]/, Str::Escape + rule %r/[^$`\\]+/, Str::Double + rule %r/[\\$]/, Str::Double + end + + state :interpolated_expression do + rule %r/}/, Punctuation, :pop! + mixin :root + end + + end + end +end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/ruby.rb ruby-rouge-3.26.1/lib/rouge/lexers/ruby.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/ruby.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/ruby.rb 2021-09-17 19:59:49.000000000 +0000 @@ -374,7 +374,7 @@ end state :method_call do - rule %r(/) do + rule %r(/|%) do token Operator goto :expr_start end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/rust.rb ruby-rouge-3.26.1/lib/rouge/lexers/rust.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/rust.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/rust.rb 2021-09-17 19:59:49.000000000 +0000 @@ -22,8 +22,8 @@ def self.keywords @keywords ||= %w( - as assert async await break const copy do drop else enum extern fail false - fn for if impl let log loop match mod move mut priv pub pure + as assert async await break const continue copy do drop else enum extern + fail false fn for if impl let log loop match mod move mut priv pub pure ref return self static struct true trait type unsafe use where while box ) @@ -99,7 +99,9 @@ rule %r/[*\/!@~&+%^<>=\?-]|\.{2,3}/, Operator rule %r/([.]\s*)?#{id}(?=\s*[(])/m, Name::Function + rule %r/[.]\s*await\b/, Keyword rule %r/[.]\s*#{id}/, Name::Property + rule %r/[.]\s*\d+/, Name::Attribute rule %r/(#{id})(::)/m do groups Name::Namespace, Punctuation end @@ -167,7 +169,7 @@ flt = /f32|f64/ rule %r( - [0-9]+ + [0-9_]+ (#{dot} #{exp}? #{flt}? |#{dot}? #{exp} #{flt}? |#{dot}? #{exp}? #{flt} @@ -177,6 +179,7 @@ rule %r( ( 0b[10_]+ | 0x[0-9a-fA-F_]+ + | 0o[0-7]+ | [0-9_]+ ) (u#{size}?|i#{size})? )x, Num::Integer diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/smarty.rb ruby-rouge-3.26.1/lib/rouge/lexers/smarty.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/smarty.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/smarty.rb 2021-09-17 19:59:49.000000000 +0000 @@ -41,7 +41,7 @@ end - rule(/.*?(?={[\/a-zA-Z0-9$#*"'])|.*/m) { delegate parent } + rule(/.+?(?={[\/a-zA-Z0-9$#*"'])/m) { delegate parent } rule(/.+/m) { delegate parent } end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/systemd.rb ruby-rouge-3.26.1/lib/rouge/lexers/systemd.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/systemd.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/systemd.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +module Rouge + module Lexers + class SystemD < RegexLexer + tag 'systemd' + aliases 'unit-file' + filenames '*.service' + mimetypes 'text/x-systemd-unit' + desc 'A lexer for systemd unit files' + + state :root do + rule %r/\s+/, Text + rule %r/[;#].*/, Comment + rule %r/\[.*?\]$/, Keyword + rule %r/(.*?)(=)(.*)(\\\n)/ do + groups Name::Tag, Punctuation, Text, Str::Escape + push :continuation + end + rule %r/(.*?)(=)(.*)/ do + groups Name::Tag, Punctuation, Text + end + end + + state :continuation do + rule %r/(.*?)(\\\n)/ do + groups Text, Str::Escape + end + rule %r/(.*)'/, Text, :pop! + end + end + end +end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/velocity.rb ruby-rouge-3.26.1/lib/rouge/lexers/velocity.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/velocity.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/velocity.rb 2021-09-17 19:59:49.000000000 +0000 @@ -63,7 +63,7 @@ rule %r/0[xX][0-9a-fA-F]+[Ll]?/, Num::Hex rule %r/\b[0-9]+\b/, Num::Integer rule %r/(true|false|null)\b/, Keyword::Constant - rule %r/[(\[]/, Punctuation, :push! + rule %r/[(\[]/, Punctuation, :push rule %r/[)\]}]/, Punctuation, :pop! end end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/wollok.rb ruby-rouge-3.26.1/lib/rouge/lexers/wollok.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/wollok.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/wollok.rb 2021-09-17 19:59:49.000000000 +0000 @@ -18,7 +18,6 @@ state :whitespaces_and_comments do rule %r/\s+/m, Text::Whitespace - rule %r/$+/m, Text::Whitespace rule %r(//.*$), Comment::Single rule %r(/\*(.|\s)*?\*/)m, Comment::Multiline end diff -Nru ruby-rouge-3.21.0/lib/rouge/lexers/yaml.rb ruby-rouge-3.26.1/lib/rouge/lexers/yaml.rb --- ruby-rouge-3.21.0/lib/rouge/lexers/yaml.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/lexers/yaml.rb 2021-09-17 19:59:49.000000000 +0000 @@ -175,7 +175,7 @@ state :block_nodes do # implicit key - rule %r/((?:[\p{L}\p{Nl}\p{Nd}_][\p{L}\p{Nl}\p{Nd}\p{Blank}_-]*)?)(:)(?=\s|$)/ do |m| + rule %r/([^#,:?\[\]{}"'\n]+)(:)(?=\s|$)/ do |m| groups Name::Attribute, Punctuation::Indicator set_indent m[0], :implicit => true end diff -Nru ruby-rouge-3.21.0/lib/rouge/regex_lexer.rb ruby-rouge-3.26.1/lib/rouge/regex_lexer.rb --- ruby-rouge-3.21.0/lib/rouge/regex_lexer.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/regex_lexer.rb 2021-09-17 19:59:49.000000000 +0000 @@ -6,6 +6,37 @@ # A stateful lexer that uses sets of regular expressions to # tokenize a string. Most lexers are instances of RegexLexer. class RegexLexer < Lexer + class InvalidRegex < StandardError + def initialize(re) + @re = re + end + + def to_s + "regex #{@re.inspect} matches empty string, but has no predicate!" + end + end + + class ClosedState < StandardError + attr_reader :state + def initialize(state) + @state = state + end + + def rule + @state.rules.last + end + + def to_s + rule = @state.rules.last + msg = "State :#{state.name} cannot continue after #{rule.inspect}, which will always match." + if rule.re.source.include?('*') + msg += " Consider replacing * with +." + end + + msg + end + end + # A rule is a tuple of a regular expression to test, and a callback # to perform if the test succeeds. # @@ -42,12 +73,13 @@ end class StateDSL - attr_reader :rules + attr_reader :rules, :name def initialize(name, &defn) @name = name @defn = defn @rules = [] @loaded = false + @closed = false end def to_state(lexer_class) @@ -95,10 +127,14 @@ # {RegexLexer#token}, and {RegexLexer#delegate}. The first # argument can be used to access the match groups. def rule(re, tok=nil, next_state=nil, &callback) + raise ClosedState.new(self) if @closed + if tok.nil? && callback.nil? raise "please pass `rule` a token to yield or a callback" end + matches_empty = re =~ '' + callback ||= case next_state when :pop! proc do |stream| @@ -123,6 +159,9 @@ @stack.push(state) end when nil + # cannot use an empty-matching regexp with no predicate + raise InvalidRegex.new(re) if matches_empty + proc do |stream| puts " yielding: #{tok.qualname}, #{stream[0].inspect}" if @debug @output_stream.call(tok, stream[0]) @@ -132,6 +171,22 @@ end rules << Rule.new(re, callback) + + close! if matches_empty && !context_sensitive?(re) + end + + def context_sensitive?(re) + source = re.source + return true if source =~ /[(][?] :base09 style Literal::String, :fg => :base0B + style Literal::String::Affix, :fg => :base0E style Literal::String::Regex, :fg => :base0C style Literal::String::Interpol, diff -Nru ruby-rouge-3.21.0/lib/rouge/themes/bw.rb ruby-rouge-3.26.1/lib/rouge/themes/bw.rb --- ruby-rouge-3.21.0/lib/rouge/themes/bw.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/themes/bw.rb 2021-09-17 19:59:49.000000000 +0000 @@ -26,6 +26,7 @@ style Name::Tag, :bold => true style Literal::String, :italic => true + style Literal::String::Affix, :bold => true style Literal::String::Interpol, :bold => true style Literal::String::Escape, :bold => true diff -Nru ruby-rouge-3.21.0/lib/rouge/themes/colorful.rb ruby-rouge-3.26.1/lib/rouge/themes/colorful.rb --- ruby-rouge-3.21.0/lib/rouge/themes/colorful.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/themes/colorful.rb 2021-09-17 19:59:49.000000000 +0000 @@ -37,6 +37,7 @@ style Name::Decorator, :fg => "#555", :bold => true style Literal::String, :bg => "#fff0f0" + style Literal::String::Affix, :fg => "#080", :bold => true style Literal::String::Char, :fg => "#04D" style Literal::String::Doc, :fg => "#D42" style Literal::String::Interpol, :bg => "#eee" diff -Nru ruby-rouge-3.21.0/lib/rouge/themes/github.rb ruby-rouge-3.26.1/lib/rouge/themes/github.rb --- ruby-rouge-3.21.0/lib/rouge/themes/github.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/themes/github.rb 2021-09-17 19:59:49.000000000 +0000 @@ -35,6 +35,7 @@ style Literal::Number::Integer, :fg => '#009999' style Literal::Number::Oct, :fg => '#009999' style Literal::Number, :fg => '#009999' + style Literal::String::Affix, :fg => '#000000', :bold => true style Literal::String::Backtick, :fg => '#d14' style Literal::String::Char, :fg => '#d14' style Literal::String::Doc, :fg => '#d14' diff -Nru ruby-rouge-3.21.0/lib/rouge/themes/gruvbox.rb ruby-rouge-3.26.1/lib/rouge/themes/gruvbox.rb --- ruby-rouge-3.21.0/lib/rouge/themes/gruvbox.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/themes/gruvbox.rb 2021-09-17 19:59:49.000000000 +0000 @@ -150,6 +150,8 @@ Literal::String::Interpol, Literal::String::Regex, :fg => :green, :italic => true + style Literal::String::Affix, :fg => :red + style Literal::String::Escape, :fg => :orange style Name::Namespace, diff -Nru ruby-rouge-3.21.0/lib/rouge/themes/igor_pro.rb ruby-rouge-3.26.1/lib/rouge/themes/igor_pro.rb --- ruby-rouge-3.21.0/lib/rouge/themes/igor_pro.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/themes/igor_pro.rb 2021-09-17 19:59:49.000000000 +0000 @@ -15,6 +15,7 @@ style Keyword::Reserved, :fg => '#007575' style Keyword, :fg => '#0000FF' style Literal::String, :fg => '#009C00' + style Literal::String::Affix, :fg => '#0000FF' style Name::Builtin, :fg => '#C34E00' end end diff -Nru ruby-rouge-3.21.0/lib/rouge/themes/magritte.rb ruby-rouge-3.26.1/lib/rouge/themes/magritte.rb --- ruby-rouge-3.21.0/lib/rouge/themes/magritte.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/themes/magritte.rb 2021-09-17 19:59:49.000000000 +0000 @@ -62,6 +62,7 @@ Literal::Date, :fg => :forest, :bold => true style Literal::String::Symbol, :fg => :forest style Literal::String, :fg => :wine, :bold => true + style Literal::String::Affix, :fg => :royal, :bold => true style Literal::String::Escape, Literal::String::Char, Literal::String::Interpol, :fg => :purple, :bold => true diff -Nru ruby-rouge-3.21.0/lib/rouge/themes/monokai.rb ruby-rouge-3.26.1/lib/rouge/themes/monokai.rb --- ruby-rouge-3.21.0/lib/rouge/themes/monokai.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/themes/monokai.rb 2021-09-17 19:59:49.000000000 +0000 @@ -59,6 +59,7 @@ Literal::Number::Oct, Literal::Number, Literal::String::Escape, :fg => :light_violet + style Literal::String::Affix, :fg => :soft_cyan, :bold => true style Literal::String::Backtick, Literal::String::Char, Literal::String::Doc, diff -Nru ruby-rouge-3.21.0/lib/rouge/themes/pastie.rb ruby-rouge-3.26.1/lib/rouge/themes/pastie.rb --- ruby-rouge-3.21.0/lib/rouge/themes/pastie.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/themes/pastie.rb 2021-09-17 19:59:49.000000000 +0000 @@ -36,6 +36,7 @@ style Num, :fg => '#0000dd', :bold => true style Str, :fg => '#dd2200', :bg => '#fff0f0' + style Str::Affix, :fg => '#008800', :bold => true style Str::Escape, :fg => '#0044dd', :bg => '#fff0f0' style Str::Interpol, :fg => '#3333bb', :bg => '#fff0f0' style Str::Other, :fg => '#22bb22', :bg => '#f0fff0' diff -Nru ruby-rouge-3.21.0/lib/rouge/themes/thankful_eyes.rb ruby-rouge-3.26.1/lib/rouge/themes/thankful_eyes.rb --- ruby-rouge-3.21.0/lib/rouge/themes/thankful_eyes.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/themes/thankful_eyes.rb 2021-09-17 19:59:49.000000000 +0000 @@ -59,6 +59,7 @@ Literal::Date, Literal::String::Symbol, :fg => :pink_merengue, :bold => true style Literal::String, :fg => :dune, :bold => true + style Literal::String::Affix, :fg => :sandy, :bold => true style Literal::String::Escape, Literal::String::Char, Literal::String::Interpol, :fg => :backlit, :bold => true diff -Nru ruby-rouge-3.21.0/lib/rouge/themes/tulip.rb ruby-rouge-3.26.1/lib/rouge/themes/tulip.rb --- ruby-rouge-3.21.0/lib/rouge/themes/tulip.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/themes/tulip.rb 2021-09-17 19:59:49.000000000 +0000 @@ -55,6 +55,7 @@ Literal::Date, Literal::String::Symbol, :fg => :lpurple, :bold => true style Literal::String, :fg => :dune, :bold => true + style Literal::String::Affix, :fg => :yellow, :bold => true style Literal::String::Escape, Literal::String::Char, Literal::String::Interpol, :fg => :orange, :bold => true diff -Nru ruby-rouge-3.21.0/lib/rouge/version.rb ruby-rouge-3.26.1/lib/rouge/version.rb --- ruby-rouge-3.21.0/lib/rouge/version.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge/version.rb 2021-09-17 19:59:49.000000000 +0000 @@ -3,6 +3,6 @@ module Rouge def self.version - "3.21.0" + "3.26.1" end end diff -Nru ruby-rouge-3.21.0/lib/rouge.rb ruby-rouge-3.26.1/lib/rouge.rb --- ruby-rouge-3.21.0/lib/rouge.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/lib/rouge.rb 2021-09-17 19:59:49.000000000 +0000 @@ -83,6 +83,7 @@ Rouge.load_file 'formatters/html_pygments' Rouge.load_file 'formatters/html_legacy' Rouge.load_file 'formatters/html_linewise' +Rouge.load_file 'formatters/html_line_highlighter' Rouge.load_file 'formatters/html_line_table' Rouge.load_file 'formatters/html_inline' Rouge.load_file 'formatters/terminal256' diff -Nru ruby-rouge-3.21.0/README.md ruby-rouge-3.26.1/README.md --- ruby-rouge-3.21.0/README.md 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/README.md 2021-09-17 19:59:49.000000000 +0000 @@ -13,6 +13,20 @@ [Pygments]: http://pygments.org "Pygments" +## Installation + +In your Gemfile, add: + +```ruby +gem 'rouge' +``` + +or + +```bash +$ gem install rouge +``` + ## Usage Rouge's most common uses are as a Ruby library, as part of Jekyll and as a @@ -79,6 +93,11 @@ your code into lines, each contained in its own div. The `class` option will be used to add a class name to the div, given the line number. +* `Rouge::Formatters::HTMLLineHighlighter.new(formatter, highlight_lines: [3, 5])` + will split your code into lines and wrap the lines specified by the + `highlight_lines` option in a span with a class name specified by the + `highlight_line_class` option (default: `hll`). + * `Rouge::Formatters::HTMLLineTable.new(formatter, opts={})` will output an HTML table containing numbered lines, each contained in its own table-row. Options are: @@ -276,8 +295,7 @@ Rouge is largely the result of the hard work of unpaid volunteers. It was originally developed by Jeanine Adkisson (@jneen) and is currently maintained by -Jeanine Adkisson, Drew Blessing (@dblessing), Michael Camilleri (@pyrmont) and -Goro Fuji (@gfx). +Jeanine Adkisson, Drew Blessing (@dblessing) and Goro Fuji (@gfx). ## License diff -Nru ruby-rouge-3.21.0/spec/formatters/html_line_highlighter_spec.rb ruby-rouge-3.26.1/spec/formatters/html_line_highlighter_spec.rb --- ruby-rouge-3.21.0/spec/formatters/html_line_highlighter_spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/formatters/html_line_highlighter_spec.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +describe Rouge::Formatters::HTMLLineHighlighter do + let(:subject) { Rouge::Formatters::HTMLLineHighlighter.new(formatter, options) } + let(:formatter) { Rouge::Formatters::HTML.new } + + let(:options) { {} } + let(:output) { subject.format(input_stream) } + + describe 'highlight lines' do + let(:input_stream) { [[Token['Text'], "foo\n"], [Token['Name'], "bar\n"]] } + let(:options) { { highlight_lines: [2] } } + + it 'should add highlight line class to lines specified by :highlight_lines option' do + assert { output == %(foo\nbar\n) } + end + end + + describe 'configure highlight line class' do + let(:input_stream) { [[Token['Text'], "foo\n"], [Token['Name'], "bar\n"]] } + let(:options) { { highlight_lines: [1, 2], highlight_line_class: 'hiline' } } + + it 'should add highlight line class to lines specified by :highlight_lines option' do + assert { output == %(foo\nbar\n) } + end + end +end diff -Nru ruby-rouge-3.21.0/spec/lexers/digdag_spec.rb ruby-rouge-3.26.1/spec/lexers/digdag_spec.rb --- ruby-rouge-3.21.0/spec/lexers/digdag_spec.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/lexers/digdag_spec.rb 2021-09-17 19:59:49.000000000 +0000 @@ -21,7 +21,7 @@ it 'recognizes one line comment on last line even when not terminated by a new line (#360)' do assert_tokens_equal "+step1:\n echo> Hello!\n", - ["Literal.String", "+step1"], + ["Name.Attribute", "+step1"], ["Punctuation.Indicator", ":"], ["Text", "\n "], ["Literal.String", "echo> Hello!"], diff -Nru ruby-rouge-3.21.0/spec/lexers/email_spec.rb ruby-rouge-3.26.1/spec/lexers/email_spec.rb --- ruby-rouge-3.21.0/spec/lexers/email_spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/lexers/email_spec.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +describe Rouge::Lexers::Email do + let(:subject) { Rouge::Lexers::Email.new } + + describe 'guessing' do + include Support::Guessing + + it 'guesses by filename' do + assert_guess :filename => 'foo.eml' + end + + it 'guesses by mimetype' do + assert_guess :mimetype => 'message/rfc822' + end + end +end diff -Nru ruby-rouge-3.21.0/spec/lexers/j_spec.rb ruby-rouge-3.26.1/spec/lexers/j_spec.rb --- ruby-rouge-3.21.0/spec/lexers/j_spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/lexers/j_spec.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,256 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +describe Rouge::Lexers::J do + let(:subject) { Rouge::Lexers::J.new } + + describe 'guessing' do + include Support::Guessing + + it 'guesses by filename' do + assert_guess :filename => 'foo.ijs' + assert_guess :filename => 'foo.ijt' + end + end + + describe 'lexing' do + include Support::Lexing + + describe 'primitives' do + # noun => Keyword.Constant + # verb => Name.Function + # adverb/conjunction => Operator + # copula => Punctuation + + it 'covers all the verbs' do + %w' + = < <. <: > >. >: + + +. +: - -. -: * *. *: % %. %: + ^ ^. $ $. $: ~. ~: | |. |: + , ,. ,: ; ;: # #. #: ! + /: \: [ [: ] + { {. {: {:: }. }: ". ": ? ?. + A. C. e. E. i. i: I. j. L. o. p. p.. p: q: + r. s: u. u: v. x: Z: + _9: _8: _7: _6: _5: _4: _3: _2: _1: 0: 1: 2: + 3: 4: 5: 6: 7: 8: 9: _: + '.each do |verb| + assert_tokens_equal verb, ['Name.Function', verb] + end + end + + it 'covers all the modifiers' do + %w' + ^: ~ . .. .: : :. :: + ;. !. !: / /. \\ \. + } }:: " ` `: @ @. @: + & &. &: &.: + d. D. D: f. F. F.. F.: F: F:. F:: H. L: M. S: + t. t: T. + '.each do |modifier| + assert_tokens_equal modifier, ['Operator', modifier] + end + end + + it 'recognizes the other primitives' do + %w'a. a:'.each do |noun| + assert_tokens_equal noun, ['Keyword.Constant', noun] + end + %w'=. =:'.each do |copula| + assert_tokens_equal copula, ['Punctuation', copula] + end + end + + it 'validates the inflection' do + assert_tokens_equal '[.q::F:.:. .::', + ['Error', '[.q::F:.:.'], ['Text', ' '], + ['Error', '.::'] + end + end + + describe 'words' do + it 'accepts names/locatives' do + assert_tokens_equal 'c', + ['Name', 'c'] + assert_tokens_equal 'foo_bar', + ['Name', 'foo_bar'] + assert_tokens_equal 'F00barBAZ', + ['Name', 'F00barBAZ'] + assert_tokens_equal 'foo_loc_', + ['Name', 'foo_loc_'] + assert_tokens_equal 'foo_1_', + ['Name', 'foo_1_'] + assert_tokens_equal 'foo__', + ['Name', 'foo__'] + assert_tokens_equal 'foo_bar__obj', + ['Name', 'foo_bar__obj'] + assert_tokens_equal 'foo__obj1__obj2', + ['Name', 'foo__obj1__obj2'] + end + + it 'rejects non-ascii characters' do + assert_tokens_equal 'á', + ['Error', 'á'] + end + + it 'recognizes control words' do + assert_tokens_equal 'if. do. return. end.', + ['Keyword', 'if.'], ['Text', ' '], + ['Keyword', 'do.'], + ['Text', ' '], + ['Keyword', 'return.'], + ['Text', ' '], + ['Keyword', 'end.'] + end + + it 'recognizes control words that include identifiers' do + assert_tokens_equal 'for_foo.a.do.end.', + ['Keyword', 'for_'], + ['Name', 'foo'], + ['Keyword', '.'], + ['Keyword.Constant', 'a.'], + ['Keyword', 'do.end.'] + assert_tokens_equal 'label_0a.', + ['Keyword', 'label_'], + ['Name.Label', '0a'], + ['Keyword', '.'] + end + + it 'validates the inflection' do + assert_tokens_equal 'foo. bar: do.. goto_.', + ['Error', 'foo.'], ['Text', ' '], + ['Error', 'bar:'], ['Text', ' '], + ['Error', 'do..'], ['Text', ' '], + ['Error', 'goto_.'] + end + end + + describe 'numerics' do + it 'accepts various forms of numeric constants' do + assert_tokens_equal '1 _2.4e9 _.j__ _.01 16bff.ee 12345x 3r2p_1', + ['Literal.Number', '1'], ['Text', ' '], + ['Literal.Number', '_2.4e9'], ['Text', ' '], + ['Literal.Number', '_.j__'], ['Text', ' '], + ['Literal.Number', '_.01'], ['Text', ' '], + ['Literal.Number', '16bff.ee'], ['Text', ' '], + ['Literal.Number', '12345x'], ['Text', ' '], + ['Literal.Number', '3r2p_1'] + end + + it 'validates the inflection' do + assert_tokens_equal '10: 2.:', + ['Error', '10:'], ['Text', ' '], + ['Error', '2.:'] + end + end + + describe 'strings' do + it 'recognizes single-quoted text' do + assert_tokens_equal "'foo bar 12345á!#$@?'", + ['Literal.String.Single', "'foo bar 12345á!#$@?'"] + end + + it 'recognizes escape sequences' do + assert_tokens_equal "'foo''bar'''", + ['Literal.String.Single', "'foo"], + ['Literal.String.Escape', "''"], + ['Literal.String.Single', "bar"], + ['Literal.String.Escape', "''"], + ['Literal.String.Single', "'"] + end + + it 'recognizes no inflection' do + assert_tokens_equal "'foo'.'bar':", + ['Literal.String.Single', "'foo'"], + ['Operator', '.'], + ['Literal.String.Single', "'bar'"], + ['Operator', ':'] + end + end + + describe 'comments' do + it 'recognizes single line comments' do + assert_tokens_equal 'NB.foo bar á', + ['Comment.Single', 'NB.foo bar á'] + assert_tokens_equal "123 NB. foo\nbar", + ['Literal.Number', '123'], + ['Text', ' '], + ['Comment.Single', 'NB. foo'], + ['Text', "\n"], + ['Name', 'bar'] + end + + it 'recognizes multiline comments' do + assert_tokens_equal "Note ''\nfoo\nbar\nbaz\n12345á\n)", + ['Name', 'Note'], ['Text', ' '], + ['Literal.String.Single', "''"], ['Text', "\n"], + ['Comment.Multiline', "foo\nbar\nbaz\n12345á\n"], + ['Punctuation', ')'] + assert_tokens_equal "0 Note ''", + ['Literal.Number', '0'], ['Text', ' '], + ['Name', 'Note'], ['Text', ' '], + ['Literal.String.Single', "''"] + assert_tokens_equal "Note\n", + ['Name', 'Note'], ['Text', "\n"] + assert_tokens_equal 'Note=: [', + ['Name', 'Note'], + ['Punctuation', '=:'], ['Text', ' '], + ['Name.Function', '['] + end + + it 'rejects inflected NB./Note' do + assert_tokens_equal 'NB..foo', + ['Error', 'NB..'], + ['Name', 'foo'] + assert_tokens_equal 'Note.1', + ['Error', 'Note.'], + ['Literal.Number', '1'] + end + end + + describe 'explicit definitions' do + it 'recognizes multiline noun' do + assert_tokens_equal "noun define\nFOO bar\n*!'~\n á1`_(\n)", + ['Keyword.Pseudo', 'noun'], ['Text', ' '], + ['Keyword.Pseudo', 'define'], ['Text', "\n"], + ['Literal.String.Heredoc', "FOO bar\n*!'~\n á1`_(\n"], + ['Punctuation', ')'] + end + + it 'recognizes multiline code' do + assert_tokens_equal "verb define\n>:y\n:\nx + y\n)", + ['Keyword.Pseudo', 'verb'], ['Text', ' '], + ['Keyword.Pseudo', 'define'], ['Text', "\n"], + ['Name.Function', '>:'], + ['Name.Builtin.Pseudo', 'y'], ['Text', "\n"], + ['Punctuation', ':'], ['Text', "\n"], + ['Name.Builtin.Pseudo', 'x'], ['Text', ' '], + ['Name.Function', '+'], ['Text', ' '], + ['Name.Builtin.Pseudo', 'y'], ['Text', "\n"], + ['Punctuation', ')'] + assert_tokens_equal "1 :0\nm :\n)", + ['Keyword.Pseudo', '1'], ['Text', ' '], + ['Keyword.Pseudo', ':0'], ['Text', "\n"], + ['Name.Builtin.Pseudo', 'm'], ['Text', ' '], + ['Operator', ':'], ['Text', "\n"], + ['Punctuation', ')'] + end + + it 'lexes inside explicit definition literals' do + assert_tokens_equal "conjunction def '1 -@u ''foo''&v NB.bar'", + ['Keyword.Pseudo', 'conjunction'], ['Text', ' '], + ['Keyword.Pseudo', 'def'], ['Text', ' '], + ['Punctuation', "'"], + ['Literal.Number', '1'], ['Text', ' '], + ['Name.Function', '-'], + ['Operator', '@'], + ['Name.Builtin.Pseudo', 'u'], ['Text', ' '], + ['Literal.String.Single', "''foo''"], + ['Operator', '&'], + ['Name.Builtin.Pseudo', 'v'], ['Text', ' '], + ['Comment.Single', 'NB.bar'], + ['Punctuation', "'"] + end + end + end +end diff -Nru ruby-rouge-3.21.0/spec/lexers/ocl.rb ruby-rouge-3.26.1/spec/lexers/ocl.rb --- ruby-rouge-3.21.0/spec/lexers/ocl.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/lexers/ocl.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +describe Rouge::Lexers::OCL do + let(:subject) { Rouge::Lexers::OCL.new } + + describe 'guessing' do + include Support::Guessing + + it 'guesses by filename' do + assert_guess :filename => 'foo.ocl' + end + + it 'guesses by mimetype' do + assert_guess :mimetype => 'text/x-ocl' + end + end + + describe 'lexing' do + include Support::Lexing + + it 'recognizes one line comment on last line even when not terminated by a new line (#360)' do + assert_tokens_equal '-- comment', ['Comment.Single', '-- comment'] + end + end +end diff -Nru ruby-rouge-3.21.0/spec/lexers/php_spec.rb ruby-rouge-3.26.1/spec/lexers/php_spec.rb --- ruby-rouge-3.21.0/spec/lexers/php_spec.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/lexers/php_spec.rb 2021-09-17 19:59:49.000000000 +0000 @@ -36,43 +36,41 @@ it 'recognizes double-slash comments not followed by a newline (#797)' do assert_tokens_equal '// comment', ['Comment.Single', '// comment'] end - + it 'recognizes try catch finally definition' do assert_tokens_equal 'try {} catch () {} finally {}', ["Keyword", "try"], ["Text", " "], ["Punctuation", "{}"], ["Text", " "], ["Keyword", "catch"], ["Text", " "], ["Punctuation", "()"], ["Text", " "], ["Punctuation", "{}"], ["Text", " "], ["Keyword", "finally"], ["Text", " "], ["Punctuation", "{}"] end - + it 'recognizes class definition' do assert_tokens_equal 'class A {}', ["Keyword.Declaration", "class"], ["Text", " "], ["Name.Class", "A"], ["Text", " "], ["Punctuation", "{}"] end - + it 'recognizes interface definition' do assert_tokens_equal 'interface A {}', ["Keyword.Declaration", "interface"], ["Text", " "], ["Name.Class", "A"], ["Text", " "], ["Punctuation", "{}"] end - + it 'recognizes trait definition' do assert_tokens_equal 'trait A {}', ["Keyword.Declaration", "trait"], ["Text", " "], ["Name.Class", "A"], ["Text", " "], ["Punctuation", "{}"] end it 'recognizes case insensitively keywords' do - assert_tokens_equal 'While', ["Keyword", "While"] - # class for anonymous classes is recognized as a regular keyword - assert_tokens_equal 'Class {', ["Keyword", "Class"], ["Text", " "], ["Punctuation", "{"] - assert_tokens_equal 'Class BAR', ["Keyword.Declaration", "Class"], ["Text", " "], ["Name.Class", "BAR"] - assert_tokens_equal 'Const BAR', ["Keyword", "Const"], ["Text", " "], ["Name.Constant", "BAR"] - assert_tokens_equal 'Use BAR', ["Keyword.Namespace", "Use"], ["Text", " "], ["Name.Namespace", "BAR"] - assert_tokens_equal 'NameSpace BAR', ["Keyword.Namespace", "NameSpace"], ["Text", " "], ["Name.Namespace", "BAR"] + assert_tokens_equal 'While', ["Keyword", "While"]; subject.reset_stack + assert_tokens_equal 'Class BAR', ["Keyword.Declaration", "Class"], ["Text", " "], ["Name.Class", "BAR"]; subject.reset_stack + assert_tokens_equal 'Const BAR', ["Keyword", "Const"], ["Text", " "], ["Name.Constant", "BAR"]; subject.reset_stack + assert_tokens_equal 'Use BAR', ["Keyword.Namespace", "Use"], ["Text", " "], ["Name.Constant", "BAR"]; subject.reset_stack + assert_tokens_equal 'NameSpace BAR', ["Keyword.Namespace", "NameSpace"], ["Text", " "], ["Name.Namespace", "BAR"]; subject.reset_stack # function for anonymous functions is also recognized as a regular keyword - assert_tokens_equal 'Function (', ["Keyword", "Function"], ["Text", " "], ["Punctuation", "("] - assert_tokens_equal 'Function foo', ["Keyword", "Function"], ["Text", " "], ["Name.Function", "foo"] + assert_tokens_equal 'Function (', ["Keyword", "Function"], ["Text", " "], ["Punctuation", "("]; subject.reset_stack + assert_tokens_equal 'Function foo', ["Keyword", "Function"], ["Text", " "], ["Name", "foo"]; subject.reset_stack end it 'recognizes case sensitively E_* and PHP_* as constants' do - assert_tokens_equal 'PHP_EOL', ["Keyword.Constant", "PHP_EOL"] - assert_tokens_equal 'PHP_EOL_1', ["Name.Other", "PHP_EOL_1"] + assert_tokens_equal 'PHP_EOL', ["Keyword.Constant", "PHP_EOL"]; subject.reset_stack + assert_tokens_equal 'PHP_EOL_1', ["Name.Constant", "PHP_EOL_1"]; subject.reset_stack - assert_tokens_equal 'E_user_DEPRECATED', ["Name.Other", "E_user_DEPRECATED"] - assert_tokens_equal 'E_USER_deprecated', ["Name.Other", "E_USER_deprecated"] - assert_tokens_equal 'E_USER_DEPRECATED', ["Keyword.Constant", "E_USER_DEPRECATED"] + assert_tokens_equal 'E_user_DEPRECATED', ["Name", "E_user_DEPRECATED"]; subject.reset_stack + assert_tokens_equal 'E_USER_deprecated', ["Name", "E_USER_deprecated"]; subject.reset_stack + assert_tokens_equal 'E_USER_DEPRECATED', ["Keyword.Constant", "E_USER_DEPRECATED"]; subject.reset_stack end end end diff -Nru ruby-rouge-3.21.0/spec/lexers/postscript_spec.rb ruby-rouge-3.26.1/spec/lexers/postscript_spec.rb --- ruby-rouge-3.21.0/spec/lexers/postscript_spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/lexers/postscript_spec.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +describe Rouge::Lexers::PostScript do + let(:subject) { Rouge::Lexers::PostScript.new } + + describe 'guessing' do + include Support::Guessing + + it 'guesses by filename' do + assert_guess :filename => 'foo.ps' + assert_guess :filename => 'foo.eps' + end + + it 'guesses by mimetype' do + assert_guess :mimetype => 'application/postscript' + end + + it 'guesses by source' do + assert_guess :source => '%!PS' + assert_guess :source => '%!PS-Adobe-3.0' + end + end +end diff -Nru ruby-rouge-3.21.0/spec/lexers/rescript_spec.rb ruby-rouge-3.26.1/spec/lexers/rescript_spec.rb --- ruby-rouge-3.21.0/spec/lexers/rescript_spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/lexers/rescript_spec.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +describe Rouge::Lexers::ReScript do + let(:subject) { Rouge::Lexers::ReScript.new } + + describe 'guessing' do + include Support::Guessing + + it 'guesses by filename' do + assert_guess :filename => 'foo.res' + assert_guess :filename => 'foo.resi' + end + + it 'guesses by mimetype' do + assert_guess :mimetype => 'text/x-rescript' + end + end +end diff -Nru ruby-rouge-3.21.0/spec/lexers/systemd_spec.rb ruby-rouge-3.26.1/spec/lexers/systemd_spec.rb --- ruby-rouge-3.21.0/spec/lexers/systemd_spec.rb 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/lexers/systemd_spec.rb 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +describe Rouge::Lexers::SystemD do + let(:subject) { Rouge::Lexers::SystemD::new } + + describe 'guessing' do + include Support::Guessing + + it 'guesses by filename' do + assert_guess :filename => 'unit.service' + end + + it 'guesses by mimetype' do + assert_guess :mimetype => 'text/x-systemd-unit' + end + end +end diff -Nru ruby-rouge-3.21.0/spec/lexer_spec.rb ruby-rouge-3.26.1/spec/lexer_spec.rb --- ruby-rouge-3.21.0/spec/lexer_spec.rb 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/lexer_spec.rb 2021-09-17 19:59:49.000000000 +0000 @@ -204,4 +204,16 @@ assert_equal false, option_lexer.new({bool_opt: 'false'}).instance_variable_get(:@bool_opt) assert_equal false, option_lexer.new({bool_opt: 'off'}).instance_variable_get(:@bool_opt) end + + it 'extends options with #with' do + php = Rouge::Lexers::PHP.new + + assert { php.instance_variable_get(:@start_inline) == :guess } + + inline_php = php.with(start_inline: true) + assert { inline_php.is_a?(Rouge::Lexers::PHP) } + assert { inline_php != php } + assert { php.instance_variable_get(:@start_inline) == :guess } + assert { inline_php.instance_variable_get(:@start_inline) == true } + end end diff -Nru ruby-rouge-3.21.0/spec/visual/samples/batchfile ruby-rouge-3.26.1/spec/visual/samples/batchfile --- ruby-rouge-3.21.0/spec/visual/samples/batchfile 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/batchfile 2021-09-17 19:59:49.000000000 +0000 @@ -35,3 +35,4 @@ echo Bye goto :eof :a +streamlink --http-header "User-Agent: test" "https://example.com/master.m3u8" best -o output.ts diff -Nru ruby-rouge-3.21.0/spec/visual/samples/cpp ruby-rouge-3.26.1/spec/visual/samples/cpp --- ruby-rouge-3.21.0/spec/visual/samples/cpp 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/cpp 2021-09-17 19:59:49.000000000 +0000 @@ -1,8 +1,7 @@ -int quote_delims = 100'000'000 -int float_delims = 100.00'00 -int hex_delims = 0xFF'Fa12 - -int binary = 0b1000; +int quote_delims = 100'000'000; +int float_delims = 100.00'00; +int hex_delims = 0xFF'Fa12; +int bin_delims = 0b10'1000; // string literal with encoding-prefix char str1[] = u8"UTF-8 string"; @@ -19,14 +18,24 @@ // time literal #include using namespace std::chrono_literals; +auto oneDecade = 10y; +auto oneYear = 365.2'425d; auto oneDay = 24h; auto halfAnHour = 30min; +auto oneYearInMins = 525'949.2min; auto halfAnHour = 0.5h; auto oneMin = 60s; auto oneSec = 1000ms; auto oneMilliSec = 1000us; auto oneMicroSec = 1000ns; +// complex literal +#include +using namespace std::complex_literals; +auto complexNumber = 1 + 1i; +auto complexNumberl = 1 + 1il; +auto complexNumberf = 1 + 1if; + // null pointer int *a = nullptr; diff -Nru ruby-rouge-3.21.0/spec/visual/samples/crystal ruby-rouge-3.26.1/spec/visual/samples/crystal --- ruby-rouge-3.21.0/spec/visual/samples/crystal 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/crystal 2021-09-17 19:59:49.000000000 +0000 @@ -1,45 +1,687 @@ -lib LibC - WNOHANG = 0x00000001 +# Examples taken from http://crystal-lang.org/docs/ +# Copyright 2012-2018 Manas Technology Solutions. +# Based on the sample in the Pygments project (github.com/pygments/pygments) - @[ReturnsTwice] - fun fork : PidT - fun getpgid(pid : PidT) : PidT - fun kill(pid : PidT, signal : Int) : Int - fun getpid : PidT - fun getppid : PidT - fun exit(status : Int) : NoReturn +## Constants - ifdef x86_64 - alias ClockT = UInt64 - else - alias ClockT = UInt32 +LUCKY_NUMBERS = [3, 7, 11] +DOCUMENTATION_URL = "http://crystal-lang.org/docs" + +## Assignments + +i = 0 +items = Items.new +channel = Channel(Int32).new(2) +a = [] of Person +hash = {} of Int32 => String +nest = [1, ["b", [:c, ['d']]]] + +## Require statements + +require "http/server" + +## Blocks + +x = a.map { |f| f.name } # Error: can't infer block return type + +spawn do + channel.send(1) + channel.send(2) + channel.send(3) +end + +3.times do |i| + puts channel.receive +end + +server = HTTP::Server.new(8080) do |context| + context.response.content_type = "text/plain" + context.response.print "Hello world! The time is #{Time.now}" +end + +## Loops + +while i < 10 + proc = ->(x : Int32) do + spawn do + puts(x) + end + end + proc.call(i) + i += 1 +end + +until some_condition + do_this +end + +## Module definitions + +module HTTP + class RequestHandler + end +end + +module Base64 + extend self + + def encode64(string) + # ... + end +end + +module Moo(T) + def t + T + end +end + +module Money + CURRENCIES = { + "EUR" => 1.0, + "ARS" => 10.55, + "USD" => 1.12, + "JPY" => 134.15, + } + + class Amount + getter :currency, :value + + def initialize(@currency, @value) + end + end + + class CurrencyConversion + def initialize(@amount, @target_currency) + end + + def amount + # implement conversion ... + end + end +end + +## Class definitions + +class Greeting + class_property global_greeting = "Hello world" + + @@default_greeting = "Hello world" + + def initialize(@custom_greeting = nil) + end + + def print_greeting + greeting = @custom_greeting || @@default_greeting + puts greeting + end +end + +class MyArray + def [](index) + # ... + end + + def [](index1, index2, index3) + # ... + end + + def []=(index, value) + # ... + end +end + +class MyDictionary(K, V) +end + +class Foo(U) + include Moo(U) + + def initialize(@value : U) end +end + +class Int32Child < Parent(Int32) +end + +class Global + class_property global1 = 1 + class_getter global2 = 2 + class_setter global3 = 3 + + # Fails on nil + class_property! global4 = 4 + class_getter! global5 = 5 + class_setter! global6 = 6 +end + +class Testing + # Assigns to an instance variable + @instance = 2 + + # Assigns to a class variable + @@class = 3 +end + +abstract class Animal + # Makes this animal talk + abstract def talk +end + +## Struct definitions + +struct Vector2 + getter x, y + + def initialize(@x, @y) + end + + def +(other) + Vector2.new(x + other.x, y + other.y) + end +end + +struct Vector2 + def - + Vector2.new(-x, -y) + end +end + +## Library definitions + +lib C + # In C: double cos(double x) + fun cos(value : Float64) : Float64 + + fun getch : Int32 - SC_CLK_TCK = 3 + fun srand(seed : UInt32) - struct Tms - utime : ClockT - stime : ClockT - cutime : ClockT - cstime : ClockT + fun exit(status : Int32) : NoReturn + + fun printf(format : UInt8*, ...) : Int32 +end + +@[Link("pcre")] +lib LibPCRE +end + +lib LibFoo + fun store_callback(callback : ->) + + @[Raises] + fun execute_callback +end + +lib C + {% if flag?(:x86_64) %} + alias SizeT = UInt64 + {% else %} + alias SizeT = UInt32 + {% end %} + + fun memcmp(p1 : Void*, p2 : Void*, size : C::SizeT) : Int32 +end + +lib U + union IntOrFloat + some_int : Int32 + some_float : Float64 end +end + +## Aliase declarations + +alias NumericValue = Float32 | Float64 | Int32 | Int64 +alias Int32OrNil = Int32? +alias Int32OrNil_ = Int32 | ::Nil +alias Int32Ptr = Int32* +alias Int32Ptr_ = Pointer(Int32) +alias Int32_8 = Int32[8] +alias Int32_8_ = StaticArray(Int32, 8) +alias Int32StringTuple = {Int32, String} +alias Int32StringTuple_ = Tuple(Int32, String) +alias Int32ToString = Int32 -> String +alias Int32ToString_ = Proc(Int32, String) +alias ProcThatReturnsInt32 = -> Int32 +alias Int32AndCharToString = Int32, Char -> String +alias ComplexProc = (Int32 -> Int32) -> String - fun times(buffer : Tms*) : ClockT - fun sysconf(name : Int) : Long +## Enum declarations + +enum Time::DayOfWeek end -class Process - def self.exit(status = 0) - LibC.exit(status) +enum Color : UInt8 + Red # 0 + Green # 1 + Blue = 5 # overwritten to 5 + Yellow # 6 (5 + 1) + + def red? + self == Color::Red end +end + +@[Flags] +enum IOMode + Read # 1 + Write # 2 + Async # 4 +end + +## Method definitions + +def foo(x : Int32) + "instance" +end + +def foo(x : Int32.class) + "class" +end + +def foo(x : _) +end + +def foo(x : _, _ -> Int32) +end + +def some_proc(&block : Int32 -> Int32) + block +end - def self.pid - LibC.getpid +def twice(&block) + yield + yield +end + + +def paint(color : Color) + case color + when Color::Red + # ... + else + # Unusual, but still can happen + raise "unknown color: #{color}" end +end + +def counter + x = 0 + ->{ x += 1; x } +end + +## Method calls + +puts "Listening on http://0.0.0.0:8080" +server.listen +Fiber.yield +Curses::Window.new +foo 1 # "instance" +foo Int32 # "class" +a.+(b) +C.printf "%d + %d = %d\n", a, b, a + b + +array[1] # invokes the first method +array[1, 2, 3] # invokes the second method +array[1] = 2 # invokes the third method +array[4]? # returns nil because of index out of bounds +array.[](1) # invokes the first method +array.[](1, 2, 3) # invokes the second method +array.[]=(1, 2) # invokes the third method + +## Operators + +john == another_john # => true + +ary << Child1 +ary << Child2 + +local += 1 # same as: local = local + 1 +local ||= 1 # same as: local || (local = 1) +local &&= 1 # same as: local && (local = 1) + +x..y # an inclusive range, in mathematics: [x, y] +x...y # an exclusive range, in mathematics: [x, y) + +## Conditionals + +a = some_condition ? 1 : "hello" +a = 1 > 2 ? 3 : 4 + +if some_condition + a = 1 +else + a = "hello" +end + +if a.is_a?(String) + # here a is a String +end + +if a.is_a?(Number) + # a : Int32 +else + # a : String +end + +if some_condition + do_something +elsif some_other_condition + do_something_else +else + do_that +end + +if a.is_a?(String) && b.is_a?(Number) + # here a is a String and b is a Number +end + +unless some_condition + then_expression +else + else_expression +end + +a = 2 if some_condition +close_door unless door_closed? + +case exp +when value1, value2 + do_something +when value3 + do_something_else +else + do_another_thing +end + +## Exceptions + +raise "OH NO!" +raise Exception.new("Some error") + +begin + raise MyException.new("OH NO!") +rescue ex : MyException + puts "Rescued MyException: #{ex.message}" +end + +begin + # ... +rescue ex : MyException | MyOtherException + # only MyException or MyOtherException +rescue + # any other kind of exception +ensure + puts "Cleanup..." +end + +def some_method + something_dangerous +rescue + # execute if an exception is raised +end + +## Procs + +proc = ->(i : Int32) { x += i } +proc = some_proc(&proc) +proc.call(1) # => 1 +adder = ->add(Int32, Int32) +adder.call(1, 2) # => 3 +twice &proc +twice &->{ puts "Hello" } + +## Macros + +{% if flag?(:x86_64) %} + # some specific code for 64 bits platforms +{% else %} + # some specific code for non-64 bits platforms +{% end %} + +{% if flag?(:linux) && flag?(:x86_64) %} + # some specific code for linux 64 bits +{% end %} + +{% if env("TEST") %} + puts "We are in test mode" +{% end %} + +macro fresh_vars_sample(*names) + # First declare vars + {% for name, index in names %} + print "Declaring: ", "%name{index}", '\n' + %name{index} = {{index}} + {% end %} + + # Then print them + {% for name, index in names %} + print "%name{index}: ", %name{index}, '\n' + {% end %} +end + +macro method_missing(name, args, block) + print "Got ", {{name.id.stringify}}, " with ", {{args.size}}, " arguments", '\n' +end - def self.getpgid(pid : Int32) - ret = LibC.getpgid(pid) - raise Errno.new(ret) if ret < 0 - ret +macro define_method(name, content) + def {{name}} + {% if content == 1 %} + "one" + {% else %} + {{content}} + {% end %} end end + +## Numbers + +1.0 # Float64 +1.0_f32 # Float32 +1_f32 # Float32 + +1e10 # Float64 +1.5e10 # Float64 +1.5e-7 # Float64 + ++1.3 # Float64 +-0.5 # Float64 + +1_000_000.111_111 # better than 1000000.111111 + +1 # Int32 + +1_i8 # Int8 +1_i16 # Int16 +1_i32 # Int32 +1_i64 # Int64 + +1_u8 # UInt8 +1_u16 # UInt16 +1_u32 # UInt32 +1_u64 # UInt64 + ++10 # Int32 +-20 # Int32 + +2147483648 # Int64 +9223372036854775808 # UInt64 + +1_000_000 # better than 1000000 + +0b1101 # == 13 + +0o123 # == 83 + +0xFE012D # == 16646445 +0xfe012d # == 16646445 + +## Regular expressions + +foo_or_bar = /foo|bar/ +heeello = /h(e+)llo/ +integer = /\d+/ +r = /foo/imx +slash = /\// +r = %r(regex with slash: /) + +## Strings + +"hello world" + +"\"" # double quote +"\\" # backslash +"\e" # escape +"\f" # form feed +"\n" # newline +"\r" # carriage return +"\t" # tab +"\v" # vertical tab + +"\101" # == "A" +"\123" # == "S" +"\12" # == "\n" +"\1" # string with one character with code point 1 + +"\u0041" # == "A" + +"\u{41}" # == "A" +"\u{1F52E}" # == "🔮" +"あ" + +"hello + world" # same as "hello\n world" + +"hello " \ +"world, " \ +"no newlines" # same as "hello world, no newlines" + +"hello \ + world, \ + no newlines" # same as "hello world, no newlines" + +# Supports double quotes and nested parenthesis +%(hello ("world")) # same as "hello (\"world\")" + +# Supports double quotes and nested brackets +%[hello ["world"]] # same as "hello [\"world\"]" + +# Supports double quotes and nested curlies +%{hello {"world"}} # same as "hello {\"world\"}" + +# Supports double quotes and nested angles +%> # same as "hello <\"world\">" + +## Heredoc strings + +<<-XML + + + +XML + +<<-STRING + Hello + world + STRING + +## Characters + +'a' +'z' +'0' +'_' + +'\'' # single quote +'\\' # backslash +'\e' # escape +'\f' # form feed +'\n' # newline +'\r' # carriage return +'\t' # tab +'\v' # vertical tab + +"\101" # == 'A' +"\123" # == 'S' +"\12" # == '\n' +"\1" # code point 1 + +'\u0041' # == 'A' + +'\u{41}' # == 'A' +'\u{1F52E}' # == '🔮' + +## Symbols + +:hello +:good_bye + +# With spaces and symbols +:"symbol with spaces" + +# Ending with question and exclamation marks +:question? +:exclamation! + +# For the operators +:+ +:- +:* +:/ +:== +:< +:<= +:> +:>= +:! +:!= +:=~ +:!~ +:& +:| +:^ +:~ +:** +:>> +:<< +:% +:[] +:[]? +:[]= +:<=> +:=== + +## Hashes + +{1 => 2, 3 => 4} # Hash(Int32, Int32) +{1 => 2, 'a' => 3} # Hash(Int32 | Char, Int32) +{} of Int32 => Int32 # same as Hash(Int32, Int32).new +{key1: 'a', key2: 'b'} # Hash(Symbol, Char) +{"key1": 'a', "key2": 'b'} # Hash(String, Char) + +MyType{"foo" => "bar"} +MyType(String, String){"foo" => "bar"} + +## Tuples + +tuple = {1, "hello", 'x'} # Tuple(Int32, String, Char) +tuple[0] # => 1 (Int32) +tuple[1] # => "hello" (String) +tuple[2] # => 'x' (Char) + +## Arrays + +[1, 2, 3] # Array(Int32) +[1, "hello", 'x'] # Array(Int32 | String | Char) + +[] of Int32 # same as Array(Int32).new + +%w(one two three) # ["one", "two", "three"] +%i(one two three) # [:one, :two, :three] + +## Keywords + +nil +true # A Bool that is true +false # A Bool that is false diff -Nru ruby-rouge-3.21.0/spec/visual/samples/email ruby-rouge-3.26.1/spec/visual/samples/email --- ruby-rouge-3.21.0/spec/visual/samples/email 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/email 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,23 @@ +From: Me +To: You +Cc: Somebody , + And One More +Bcc: Secret Person +X-Spam-Status: Definitely not spam +Date: Tue, 21 Jul 2020 15:14:03 +0000 +Subject: RE: A very important message + that continues onto the next line. + +Greetings and salutations. + +>> A second-level quotation. +> +> Please investigate. Thank you. + +I have investigated. + +Note: A space-stuffed line starting with > is not a quote. + > like this. + +-- +This message is highly confidential and will self-destruct. diff -Nru ruby-rouge-3.21.0/spec/visual/samples/j ruby-rouge-3.26.1/spec/visual/samples/j --- ruby-rouge-3.21.0/spec/visual/samples/j 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/j 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,92 @@ +NB. Single line comment + +Note 'Multiline comment' +The verb `Note` starts a multiline comment. +')' in the next line ends this comment. +) + +Note=: 'This is not a comment' + +NB. Primitives += =. =: < <. <: > >. >: ++ +. +: - -. -: * *. *: % %. %: +^ ^. ^: $ $. $: ~ ~. ~: | |. |: +. .. .: : :. :: , ,. ,: ; ;. ;: +# #. #: ! !. !: / /. /: \ \. \: +[ [: ] { {. {: {:: } }. }: }:: +" ". ": ` `: @ @. @: & &. &: &.: +? ?. +a. a: A. b. C. d. D. D: e. E. f. F. F.. F.: F: +F:. F:: H. i. i: I. j. L. L: M. o. p. p.. p: q: +r. s: S: t. t: T. u. u: v. x: Z: +_9: _8: _7: _6: _5: _4: _3: _2: _1: 0: 1: 2: 3: +4: 5: 6: 7: 8: 9: _: + +NB. Control words +do. end. +if. elseif. else. +select. case. fcase. +for. +while. +whilst. +break. continue. +assert. +try. catch. catchd. catcht. +throw. +return. + +NB. Control words with identifiers +for_elem. +label_lbl. goto_lbl. + +NB. Names +foo foo_bar +foo_loc_ foo_bar_loc_ foo_1_ foo__ NB. Explicit locatives +foo__obj foo_bar__obj foo__o1__o2 NB. Object locatives + +NB. Numeric constants +0 1 _1 NB. Integers 0, 1, -1 +_ __ _. NB. Infinity, negative infinity, NaN +0.8 1.23e_9 _3e15 NB. Floating-point numbers +1.5j2 3.3ar1 2ad60 NB. Complex numbers +5r3 _1r2 NB. Rational numbers +1.2p3 7x_1.5 NB. 1.2*π^3, 7*e^-1.5 +2b0010 16babc789.12 NB. Binary/hexadecimal numbers +9999999999999999999x NB. An extended precision integer + +NB. String literals +'foo bar' +'foo ''bar''' NB. `''` escapes single-quote + +NB. Invalid tokens +foo: for_. {::. .:. 10: NB.. + +NB. Multiline String +noun define +This is a 'heredoc' string. +You can include LF + + or single-quote ' here. +) + +NB. Explicit definitions +verb define + NB. Monadic case + if. #y do. + echo y + end. +: + NB. Dyadic case + if. x <: #y do. + echo x {. y + end. +) +adverb def '[: u^:_1 u/' NB. Single line form +NB. More complicated example +0 define 13 def 0 noun : 0 +the right noun +) + x , y +) +the left noun +) diff -Nru ruby-rouge-3.21.0/spec/visual/samples/janet ruby-rouge-3.26.1/spec/visual/samples/janet --- ruby-rouge-3.21.0/spec/visual/samples/janet 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/janet 2021-09-17 19:59:49.000000000 +0000 @@ -130,6 +130,8 @@ (def name 'myfunction) (def args '[x y z]) (defn body '[(print x) (print y) (print z)]) +'{:foo (print "bar")} +'@(print 1 2 3) # Quasiquotes ~x diff -Nru ruby-rouge-3.21.0/spec/visual/samples/javascript ruby-rouge-3.26.1/spec/visual/samples/javascript --- ruby-rouge-3.21.0/spec/visual/samples/javascript 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/javascript 2021-09-17 19:59:49.000000000 +0000 @@ -229,6 +229,8 @@ 1 + 2 }`; +var notATernary = `${obj?.prop}`; + @(function(thing) { return thing; }) class Person { @deprecate diff -Nru ruby-rouge-3.21.0/spec/visual/samples/jsl ruby-rouge-3.26.1/spec/visual/samples/jsl --- ruby-rouge-3.21.0/spec/visual/samples/jsl 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/jsl 2021-09-17 19:59:49.000000000 +0000 @@ -4,6 +4,14 @@ /* Multi-line comment */ +/* Single line block comment */ +/* + Nested + /* + Comments + */ + Work +*/ escapeSequence = "This is an \!b escaped sequence"; escapeQuote = "This is a \!" quotation mark"; @@ -11,14 +19,24 @@ list = List( 1, 3, 5 ); alsoAList = {7,9,11}; +index = 1::10::2; a name with spaces = 5; "a-name!with\!"special\characters"n = 5; +::globalVar = 1; +here:scopedVar = 2; scientificNotation = 5e9; decimal = 1.234; +missing = .; date = 01jan00; dateTime = 12dec1999:12:30:00.45; New Window( "Rouge Test", - Text Box( "Syntax highlighting is great!" ) + tb = Text Box( "Syntax highlighting is great!" ) ); + +If(tb << Get Text != "", "I'm still formatted correctly!"); + +New Namespace("rouge"); +rouge:scoped.func = function({x, y}, x + y); +rouge:scoped.func(1, 2); diff -Nru ruby-rouge-3.21.0/spec/visual/samples/kotlin ruby-rouge-3.26.1/spec/visual/samples/kotlin --- ruby-rouge-3.21.0/spec/visual/samples/kotlin 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/kotlin 2021-09-17 19:59:49.000000000 +0000 @@ -155,15 +155,19 @@ } fun String.extensionFunction() { - return + return } fun `String`.`backTickedExtensionFunction`() { - return + return } fun String.genericExtensionFunction() { - return + return +} + +fun foo(supersedingStuff: List): List { + return supersedingStuff.map { it } } inline fun membersOf() = T::class.members diff -Nru ruby-rouge-3.21.0/spec/visual/samples/ocl ruby-rouge-3.26.1/spec/visual/samples/ocl --- ruby-rouge-3.21.0/spec/visual/samples/ocl 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/ocl 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,45 @@ +package uml::Activities + +context uml::Activities::Activity + inv maximum_one_parameter_node: + ownedParameter->forAll(p | p.direction <> UML::Classification::ParameterDirectionKind::inout implies + node->select( + ( + oclIsKindOf(activities::ActivityParameterNode) and + oclAsType(activities::ActivityParameterNode).parameter = p + )) + ->size() = 1) + +context Action::allActions() : Set(uml::Actions::Action) + body: + (self->asSet()) + +context Action::allOwnedNodes() : Set(uml::Activities::ActivityNode) + body: + (input.oclAsType(Pin)->asSet()->union(output->asSet())) + +context Action::containingBehavior() : uml::CommonBehavior::Behavior + body: + (if inStructuredNode<>null then inStructuredNode.containingBehavior() +else if activity<>null then activity +else interaction +endif +endif +) + +context uml::Actions::Action::isLocallyReentrant : Boolean +init: + false + +context uml::Actions::ExpansionRegion::mode : uml::Actions::ExpansionKind +init: + UML::Actions::ExpansionKind::iterative + +context Guard +-- [1] A guard should not have side effects. +inv: self.transition->stateMachine->notEmpty() implies + (self.transition.stateMachine.context = + self.transition.stateMachine.context@pre) + +endpackage +body: self.employees->collect(salary) -> collect(x | x/6.55957) diff -Nru ruby-rouge-3.21.0/spec/visual/samples/perl ruby-rouge-3.26.1/spec/visual/samples/perl --- ruby-rouge-3.21.0/spec/visual/samples/perl 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/perl 2021-09-17 19:59:49.000000000 +0000 @@ -170,6 +170,28 @@ => 1 ) +# sigils +${ $sref } +@{ $aref } +$#{ $aref } +%{ $href } +&{ $cref } +*{ $gref } +@$aref[ ... ] +@$href{ ... } +%$aref[ ... ] +%$href{ ... } +$sref->$*; # same as ${ $sref } +$aref->@*; # same as @{ $aref } +$aref->$#*; # same as $#{ $aref } +$href->%*; # same as %{ $href } +$cref->&*; # same as &{ $cref } +$gref->**; # same as *{ $gref } +$aref->@[ ... ]; # same as @$aref[ ... ] +$href->@{ ... }; # same as @$href{ ... } +$aref->%[ ... ]; # same as %$aref[ ... ] +$href->%{ ... }; # same as %$href{ ... } + __DATA__ This is just some end text; everything after DATA can be accessed diff -Nru ruby-rouge-3.21.0/spec/visual/samples/php ruby-rouge-3.26.1/spec/visual/samples/php --- ruby-rouge-3.21.0/spec/visual/samples/php 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/php 2021-09-17 19:59:49.000000000 +0000 @@ -1,33 +1,40 @@

It's html outside php!

+ + + + + + + + + + + + + -$test = function($a) { $lambda = 1; } -?>I can close php tags and get html! -/** snippet from wordpress */ -if (! isset($wp_did_header)): -if ( !file_exists( dirname(__FILE__) . '/wp-config.php') ) { - if ( strstr( $_SERVER['PHP_SELF'], 'wp-admin') ) $path = ''; - else $path = 'wp-admin/'; - die("There doesn't seem to be a wp-config.php" . - "file. I need this before we can get started. Need more" . - "help? We" . - "got it. You can create" . - "a wp-config.php file through a web interface," . - "but this doesn't work for all server setups. The safest way is" . - "to manually create the file." - ); -} +I can close php tags and get html! + + +other_thing()}" - -function &byref() { - $x = array(); - return $x; -} - -trait SomeTrait { - // Some visibility - const PUBLIC_CONST_A = 1; - public const PUBLIC_CONST_B = 2; - protected const PROTECTED_CONST = 3; - private const PRIVATE_CONST = 4; - - function afunc(string $arg, SomeInterface $arg2, callable $arg3, object $arg4): void { - echo "hello"; - if (1 <=> 1) { - echo "yep!"; - } - } -} - -interface SomeInterface { - function interfaceFunc(bool $arg): iterable; - function nullableTypes(?bool $arg): ?iterable; -} - -//Anonymous class example -$app->setLogger(new class implements Logger { - public function log(string $msg) { - echo $msg; - } -}); -// some uses -use some\namespace\ClassA; -use some\namespace\ClassB; -use some\namespace\ClassC as C; +/* Numbers */ -use function some\namespace\fn_a; -use function some\namespace\fn_b; -use function some\namespace\fn_c; +1; +3.14; +1.414e10; +1_000_000; +007; +0b1010; +0xabcdef; -use const some\namespace\ConstA; -use const some\namespace\ConstB; -use const some\namespace\ConstC; -// Grouped uses -use some\namespace\{ClassA, ClassB, ClassC as C}; -use function some\namespace\{fn_a, fn_b, fn_c}; -use const some\namespace\{ConstA, ConstB, ConstC}; +/* Strings */ -namespace some\namespace; - -// A generator -$gen = (function() { - yield 1; - yield 2; - - return 3; -})(); - -// descructuring -// list() style -list($id1, $name1) = $data[0]; - -// [] style -[$id1, $name1] = $data[0]; +'A single-quoted string'; +"A double-quoted string"; // heredoc $a = <<other_thing()}" -// Unlock? -if(!defined('UNLOCK') || !UNLOCK) - die(); -// Load the parent archive class -require_once(ROOT_PATH.'/classes/archive.class.php'); +/* Functions */ + +function &byref() { + $x = array(); + return $x; +} + +public abstract function thing(mysqli $mysqli, int FOO + BAR, ?mysqli $mysqli): mysqli $mysqli; + +function sort_on(array &$array, string $key) { + usort($array, function ($a, $b) use($key) { return $a <=> $b; }); +} + +// No "use" +$example = function () { + some_fn($message); +}; + +// Inherit $message +$example = function () use ($message) { + some_fn($message); +}; + +// A generator +$gen = (function() { + yield 1; + yield 2; + + return 3; +})(); + +$fn = fn($x) => fn($y) => $x * $y + $z; +fn(array $x) => $x; +static fn(): int => $x; +fn($x = 42) => $x; +fn(&$x) => $x; +fn&($x) => $x; +fn($x, ...$rest) => $rest; + + +/* Classes */ + +class Foo extends AbstractFoo implements Bar { +} + +//Anonymous class example +$app->setLogger(new class implements Logger { + public function log(string $msg) { + echo $msg; + } +}); + +class ClassB +{ + use TraitA, TraitB, TraitC { + TraitB::foo insteadof TraitA; + } +} class Zip\Zipp { } -/** - * Zip class - * - * @author Manni - * @copyright Copyright (c) 2006, Manni - * @version 1.0 - * @link http://www.pkware.com/business_and_developers/developer/popups/appnote.txt - * @link http://mannithedark.is-a-geek.net/ - * @since 1.0 - * @package fnord.bb - * @subpackage archive - */ class Zip extends Archive { - /** - * Outputs the zip file - * - * This function creates the zip file with the dirs and files given. - * If the optional parameter $file is given, the zip file is will be - * saved at that location. Otherwise the function returns the zip file's content. - * - * @access public - * - * @link http://www.pkware.com/business_and_developers/developer/popups/appnote.txt - * @param string $filename The path where the zip file will be saved - * - * @return bool|string Returns either true if the fil is sucessfully created or the content of the zip file - */ function out($filename = false) { // Empty output $file_data = array(); // Data of the file part $cd_data = array(); // Data of the central directory + } +} - // Sort dirs and files by path length - uksort($this->dirs, 'sort_by_length'); - uksort($this->files, 'sort_by_length'); - - // Handle dirs - foreach($this->dirs as $dir) { - $dir .= '/'; - // File part - - // Reset dir data - $dir_data = ''; - - // Local file header - $dir_data .= "\x50\x4b\x03\x04"; // Local file header signature - $dir_data .= pack("v", 10); // Version needed to extract - $dir_data .= pack("v", 0); // General purpose bit flag - $dir_data .= pack("v", 0); // Compression method - $dir_data .= pack("v", 0); // Last mod file time - $dir_data .= pack("v", 0); // Last mod file date - $dir_data .= pack("V", 0); // crc-32 - $dir_data .= pack("V", 0); // Compressed size - $dir_data .= pack("V", 0); // Uncompressed size - $dir_data .= pack("v", strlen($dir)); // File name length - $dir_data .= pack("v", 0); // Extra field length - - $dir_data .= $dir; // File name - $dir_data .= ''; // Extra field (is empty) - - // File data - $dir_data .= ''; // Dirs have no file data - - // Data descriptor - $dir_data .= pack("V", 0); // crc-32 - $dir_data .= pack("V", 0); // Compressed size - $dir_data .= pack("V", 0); // Uncompressed size - - // Save current offset - $offset = strlen(implode('', $file_data)); - - // Append dir data to the file part - $file_data[] = $dir_data; - - // Central directory - - // Reset dir data - $dir_data = ''; - - // File header - $dir_data .= "\x50\x4b\x01\x02"; // Local file header signature - $dir_data .= pack("v", 0); // Version made by - $dir_data .= pack("v", 10); // Version needed to extract - $dir_data .= pack("v", 0); // General purpose bit flag - $dir_data .= pack("v", 0); // Compression method - $dir_data .= pack("v", 0); // Last mod file time - $dir_data .= pack("v", 0); // Last mod file date - $dir_data .= pack("V", 0); // crc-32 - $dir_data .= pack("V", 0); // Compressed size - $dir_data .= pack("V", 0); // Uncompressed size - $dir_data .= pack("v", strlen($dir)); // File name length - $dir_data .= pack("v", 0); // Extra field length - $dir_data .= pack("v", 0); // File comment length - $dir_data .= pack("v", 0); // Disk number start - $dir_data .= pack("v", 0); // Internal file attributes - $dir_data .= pack("V", 16); // External file attributes - $dir_data .= pack("V", $offset); // Relative offset of local header - - $dir_data .= $dir; // File name - $dir_data .= ''; // Extra field (is empty) - $dir_data .= ''; // File comment (is empty) - - /* - // Data descriptor - $dir_data .= pack("V", 0); // crc-32 - $dir_data .= pack("V", 0); // Compressed size - $dir_data .= pack("V", 0); // Uncompressed size - */ - - // Append dir data to the central directory data - $cd_data[] = $dir_data; +class User +{ + public int $id; + public ?string $name; + + public function __construct(int $id, ?string $name) + { + $this->id = $id; + $this->name = $name; } +} - // Handle files - foreach($this->files as $name => $file) { - // Get values - $content = $file[0]; - - // File part - - // Reset file data - $fd = ''; - - // Detect possible compressions - // Use deflate - if(function_exists('gzdeflate')) { - $method = 8; - - // Compress file content - $compressed_data = gzdeflate($content); - - // Use bzip2 - } elseif(function_exists('bzcompress')) { - $method = 12; - - // Compress file content - $compressed_data = bzcompress($content); - - // No compression - } else { - $method = 0; - - // Do not compress the content :P - $compressed_data = $content; - } - - // Local file header - $fd .= "\x50\x4b\x03\x04"; // Local file header signature - $fd .= pack("v", 20); // Version needed to extract - $fd .= pack("v", 0); // General purpose bit flag - $fd .= pack("v", $method); // Compression method - $fd .= pack("v", 0); // Last mod file time - $fd .= pack("v", 0); // Last mod file date - $fd .= pack("V", crc32($content)); // crc-32 - $fd .= pack("V", strlen($compressed_data)); // Compressed size - $fd .= pack("V", strlen($content)); // Uncompressed size - $fd .= pack("v", strlen($name)); // File name length - $fd .= pack("v", 0); // Extra field length - - $fd .= $name; // File name - $fd .= ''; // Extra field (is empty) - - // File data - $fd .= $compressed_data; - - // Data descriptor - $fd .= pack("V", crc32($content)); // crc-32 - $fd .= pack("V", strlen($compressed_data)); // Compressed size - $fd .= pack("V", strlen($content)); // Uncompressed size - - // Save current offset - $offset = strlen(implode('', $file_data)); - - // Append file data to the file part - $file_data[] = $fd; - - // Central directory - - // Reset file data - $fd = ''; - - // File header - $fd .= "\x50\x4b\x01\x02"; // Local file header signature - $fd .= pack("v", 0); // Version made by - $fd .= pack("v", 20); // Version needed to extract - $fd .= pack("v", 0); // General purpose bit flag - $fd .= pack("v", $method); // Compression method - $fd .= pack("v", 0); // Last mod file time - $fd .= pack("v", 0); // Last mod file date - $fd .= pack("V", crc32($content)); // crc-32 - $fd .= pack("V", strlen($compressed_data)); // Compressed size - $fd .= pack("V", strlen($content)); // Uncompressed size - $fd .= pack("v", strlen($name)); // File name length - $fd .= pack("v", 0); // Extra field length - $fd .= pack("v", 0); // File comment length - $fd .= pack("v", 0); // Disk number start - $fd .= pack("v", 0); // Internal file attributes - $fd .= pack("V", 32); // External file attributes - $fd .= pack("V", $offset); // Relative offset of local header - - $fd .= $name; // File name - $fd .= ''; // Extra field (is empty) - $fd .= ''; // File comment (is empty) - - /* - // Data descriptor - $fd .= pack("V", crc32($content)); // crc-32 - $fd .= pack("V", strlen($compressed_data)); // Compressed size - $fd .= pack("V", strlen($content)); // Uncompressed size - */ - // Append file data to the central directory data - $cd_data[] = $fd; - } +/* Traits */ + +trait SomeTrait { + // Some visibility + const PUBLIC_CONST_A = 1; + public const PUBLIC_CONST_B = 2; + protected const PROTECTED_CONST = 3; + private const PRIVATE_CONST = 4; - // Digital signature - $digital_signature = ''; - $digital_signature .= "\x50\x4b\x05\x05"; // Header signature - $digital_signature .= pack("v", 0); // Size of data - $digital_signature .= ''; // Signature data (is empty) - - $tmp_file_data = implode('', $file_data); // File data - $tmp_cd_data = implode('', $cd_data). // Central directory - $digital_signature; // Digital signature - - // End of central directory - $eof_cd = ''; - $eof_cd .= "\x50\x4b\x05\x06"; // End of central dir signature - $eof_cd .= pack("v", 0); // Number of this disk - $eof_cd .= pack("v", 0); // Number of the disk with the start of the central directory - $eof_cd .= pack("v", count($cd_data)); // Total number of entries in the central directory on this disk - $eof_cd .= pack("v", count($cd_data)); // Total number of entries in the central directory - $eof_cd .= pack("V", strlen($tmp_cd_data)); // Size of the central directory - $eof_cd .= pack("V", strlen($tmp_file_data)); // Offset of start of central directory with respect to the starting disk number - $eof_cd .= pack("v", 0); // .ZIP file comment length - $eof_cd .= ''; // .ZIP file comment (is empty) - - // Content of the zip file - $data = $tmp_file_data. - // $extra_data_record. - $tmp_cd_data. - $eof_cd; - - // Return content? - if(!$filename) - return $data; - - // Write to file - return file_put_contents($filename, $data); + function afunc(string $arg, SomeInterface $arg2, callable $arg3, object $arg4): void { + echo "hello"; + if (1 <=> 1) { + echo "yep!"; + } } +} - /** - * Load a zip file - * - * This function loads the files and dirs from a zip file from the harddrive. - * - * @access public - * - * @param string $file The path to the zip file - * @param bool $reset Reset the files and dirs before adding the zip file's content? - * - * @return bool Returns true if the file was loaded sucessfully - */ - function load_file($file, $reset = true) { - // Check whether the file exists - if(!file_exists($file)) - return false; - // Load the files content - $content = @file_get_contents($file); +/* Interfaces */ - // Return false if the file cannot be opened - if(!$content) - return false; +interface SomeInterface { + function interfaceFunc(bool $arg): iterable; + function nullableTypes(?bool $arg): ?iterable; +} - // Read the zip - return $this->load_string($content, $reset); - } - /** - * Load a zip string - * - * This function loads the files and dirs from a string - * - * @access public - * - * @param string $string The string the zip is generated from - * @param bool $reset Reset the files and dirs before adding the zip file's content? - * - * @return bool Returns true if the string was loaded sucessfully - */ - function load_string($string, $reset = true) { - // Reset the zip? - if($reset) { - $this->dirs = array(); - $this->files = array(); - } +/* Imports */ - // Get the starting position of the end of central directory record - $start = strpos($string, "\x50\x4b\x05\x06"); +use some\namespace\ClassA; +use some\namespace\ClassB as B; +use function some\namespace\fn_a; +use const some\namespace\ConstA; +use Class1, /*Class2, */Class3; - // Error - if($start === false) - die('Could not find the end of central directory record'); - - // Get the ecdr - $eof_cd = substr($string, $start+4, 18); - - // Unpack the ecdr infos - $eof_cd = unpack('vdisc1/'. - 'vdisc2/'. - 'ventries1/'. - 'ventries2/'. - 'Vsize/'. - 'Voffset/'. - 'vcomment_lenght', $eof_cd); - - // Do not allow multi disc zips - if($eof_cd['disc1'] != 0) - die('multi disk stuff is not yet implemented :/'); - - // Save the interesting values - $cd_entries = $eof_cd['entries1']; - $cd_size = $eof_cd['size']; - $cd_offset = $eof_cd['offset']; - - // Get the central directory record - $cdr = substr($string, $cd_offset, $cd_size); - - // Reset the position and the list of the entries - $pos = 0; - $entries = array(); - - // Handle cdr - while($pos < strlen($cdr)) { - // Check header signature - // Digital signature - if(substr($cdr, $pos, 4) == "\x50\x4b\x05\x05") { - // Get digital signature size - $tmp_info = unpack('vsize', substr($cdr, $pos + 4, 2)); - - // Read out the digital signature - $digital_sig = substr($header, $pos + 6, $tmp_info['size']); - - break; - } - - // Get file header - $header = substr($cdr, $pos, 46); - - // Unpack the header information - $header_info = @unpack('Vheader/'. - 'vversion_made_by/'. - 'vversion_needed/'. - 'vgeneral_purpose/'. - 'vcompression_method/'. - 'vlast_mod_time/'. - 'vlast_mod_date/'. - 'Vcrc32/'. - 'Vcompressed_size/'. - 'Vuncompressed_size/'. - 'vname_length/'. - 'vextra_length/'. - 'vcomment_length/'. - 'vdisk_number/'. - 'vinternal_attributes/'. - 'Vexternal_attributes/'. - 'Voffset', - $header); - - // Valid header? - if($header_info['header'] != 33_639_248) - return false; - - // New position - $pos += 46; - - // Read out the file name - $header_info['name'] = substr($cdr, $pos, $header_info['name_length']); - - // New position - $pos += $header_info['name_length']; - - // Read out the extra stuff - $header_info['extra'] = substr($cdr, $pos, $header_info['extra_length']); - - // New position - $pos += $header_info['extra_length']; +use some\namespace\{ClassA, ClassB, ClassC as C}; +use function some\namespace\{fn_a, fn_b, fn_c}; +use const some\namespace\{ConstA, ConstB, ConstC}; +use some\name\{function some_fn, const Foo\BAR, SomeClass}; - // Read out the comment - $header_info['comment'] = substr($cdr, $pos, $header_info['comment_length']); +use const some\namespace\{ + ConstA, + #ConstB, + ConstC +}; - // New position - $pos += $header_info['comment_length']; - // Append this file/dir to the entry list - $entries[] = $header_info; - } +/* Namespaces */ + +namespace some\namespace; + + +/* Assignments */ - // Check whether all entries where read sucessfully - if(count($entries) != $cd_entries) +list($id1, $name1) = $data[0]; +[$id1, $name1] = $data[0]; +const A = f(1, 2, g(3, 4, $my_var[0])), B = "abc"; + + +/* Conditionals */ + +if(!defined('UNLOCK') || !UNLOCK) + die(); + +if(function_exists('gzdeflate')) { + $method = 8; + $compressed_data = gzdeflate($content); +} elseif(function_exists('bzcompress')) { + $method = 12; + $compressed_data = bzcompress($content); +} else { + $compressed_data = $content; +} + +switch($header_info['compression_method']) { + case 0: + $content = $data; + break; + + case 8: + $content = gzinflate($data); + break; + + case 12: + if(!function_exists('bzdecompress')) return false; + break; - // Handle files/dirs - foreach($entries as $entry) { - // Is a dir? - if($entry['external_attributes'] & 16) { - $this->add_dir($entry['name']); - continue; - } - - // Get local file header - $header = substr($string, $entry['offset'], 30); - - // Unpack the header information - $header_info = @unpack('Vheader/'. - 'vversion_needed/'. - 'vgeneral_purpose/'. - 'vcompression_method/'. - 'vlast_mod_time/'. - 'vlast_mod_date/'. - 'Vcrc32/'. - 'Vcompressed_size/'. - 'Vuncompressed_size/'. - 'vname_length/'. - 'vextra_length', - $header); - - // Valid header? - if($header_info['header'] != 67_324_752) - return false; - - // Get content start position - $start = $entry['offset'] + 30 + $header_info['name_length'] + $header_info['extra_length']; - - // Get the compressed data - $data = substr($string, $start, $header_info['compressed_size']); - - // Detect compression type - switch($header_info['compression_method']) { - // No compression - case 0: - // Ne decompression needed - $content = $data; - break; - - // Gzip - case 8: - if(!function_exists('gzinflate')) - return false; - - // Uncompress data - $content = gzinflate($data); - break; - - // Bzip2 - case 12: - if(!function_exists('bzdecompress')) - return false; - - // Decompress data - $content = bzdecompress($data); - break; - - // Compression not supported -> error - default: - return false; - } - - // Try to add file - if(!$this->add_file($entry['name'], $content)) - return false; - } + default: + return false; +} + +/* Loops */ - return true; +foreach($this->files as $name => $file) { + $content = $file[0]; + $fd .= "\x50\x4b\x03\x04"; // Local file header signature + $fd .= pack("v", 20); // Version needed to extract + $fd .= pack("V", crc32($content)); // crc-32 + $fd .= pack("V", strlen($compressed_data)); // Compressed size +} + +while($pos < strlen($cdr)) { + if(substr($cdr, $pos, 4) == "\x50\x4b\x05\x05") { + $tmp_info = unpack('vsize', substr($cdr, $pos + 4, 2)); + $digital_sig = substr($header, $pos + 6, $tmp_info['size']); + break; } } + +/* Exceptions */ + +class Test { + public function testing() { + try { + throw new MyException(); + } catch (MyException | MyOtherException $e) { + var_dump(get_class($e)); + } + } +} + ?> + +

Hello world!

diff -Nru ruby-rouge-3.21.0/spec/visual/samples/postscript ruby-rouge-3.26.1/spec/visual/samples/postscript --- ruby-rouge-3.21.0/spec/visual/samples/postscript 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/postscript 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,107 @@ +%!PS-Adobe-3.0 +%%BoundingBox: 38 24 574 768 +%%Title: Enscript Output +% +% Procedures. +% + +/_S { % save current state + /_s save def +} def +/_R { % restore from saved state + _s restore +} def + +/S { % showpage protecting gstate + gsave + showpage + grestore +} bind def + +/MF { % fontname newfontname -> - make a new encoded font + /newfontname exch def + /fontname exch def + + /fontdict fontname findfont def + /newfont fontdict maxlength dict def + + fontdict { + exch + dup /FID eq { + % skip FID pair + pop pop + } { + % copy to the new font dictionary + exch newfont 3 1 roll put + } ifelse + } forall + + newfont /FontName newfontname put + + % insert only valid encoding vectors + encoding_vector length 256 eq { + newfont /Encoding encoding_vector put + } if + + newfontname newfont definefont pop +} def + +% Column separator lines. +/column_lines { + gsave + .1 setlinewidth + 0 d_footer_h translate + /cw d_output_w cols div def + 1 1 cols 1 sub { + cw mul 0 moveto + 0 d_output_h rlineto stroke + } for + grestore +} def + +% Page prefeed +/page_prefeed { % bool -> - + statusdict /prefeed known { + statusdict exch /prefeed exch put + } { + pop + } ifelse +} def + +%%BeginResource: procset Enscript-Encoding-88591 1.6 6 +/encoding_vector [ +/udieresis /yacute /thorn /ydieresis +] def +%%EndResource +%%EndProlog +%%BeginSetup +% Pagedevice definitions: +gs_languagelevel 1 gt { + << + /PageSize [612 792] + >> setpagedevice +} if + +%%EndSetup +%%Page: (1) 1 +%%BeginPageSetup +_S +38 24 translate +/pagenum 1 def +/fname (t.txt) def +/fdir (.) def +/ftail (t.txt) def +/fmodstr (ti. feb. 19 15:28:20 2019) def +/pagenumstr (1) def +/user_header_p false def +/user_footer_p false def +%%EndPageSetup +do_header +5 687 M +(text]\(https://example.com\)\)) s +5 588 M +_R +S +%%Trailer +%%Pages: 1 +%%EOF diff -Nru ruby-rouge-3.21.0/spec/visual/samples/powershell ruby-rouge-3.26.1/spec/visual/samples/powershell --- ruby-rouge-3.21.0/spec/visual/samples/powershell 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/powershell 2021-09-17 19:59:49.000000000 +0000 @@ -52,8 +52,34 @@ thing = "table" } +$my_complex_hash = @{ + # comment + foo = { + if ($var1 -eq $var2) + { + return $true + } + } +} + $my_array = @("my" "array") +$myobject = [PSCustomObject]@{ + Name = 'Alice'; + Age = 42; +} + +$myarray = @( + [PSCustomObject]@{ + Name = 'Bob'; + Age = 31; + }, + [PSCustomObject]@{ + Name = 'Charlie'; + Age = 41; + } +) + ########################### # Commands ########################### diff -Nru ruby-rouge-3.21.0/spec/visual/samples/reasonml ruby-rouge-3.26.1/spec/visual/samples/reasonml --- ruby-rouge-3.21.0/spec/visual/samples/reasonml 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/reasonml 2021-09-17 19:59:49.000000000 +0000 @@ -1,3 +1,5 @@ +let x = 6 // This is single line comment + let c: char = 'A'; /* comment with link https://example and - = */ let respond_no_content = reqd => { @@ -43,6 +45,8 @@ /* comment ****/ /* comment *****/ +// A single line comment + let testingNotQuiteEndOfLineComments = [ "Item 1" /* Comment For First Item */, "Item 2" /* Comment For Second Item */, diff -Nru ruby-rouge-3.21.0/spec/visual/samples/rescript ruby-rouge-3.26.1/spec/visual/samples/rescript --- ruby-rouge-3.21.0/spec/visual/samples/rescript 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/rescript 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,1574 @@ +// Single line comment +let foo = #Bar +let s1 = "s1" +let s2 = `HI ${s2} BYE` +let s3 = j`HI ${s2} BYE` + +let f = _ => 2 + +let \"let" = 2 +let \"let" = "foo bar \n" +let \"let" = '\'' + +module Person = { + type t = Teacher | Director | Student(string) + + let greeting = person => + switch person { + | Teacher => "Hey Professor!" + | Director => "Hello Director." + | Student("Richard") => "Still here Ricky?" + | Student(other) => "Hey, " ++ other ++ "." + } +} + +module Button = { + @react.component + let make = (~count: int, ~onClick) => { + let times = switch count { + | 1 => "once" + | 2 => "twice" + | n => Belt.Int.toString(n) ++ " times" + } + + let msg = "Click me " ++ times + + + } +} + +/* + +## Properties: + +- size: The total number of items. +*/ + +type nodeColor = + | Red + | Black + +/* +Property of a red-black tree, taken from Wikipedia: +1. A node is either red or black. +2. Root is black. +3. Leaves are all null and considered black. +4. Both children of a red node are black. +5. Every path from a node to any of its descendent leaves contains the same +number of black nodes. +*/ + +type rec node<'value> = { + mutable left: option>, + mutable right: option>, + mutable parent: option>, + mutable sum: float, + mutable color : nodeColor, + mutable height: float, + mutable value: 'value, +} + +type t<'value> = { + mutable size: int, + mutable root: option>, + compare: (. 'value, 'value) => int, +} + +let createNode = (~color, ~value, ~height) => + {left:None, right:None, parent:None, sum:0., height, value, color} + +external castNotOption: option<'a> => 'a = "%identity" + +let updateSum = (node) => { + let leftSum = switch node.left { + | None => 0. + | Some(left) => left.sum + } + let rightSum = switch node.right { + | None => 0. + | Some(right) => right.sum + } + node.sum = leftSum +. rightSum +. node.height +} + +/* Update the sum for the node and parents recursively. */ +let rec updateSumRecursive = (rbt, node) => { + updateSum(node) + switch node.parent { + | None => () + | Some(parent) => + rbt->updateSumRecursive(parent) + } +} + +let grandParentOf = node => { + switch node.parent { + | None => None + | Some(ref_) => ref_.parent + } +} + +let isLeft = node => { + switch node.parent { + | None => false + | Some(parent) => Some(node) === parent.left + } +} + +let leftOrRightSet = (~node, x, value) => { + isLeft(node) ? x.left=value : x.right=value +} + +let siblingOf = node => { + if isLeft(node) { + castNotOption(node.parent).right + } else { + castNotOption(node.parent).left + } +} + +let uncleOf = node => { + switch grandParentOf(node) { + | None => None + | Some(grandParentOfNode) => + if isLeft(castNotOption(node.parent)) { + grandParentOfNode.right + } else { + grandParentOfNode.left + } + } +} + +let rec findNode = (rbt, node, value) => { + switch node { + | None => None + | Some(node) => + let cmp = rbt.compare(. value, node.value) + if cmp === 0 { + Some(node) + } else if cmp < 0 { + findNode(rbt, node.left, value) + } else { + findNode(rbt, node.right, value) + } + } +} + +let has = (rbt, value) => findNode(rbt, rbt.root, value) !== None + +let rec peekMinNode = node => switch node { + | None => None + | Some(node) => + node.left === None ? Some(node) : node.left->peekMinNode +} + +let rec peekMaxNode = node => switch node { + | None => None + | Some(node) => + node.right === None ? Some(node) : node.right->peekMaxNode +} + +let rotateLeft = (rbt, node) => { + let parent = node.parent + let right = node.right + switch parent { + | Some(parent) => + parent->leftOrRightSet(~node, right) + | None => + rbt.root = right + } + node.parent = right + let right = right->castNotOption // precondition + let rightLeft = right.left + node.right = rightLeft + switch rightLeft { + | Some(rightLeft) => + rightLeft.parent = Some(node) + | None => + () + } + right.parent = parent + right.left = Some(node) + updateSum(node) + updateSum(right) +} + +let rotateRight = (rbt, node) => { + let parent = node.parent + let left = node.left + switch parent { + | Some(parent) => + parent->leftOrRightSet(~node, left) + | None => + rbt.root = left + } + node.parent = left + let left = left->castNotOption // precondition + let leftRight = left.right + node.left = leftRight + switch leftRight { + | Some(leftRight) => + leftRight.parent = Some(node) + | None => + () + } + left.parent = parent + left.right = Some(node) + updateSum(node) + updateSum(left) +} + +let rec findInsert = (rbt, node, nodeToInsert, value) => { + switch node { + | None => None + | Some(node) => { + let cmp = rbt.compare(. value, node.value) + if cmp === 0 { + Some(node) + } else { + if cmp < 0 { + if node.left !== None { + rbt->findInsert(node.left, nodeToInsert, value) + } else { + nodeToInsert.parent = Some(node) + node.left = Some(nodeToInsert) + None + } + } else { + if node.right !== None { + rbt->findInsert(node.right, nodeToInsert, value) + } else { + nodeToInsert.parent = Some(node) + node.right = Some(nodeToInsert) + None + } + } + } + } + } +} + +// After adding the node, we need to operate on it to preserve the tree's +// properties by filtering it through a series of cases. It'd be easier if +// there's tail recursion in JavaScript, as some cases fix the node but +// restart the cases on the node's ancestor. We'll have to use loops for now. + +let rec _addLoop = (rbt, currentNode) => { + // Case 1: node is root. Violates 1. Paint it black. + if Some(currentNode) === rbt.root { + currentNode.color = Black + } + + // Case 2: parent black. No properties violated. After that, parent is sure + // to be red. + else if (currentNode.parent->castNotOption).color === Black { + () + } + + // Case 3: if node's parent and uncle are red, they are painted black. + // Their parent (node's grandparent) should be painted red, and the + // grandparent red. Note that node certainly has a grandparent, since at + // this point, its parent's red, which can't be the root. + + // After the painting, the grandparent might violate 2 or 4. + else if({ + let uncle = uncleOf(currentNode) + uncle !== None && (uncle->castNotOption).color === Red + }) { + (currentNode.parent->castNotOption).color = Black + (uncleOf(currentNode)->castNotOption).color = Black + (grandParentOf(currentNode)->castNotOption).color = Red + _addLoop(rbt, grandParentOf(currentNode)->castNotOption) + } + else { + // At this point, uncle is either black or doesn't exist. + + // Case 4: parent red, uncle black, node is right child, parent is left + // child. Do a left rotation. Then, former parent passes through case 5. + let currentNode = + if !isLeft(currentNode) && isLeft(currentNode.parent->castNotOption) { + rotateLeft(rbt, currentNode.parent->castNotOption) + currentNode.left->castNotOption + } else if isLeft(currentNode) && !isLeft(currentNode.parent->castNotOption) { + rotateRight(rbt, currentNode.parent->castNotOption) + currentNode.right->castNotOption + } else { + currentNode + } + + // Case 5: parent red, uncle black, node is left child, parent is left + // child. Right rotation. Switch parent and grandparent's color. + (currentNode.parent->castNotOption).color = Black + (grandParentOf(currentNode)->castNotOption).color = Red + if isLeft(currentNode) { + rotateRight(rbt, grandParentOf(currentNode)->castNotOption) + } else { + rotateLeft(rbt, grandParentOf(currentNode)->castNotOption) + } + } +} + +let add = (rbt, value, ~height) => { + // Again, make sure to not pass a value already in the tree. + // + // _Returns:_ value added. + rbt.size = rbt.size + 1 + let nodeToInsert = createNode(~value, ~color=Red, ~height) + let inserted = + if rbt.root === None { + rbt.root = Some(nodeToInsert) + true + } + else { + let foundNode = findInsert(rbt, rbt.root, nodeToInsert, value) + foundNode === None + } + if inserted { + rbt->updateSumRecursive(nodeToInsert) + + _addLoop(rbt, nodeToInsert) + Some(nodeToInsert) + } else { + None + } +} + + +// To simplify removal cases, we can notice this: +// 1. Node has no child. +// 2. Node has two children. Select the smallest child on the right branch +// (leftmost) and copy its value into the node to delete. This replacement node +// certainly has less than two children or it wouldn't be the smallest. Then +// delete this replacement node. +// 3. Node has one child. +// They all come down to removing a node with maximum one child. +let removeNode = (rbt, node) => { + let nodeToRemove = + switch (node.left, node.right) { + | (Some(_), Some(_)) => + let successor = peekMinNode(node.right)->castNotOption + node.value = successor.value + node.height = successor.height + successor + | _ => node + } + // At this point, the node to remove has only one child. + let successor = switch nodeToRemove.left { + | None => nodeToRemove.right + | left => left + } + let (successor, isLeaf) = switch successor { + | None => + let leaf = createNode(~value=%bs.raw("0"), ~color=Black, ~height=0.) + let isLeaf = (. x) => x === leaf; + (leaf, isLeaf) + | Some(successor) => + (successor, (. _) => false) + } + let nodeParent = nodeToRemove.parent + successor.parent = nodeParent + switch nodeParent { + | None => () + | Some(parent) => + parent->leftOrRightSet(~node=nodeToRemove, Some(successor)) + } + + rbt->updateSumRecursive(successor) + + // We're done if node's red. If it's black and its child that took its place + // is red, change it to black. If both are black, we do cases checking like + // in insert. + if nodeToRemove.color === Black { + if successor.color === Red { + successor.color = Black + if successor.parent === None { + rbt.root = Some(successor) + } + } else { + let break = ref(false) + let successorRef = ref(successor) + while !break.contents { + let successor = successorRef.contents + // Case 1: node is root. Done. + switch successor.parent { + | None => + rbt.root = Some(successor) + break.contents = true + | Some(successorParent) => + // Case 2: sibling red. Flip color of P and S. Left rotate P. + let sibling = siblingOf(successor) + if sibling !== None && (sibling->castNotOption).color === Red { + successorParent.color = Red + (sibling->castNotOption).color = Black + if isLeft(successor) { + rotateLeft(rbt, successorParent) + } else { + rotateRight(rbt, successorParent) + } + } + + // Case 3: parent, sibling and sibling children all black. Paint + // sibling red. Rebalance parent. + let sibling = siblingOf(successor) + let siblingNN = sibling->castNotOption + if + successorParent.color === Black && + ( sibling === None || + ( siblingNN.color === Black && + ( siblingNN.left === None || + (siblingNN.left->castNotOption).color === Black ) && + ( siblingNN.right === None || + (siblingNN.right->castNotOption).color === Black))) + { + if sibling !== None { + siblingNN.color = Red + } + successorRef.contents = successorParent + // continue + } else if + // Case 4: sibling and sibling children black. Node parent red. Swap + // color of sibling and node parent. + successorParent.color === Red && + ( sibling === None || + ( siblingNN.color === Black && + ( siblingNN.left === None || + (siblingNN.left->castNotOption).color === Black) && + ( siblingNN.right === None || + (siblingNN.right->castNotOption).color === Black))) + { + if sibling !== None { + siblingNN.color = Red + } + successorParent.color = Black + break.contents = true + } else if + // Case 5: sibling black, sibling left child red, right child black, + // node is left child. Rotate right sibling. Swap color of sibling and + // its new parent. + sibling !== None && (sibling->castNotOption).color === Black + { + let sibling = sibling->castNotOption + if + isLeft(successor) && + (sibling.right === None || (sibling.right->castNotOption).color === Black) && + sibling.left !== None && + (sibling.left->castNotOption).color === Red { + sibling.color = Red + (sibling.left->castNotOption).color = Black + rotateRight(rbt, sibling) + } else if + !isLeft(successor) && + (sibling.left === None || (sibling.left->castNotOption).color === Black) && + sibling.right !== None && + (sibling.right->castNotOption).color === Red + { + sibling.color = Red + (sibling.right->castNotOption).color = Black + rotateLeft(rbt, sibling) + } + break.contents = true + } else { + // Case 6: sibling black, sibling right child red, node is left child. + // Rotate left node parent. Swap color of parent and sibling. Paint + // sibling right child black. + let sibling = siblingOf(successor) + let sibling = sibling->castNotOption + sibling.color = successorParent.color + if isLeft(successor) { + (sibling.right->castNotOption).color = Black + rotateRight(rbt, successorParent) + } else { + (sibling.left->castNotOption).color = Black + rotateLeft(rbt, successorParent) + } + } + } + } + } + } + // Don't forget to detatch the artificially created leaf. + if isLeaf(. successor) { + if rbt.root === Some(successor) { + rbt.root = None + } + switch successor.parent { + | None => () + | Some(parent) => + parent->leftOrRightSet(~node=successor, None) + } + } +} + +let remove = (rbt, value) => { + switch findNode(rbt, rbt.root, value) { + | Some(node) => + rbt->removeNode(node) + rbt.size = rbt.size - 1 + true + | None => + false + } +} + +let rec findNodeThroughCallback = (rbt, node, cb) => { + switch node { + | None => None + | Some(node) => + let cmp = cb(. node) + if cmp === 0 { + Some(node) + } else if cmp < 0 { + findNodeThroughCallback(rbt, node.left, cb) + } else { + findNodeThroughCallback(rbt, node.right, cb) + } + } +} + +let removeThroughCallback = (rbt, cb) => { + switch findNodeThroughCallback(rbt, rbt.root, cb) { + | Some(node) => + rbt->removeNode(node) + rbt.size = rbt.size - 1 + true + | None => + false + } +} + +let make = (~compare) => {size: 0, root: None, compare} + +let makeWith = (array, ~compare) => { + let rbt = make(~compare) + array->Js.Array2.forEach(((value, height)) => add(rbt,value, ~height)->ignore) + rbt +} + +// sum of the heights of the elements in [lhs ... rhs] +// both lhs and rhs are optional +let rec heightOfInterval = (rbt, node, lhs, rhs) => { + switch node { + | None => 0. + | Some(n) => + //Js.log4("heightOfInterval n:", n.value, lhs, rhs) + if lhs === None && rhs === None { + n.sum + } else if lhs !== None && rbt.compare(. n.value, lhs->castNotOption) < 0 { + // to the lhs of the interval + rbt->heightOfInterval(n.right, lhs, rhs) + } else if rhs !== None && rbt.compare(. n.value, rhs->castNotOption) > 0 { + // to the rhs of the interval + rbt->heightOfInterval(n.left, lhs, rhs) + } else { + // in the interval + n.height +. + rbt->heightOfInterval(n.left, lhs, None) +. + rbt->heightOfInterval(n.right, None, rhs) + } + } +} + +let heightOfInterval = (rbt, lhs, rhs) => { + //Js.log("-----------") + heightOfInterval(rbt, rbt.root, lhs, rhs) +} + +// Return a node at y such that y <= top < y + node.height +let rec firstVisibleNode = (node, top) => { + switch node { + | None => None + | Some(node) => + //Js.log4("firstVisibleNode", node.value, "top:", top) + if node.sum <= top { + // no node is visible + None + } else { + let nodeHeight = node.height + let sumLeft = switch node.left { + | None => 0.0 + | Some(left) => left.sum + } + if sumLeft > top { + firstVisibleNode(node.left, top) + } else if sumLeft +. nodeHeight > top { + // found + Some(node) + } else { + let offset = sumLeft +. nodeHeight + firstVisibleNode(node.right, top -. offset) + } + } + } +} + +let lastVisibleNode = (node, top) => { + switch firstVisibleNode(node, top) { + | None => + node->peekMaxNode + | first => first + } +} + +// Find the value of the first visible node starting from top +let firstVisibleValue = (rbt, ~top) => + switch firstVisibleNode(rbt.root, top) { + | None => None + | Some(node) => Some(node.value) +} + +let rec leftmost = node => switch node.left { + | None => node + | Some(node) => node->leftmost +} + +let rec firstRightParent = node => { + switch node.parent { + | None => None + | Some(parent) => + isLeft(node) ? Some(parent) : parent->firstRightParent + } +} + +let nextNode = node => { + switch node.right { + | None => + node->firstRightParent + | Some(right) => + Some(right->leftmost) + } +} + +let rec sumLeftSpine = (node, ~fromRightChild) => { + let leftSpine = switch node.left { + | None => node.height + | Some(left) => fromRightChild ? node.height +. left.sum : 0.0 + } + switch node.parent { + | None => + leftSpine + | Some(parent) => + leftSpine +. parent->sumLeftSpine(~fromRightChild = parent.right === Some(node)) + } +} + +let getY = node => + node->sumLeftSpine(~fromRightChild=true) -. node.height + +let rec iterate = (~inclusive, firstNode, lastNode, ~callback) => { + switch firstNode { + | None => () + | Some(node) => + if inclusive { callback(. node) } + if firstNode !== lastNode { + if !inclusive { callback (.node) } + iterate(~inclusive, node->nextNode, lastNode, ~callback) + } + } +} + +let rec iterateWithY = (~y=?, ~inclusive, firstNode, lastNode, ~callback) => { + switch firstNode { + | None => () + | Some(node) => + let y = switch y { + | None => node->getY + | Some(y) => y + } + if inclusive { + callback(. node, y) + } + if firstNode !== lastNode { + if !inclusive { + callback (.node, y) + } + iterateWithY(~y=y+.node.height, ~inclusive, node->nextNode, lastNode, ~callback) + } + } +} + +let rec updateSum = (node, ~delta) => switch node { + | None => () + | Some(node) => + node.sum = node.sum +. delta + node.parent->updateSum(~delta) +} + +let updateHeight = (node, ~height) => { + let delta = height -. node.height + node.height = height + Some(node)->updateSum(~delta) +} + +type oldNewVisible<'value> = { + mutable old: array<'value>, + mutable new: array<'value>, +}; + +let getAnchorDelta = (rbt, ~anchor) => { + switch anchor { + | None => 0.0 + | Some((value, y)) => + switch rbt->findNode(rbt.root, value) { + | Some(node) => y -. node->getY + | None => 0.0 + } + } +} + +let onChangedVisible = + ( + ~anchor=None, + rbt, + ~oldNewVisible, + ~top as top_, + ~bottom as bottom_, + ~appear, + ~remained, + ~disappear, + ) => + { + let old = oldNewVisible.new + let new = oldNewVisible.old + // empty new + new->Js.Array2.removeCountInPlace(~pos=0, ~count=new->Js.Array2.length)->ignore + oldNewVisible.old = old + oldNewVisible.new = new + + let anchorDelta = rbt->getAnchorDelta(~anchor) + //Js.log2("anchorDelta", anchorDelta) + let top = top_ -. anchorDelta + let top = top < 0.0 ? 0.0 : top // anchoring can make top negative + let bottom = bottom_ -. anchorDelta + + let first = firstVisibleNode(rbt.root, top) + let last = lastVisibleNode(rbt.root, bottom) + + let oldLen = old->Js.Array2.length + let oldIter = ref(0) + iterateWithY(~inclusive=true, first, last, ~callback=(. node, y_) => { + let y = y_ +. anchorDelta + if y >= 0.0 { // anchoring can make y negative + while ( + oldIter.contents < oldLen && + rbt.compare(. Js.Array2.unsafe_get(old, oldIter.contents), node.value) < 0 + ) { + disappear(. Js.Array2.unsafe_get(old, oldIter.contents)) + oldIter.contents = oldIter.contents + 1 + } + new->Js.Array2.push(node.value)->ignore + if (oldIter.contents < oldLen) { + let cmp = rbt.compare(. Js.Array2.unsafe_get(old, oldIter.contents), node.value) + if cmp == 0 { + remained(. node, y) + oldIter.contents = oldIter.contents + 1 + } else { + appear(. node, y) + } + } else { + appear(. node, y) + } + } + }) + while (oldIter.contents < oldLen) { + disappear(. Js.Array2.unsafe_get(old, oldIter.contents)) + oldIter.contents = oldIter.contents + 1 + } +}; + + + +let c: char = 'A' /* comment with link https://example and - = */ + +let respond_no_content = reqd => Reqd.respond_with_string(reqd, Response.create(#No_content), "") + +let to_meth = x => + switch x { + | #GET => #GET + | #POST => #POST + | #HEAD => #HEAD + | #DELETE => #DELETE + | #PUT => #PUT + | #OPTIONS => #OPTIONS + | #TRACE => #TRACE + | #CONNECT => #CONNECT + | #Other(w) => failwith(w ++ " is not supported") + } + +let ignore: 'a => unit = _ => () + +/* ** comment */ +/* *** comment */ +/* **** comment */ + +/* ** */ +/* *** */ + +/* ** */ + +/* (** comment *) */ +/* (*** comment *) */ +/* *(*** comment *) */ + +/* comment * */ +/* comment ** */ +/* comment *** */ +/* comment **** */ + +let testingNotQuiteEndOfLineComments = list{ + "Item 1" /* Comment For First Item */, + "Item 2" /* Comment For Second Item */, + "Item 3" /* Comment For Third Item */, + "Item 4" /* Comment For Fourth Item - but no semi */, + /* Comment after last item in list. */ +} /* Comment after list bracket */ + +let testingEndOfLineComments = list{ + "Item 1" /* Comment For First Item */, + "Item 2" /* Comment For Second Item */, + "Item 3" /* Comment For Third Item */, + "Item 4" /* Comment For Fourth Item - but before semi */, + /* Comment after last item in list. */ +} /* Comment after list bracket */ + +/* This time no space between bracket and comment */ +let testingEndOfLineComments = list{} /* Comment after list bracket */ + +type t = (int, int) /* End of line on t */ + +type t22 = /* End of t22 line on type t22 = */ +(int, int) + +type variant = + /* Comment above X */ + | X(int) /* End of line on X */ + /* Comment above Y */ + | Y(int) /* End of line on Y */ +/* Comment on entire type def for variant */ + +type rec x = { + /* not attached *above* x */ + fieldOne: int, +} /* Attached end of line after x */ +and y = { + /* not attached *above* y */ + fieldTwo: int, +} /* Attached end of line after y */ + +let result = switch X(3) { +| X(x) => + /* Where does this comment go? */ + let tmp = x + x + tmp +| Y(x) => + /* How about this one */ + let tmp = x + x + tmp +} + +let result = switch None { +| Some({fieldOne: 20}) => + /* Where does this comment go? */ + let tmp = 0 + 2 + tmp +| Some({fieldOne: n}) => + /* How about this one */ + let tmp = n + n + tmp +| None => 20 +} + +type pointWithManyKindsOfComments = { + /* Line before x */ + x: string /* x field */, + /* Line before y */ + y: string /* y field */, + /* Final row of record */ +} + +type typeParamPointWithComments<'a> = { + /* Line before x */ + x: 'a /* x field */, + /* Line before y */ + y: 'a /* y field */, + /* Final row of record */ +} + +let name_equal = (x, y) => x == y + +let equal = (i1, i2) => i1.contents === i2.contents && true /* most unlikely first */ + +let equal = (i1, i2) => compare(compare(0, 0), compare(1, 1)) /* END OF LINE HERE */ + +module Temp = { + let v = true + let logIt = (str, ()) => print_string(str) +} + +let store_attributes = arg => { + let attributes_file = "test" + let proc_name = attributes_file ++ ".proc" + let should_write = + /* only overwrite defined procedures */ + Temp.v || !Temp.v + if should_write { + Temp.logIt(proc_name, ()) + } +} + +let run = () => TestUtils.printSection("Basic Structures") + +while something { + print_string("You're in a while loop") + print_newline() +} + +for i in 0 to 5 { + print_int(i) + print_newline() + for i in 10 downto 0 { + print_string("Counting in reverse direction") + print_newline() + } +} + +for i in 0 to endOfRangeMustBeSimple(expr, soWrap) { + print_int(i) + print_newline() + for i in theSame(isTrue, ofThe, startOfRange) downto 0 { + print_string("Counting in reverse direction") + print_newline() + } +} + +let x = \"!"(\"!"(foo)).bar.contents + +let x = foo.bar.contents + +let x = \"!"(foo).bar.contents + +/* Prefix operators: + * ! followed by zero or more appropriate_operator_suffix_chars (see the + * lexer). + * ? or ~ followed by at least one appropriate_operator_suffix_chars. + */ +let x = !(!(!foo)).bar + +let x = !foo.bar + +let x = !(!foo).bar + +let x = !(!foo.bar) + +let x = \"?!"(!foo.bar) + +let x = !\"?!"(foo.bar) + +let x = \"~!"(!foo.bar) + +let x = !\"~!"(foo.bar) + +let x = \"~!"(\"~!"(foo.bar)) + +let x = \"!!"(foo.bar) + +let x = \"!~"(foo.bar) + +let noParensNeeded = !blah.foo.bar + +let parensNeededAroundFirst = (!blah).foo.bar + +let parensNeededAroundSecond = (!blah.foo).bar + +let x = !(!foo.bar) + +let x = -10 + +let x = -5.0 + +let x = Some(-10) + +let x = Some(-5.0) + +let lazy x = 10 +let lazy x: int = 10 +let lazy list{} = 10 +let lazy true = 10 +let lazy #...x = 10 +let lazy #Variant = 10 +let lazy #variant = 10 +let lazy '0' .. '9' = 10 +let lazy lazy true = 10 +let lazy %extend = 10 + +/* Test precedence on access sugar */ +let x = arr.contents[0] + +let x = arr.contents[0] + +let x = String.get(str.contents, 0) + +let x = String.get(str.contents, 0) + +let x = arr.contents[0] = 1 + +let x = arr.contents[0] = 1 + +let \"/++" = \"+" /* // indicates the start of a comment, not an infix op */ + +let something = if self.ext.logSuccess { + print_string("Did tap") + print_newline() +} + +let logTapSuccess = self => + if self.ext.logSuccess { + print_string("Did tap") + print_newline() + } else { + () + } + +let logTapSuccess = self => + if self.ext.logSuccess { + print_string("Did tap") + print_newline() + } + +(!data).field = true +(!data).field1.field2 = true +(!data.field1).field2 = true +(!data).field1.field2 = true +(!data.field1).field2 = true + +let loop = (appTime, frameTime) => { + if hasSetup.contents { + setupScene() + renderIntoTop() + hasSetup.contents = true + } + process(appTime, frameTime) +} + +/* These parens should be kept around the entire last if/then/else */ +if something { + if somethingElse { + () + } else { + "blah" + } +} + +/* These parens should be kept around just the last if/then */ +if something { + if somethingElse { + () + } else { + "blah" + } +} + +/* Parens should be generated to wrap the entire final if then else. + * To test that it's being parsed correclty, should print "one". */ +if true { + if true { + print_string("one") + } else { + print_string("two") + } +} + +/* Should print two */ +if true { + if false { + print_string("one") + } else { + print_string("two") + } +} + +/* Should not print */ +if false { + if true { + print_string("one") + } else { + print_string("two") + } +} + +/* Should wrap (if a > b then a else b). + * printer( + */ +let printIfFirstArgGreater = true +let result = if printIfFirstArgGreater { + (a, b) => + if a > b { + print_string("a > b") + } else { + print_string("b >= a") + } +} else if ( + (a, b) => + if a > b { + print_string("b < a") + } else { + print_string("a <= b") + } +) { + print_string("That could never possibly type check") + print_newline() +} + +let myRecord = { + nestedRecord: { + anotherNestedRecord: (instaComp, displayRect) => + if ( + Graphics.cgRectIntersectsWithSlop( + defaultCompositeTimerRectSlop, + instaComp.relativeRect, + displayRect, + ) + ) { + IoEligible + } else { + IoInelibleButTryComposition + }, + }, +} + +if printIfFirstArgGreater { + (a, b) => + if a > b { + print_string("a > b") + } +} else { + (a, b) => + if a > b { + print_string("b < a") + } +} +/* Should Be Parsed As: Cleary a type error, but at least the parsing makes that clear */ +if printIfFirstArgGreater { + (a, b) => + if a > b { + print_string("a > b") + } else { + (a, b) => + if a > b { + print_string("b < a") + } + } +} + +(a, b) => + if a > b { + print_string("a > b") + } + +/* What you probably wanted was: */ +if printIfFirstArgGreater { + (a, b) => + if a > b { + print_string("a > b") + } +} else { + (a, b) => + if a > b { + print_string("b < a") + } +} + +/* Mutative if statement: Not used to evaluate to something. */ +if 10 < 100 { + let msg = "If there was any doubt, 10 is in fact less than 100." + print_string(msg) +} else { + let msg = "All bets are off." + print_string(msg) +} + +if 10 < 100 { + print_string("If there was any doubt, 10 is in fact less than 100.") +} else { + print_string("All bets are off.") +} + +let x: int = 10 +let x: int = 10 +let x: int = 10 +let x: int = (10: int) + +/* In Reason, types look like the data they model! Tuples are no exception. */ +type pairOfInts = (int, int) +let letBindingWithTypeConstraint: int = 10 +let (tupleItem: int, withTypeConstraint: int) = (10, 20) + +/* To make sure that tuple field annotations are annotating the entire field */ +let _dummyFunc = x => 10 +let annotatingFuncApplication = ((_dummyFunc("a"): int), (_dummyFunc("a"): int)) + +/* Pretty printer might stick the [int] at the label. */ +let annotatingSingleFuncApplication: int = _dummyFunc("a") + +/* So lets try a place where it won't */ +let annotatingSingleFuncApplication = { + /* Commenting a let binding. */ + let a = 100 + /* Commenting another let binding. */ + let int = 200 + /* + * This demonstrates why named arguments cannot simply have the form (func + * arg:val) - it is indistinguishable from a type constraint. + */ + 2 + (_dummyFunc(a): int) +} + +let (tupleItem: int, constrainedWithoutGrouping: int) = (10, 20) +let (tupleItem, withOutsideTypeConstraint): (int, int) = (10, 20) + +/* Trailing commas */ +let trailingCommaAccepted = (1, 2) +let moreTrailing = (1, 2, 3, 4, 5, 7) + + +/* Anatomy: -Head- --------- Tail--------- nil: You can't see nil */ +let x: list = list{1, 2, 3, 4, 5, 6, 7, 8, 9} +let hd = "appendedToHead" +let tl = list{"listTo", "append", "to"} + +/* To push *one* and only *one* item to the front of a list - use [hd, ...tl] */ +let result: list = list{hd, ...tl} + +/* Is the same as writing */ +let result: list = list{"appendedToHead", "listTo", "append", "to"} + +/* To operate on lists, use pattern matching */ +let rec size = x => + switch x { + | list{} => 0 + | list{hd, ...tl} => 1 + size(tl) + } + +/* Optimize for tail recursion */ +let rec size = (soFar, lst) => + switch lst { + | list{} => 0 + | list{hd, ...tl} => size(soFar + 1, tl) + } + +let nestedMatch = lstLst => + switch lstLst { + | list{hd, ...tl} when false => 10 + | list{hd, ...tl} => + switch tl { + | list{} => 0 + 0 + | list{tlHd, ...tlTl} => 0 + 1 + } + | list{} => 0 + } + +let nestedMatchWithWhen = lstLst => + switch lstLst { + | list{hd, ...tl} when false => 10 + | list{hd, ...tl} when true => + switch tl { + | list{} when false => 0 + 0 + | list{} when true => 0 + 0 + | list{tlHd, ...tlTl} => 0 + 1 + } + | list{} => 0 + } + +type mine = + | MyThing(int) + | YourThing(int) +/* + * Reason parses "as" aliases differently than OCaml. + */ +let ppp = switch MyThing(20) { +| MyThing(x) as ppp +| YourThing(x) as ppp => ppp +} + +let MyThing(_) as ppp | YourThing(_) as ppp = ppp + +/* + * in order to achieve the previous example in ocaml, you would have to group + * as: + */ +let ppp = switch MyThing(20) { +| MyThing(x) as ppp +| YourThing(x) as ppp => ppp +} + +let MyThing(_) as ppp | YourThing(_) as ppp = ppp +let emptyArray = [] +let arrayWithOne = [10] +let arrayWithTwo = [10, 10] +let secondItem = arrayWithTwo[1] + +/* Getting And Setting: Yeah, we should really change this */ +/* Get an array item at index 1 */ +let secondItem = arrayWithTwo[1] +/* Set an array item at index 1 */ +arrayWithTwo[1] = 300 + +let myString = "asdf" +String.set(myString, 2, '9') /* Replacing a character: I could do without this sugar */ + +/* FUNCTIONS + *============================================================================= + */ + +/* TYPE ANNOTATIONS + * ============================================================================= + */ + +let one = 900 +let two = 10000 +/* Tuple expressions can be annotated without additional paren wrapping */ +let myTuple = ((one: int), (two: int)) +type myTupleType = (int, int) +let myTuple: myTupleType = myTuple + +/* Anything *outside* of a tuple, must still be annotated within parens. */ +let myTuple: myTupleType = ((one: int), (two: int)) + +/* Now functions that accept a single argument being a tuple look familiar */ +let addValues = (a: int, b: int) => a + b + +let addValues = (a: int, b: int) => a + b + +let myFunction = (a: int, b: int): int => a + b + +let functionReturnValueType = (i: int, s: string): (int => int) => x => x + 1 + +let curriedFormOne = (i: int, s: string) => s ++ string_of_int(i) + +let curriedFormTwo = (i: int, x: int): (int, int) => (i, x) +/* let nonCurriedFormTwo = fun (i:int, x:int) (:(int, int)) => (i, x); */ + +let curriedFormThree = (i: int, (a: int, b: int): (int, int)): (int, int, int) => (i, a, b) + + +type myFuncType = (int, int) => int + +let myFunc: myFuncType = (a, b) => a + b + +let funcWithTypeLocallyAbstractTypes = (type atype btype, a, b, c: (atype, btype) => unit) => + c(a, b) + +/* Checks that function types aren't unnecessary wrapped */ +type a = unit => unit + +type rec b = + | Foo(unit => unit) + | Bar(unit => unit, unit => unit, (a, b) => c) + | Baz(unit => unit, unit => unit, (a, b) => c) + +type c = + | Foo((a, b) => unit) + | Bar((a, b) => unit) + +type d = [> #Foo(unit => unit)] + +type withThreeFields = { + name: string, + age: int, + occupation: string, +} + +let testRecord = { + name: "joe", + age: 20, + occupation: "engineer", +} +let anotherRecord = { + ...testRecord, + name: "joe++", + age: testRecord.age + 10, +} + +let makeRecordBase = () => { + name: "Joe", + age: 30, + occupation: "Engineer", +} +let anotherRecord = { + .../* These parens should be evaporated. */ + makeRecordBase(), + name: "joe++", + age: testRecord.age + 10, +} + +let anotherRecord = { + .../* Comments should be correctly placed before ... expression */ + makeRecordBase(), + /* Comment after record extension */ + name: "joe++", + age: testRecord.age + 10, +} + +let anotherRecord = { + ...( + /* Currently, type annotations must be wrapped in parens - that's easy to improve */ + makeRecordBase(): withThreeFields + ), + name: "joe++", + age: testRecord.age + 10, +} + +let anotherRecord = { + .../* This is meaningless, sure */ + String.set(someArray, 0, 20), + name: "joe++", + age: testRecord.age + 10, +} + +let anotherRecord = { + ...SomeReally.longFunctionCall({ + passingRecordField: 0, + andThisOtherRecordField: 10, + }), + name: "joe++", + age: testRecord.age + 10, +} + +let anotherRecord = { + ...SomeReally.longFunctionCall(withArguments, (thatWrap: bool)), + name: "joe++", + age: testRecord.age + 10, +} + +let anotherRecord = { + ...SomeReally.longFunctionCall(withArg, list{"and", "final", "list", "that", "should", "break"}), + name: "joe++", + age: testRecord.age + 10, +} + +/* Record type punning */ +type props = {title: string} + +type state = unit + +type component = {props: props} + +type component2 = { + props: props, + state: state, + updater: unit, +} + +type component3 = { + props: M.props, + state: state, +} + +type mutableComponent = {mutable props: props} + +type mutabeleComponent2 = { + mutable props: props, + mutable state: state, + style: int, +} + +/* Don't pun parameterized types */ +type description<'props> = { + element: string, + tag: tag<'props>, +} + +/* Don't pun types from other modules */ +module Foo = { + type bar = {foo: Baz.foo} +} + +/* Don't pun field names that aren't "simple" */ +type foo = { + bar: Baz.bar, + qux: qux, + fooo: Fooo.fooo, +} + +let moreFoo = { + bar: Baz.bar, + qux: qux, + fooo: Fooo.fooo, +} + +/* record value punning */ + +let props = {title: "hi"} +/* no punning available for a single field. Can't tell the difference with a scope + expression */ +let componentA = {props: props} +/* pun for real */ +let componentB = {props: props, state: ()} +/* pun fields with module prefix too */ +let foo = {Foo.foo: foo} +let bar = {Foo.foo: foo, bar: 1} +let bar = {bar: 1, Foo.foo: foo} +let bar = {Foo.foo: foo, Bar.bar: bar} + +({M.x: x, y}) => 1 + +switch foo { +| {y: 1, M.x: x} => 2 +} + +/* Requested in #566 */ +let break_after_equal = no_break_from_here(some_call(to_here)) + +/* Pexp_letexception */ +let () = { + exception E + raise(E) +} + +/* # 1587: don't print fun keyword when printing Pexp_fun in a record expression */ +{contents: (): unit => ()} + +/* #1556: Always break nested record/obj */ +let z = { + a: { + b: c, + d: e, + }, + f: g, +} + +let z = { + a: { + "b": c, + "d": e, + }, + f: g, +} + +let z = { + "a": { + "b": c, + "d": e, + }, + "f": g, +} + +let z = { + "a": { + b: c, + d: e, + }, + "f": g, +} + +let unitLambda = () => () +let identifierLambda = a => () +let underscoreLambda = _ => () +it("should remove parens", a => { + print_string("did it work?") + print_string("did it work?") +}) + +foo(preserveBraces => inCallback) + +foo(preserveBraces => inFirstPos, secondArg) + +foo(oneArg, preserveBraces => inFirstPos, secondArg) diff -Nru ruby-rouge-3.21.0/spec/visual/samples/ruby ruby-rouge-3.26.1/spec/visual/samples/ruby --- ruby-rouge-3.21.0/spec/visual/samples/ruby 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/ruby 2021-09-17 19:59:49.000000000 +0000 @@ -269,6 +269,14 @@ %r( hash mark: # ) %w( ! $ % # ) +# this is modulo +board[i/w][i%w] == 'O' +puts [[x%w].reverse] + +# this is a method that takes a list +def x(s) puts x end +x %w].] + ################################################################## # HEREDOCS <<-CONTENT.strip_heredoc diff -Nru ruby-rouge-3.21.0/spec/visual/samples/rust ruby-rouge-3.26.1/spec/visual/samples/rust --- ruby-rouge-3.21.0/spec/visual/samples/rust 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/rust 2021-09-17 19:59:49.000000000 +0000 @@ -16,7 +16,7 @@ let b = (a / 4 + 1_000) * 2 - 3; let c = (a | 0b0100) & 0xF; - c ^ !b + c ^ !b ^ 0o707 } fn main() { @@ -400,6 +400,10 @@ let red_color = 0xff_60_60; } +fn float_literals_delimiter() { + let billion = 1000_000_000.0; +} + // Some hidden lines by starting with hash # extern crate core; # use core::str; @@ -409,3 +413,8 @@ let song = learn_song().await; sing_song(song).await; } + +fn tuple_access() { + let t: (i32, i32) = (42, 13); + let f: t.0; +} diff -Nru ruby-rouge-3.21.0/spec/visual/samples/systemd ruby-rouge-3.26.1/spec/visual/samples/systemd --- ruby-rouge-3.21.0/spec/visual/samples/systemd 1970-01-01 00:00:00.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/systemd 2021-09-17 19:59:49.000000000 +0000 @@ -0,0 +1,23 @@ +[Unit] +Description=Snap Daemon +Requires=snapd.socket +OnFailure=snapd.failure.service +# This is handled by snapd +# X-Snapd-Snap: do-not-start + +[Service] +# Disabled because it breaks lxd +# (https://bugs.launchpad.net/snapd/+bug/1709536) +#Nice=-5 +OOMScoreAdjust=-900 +ExecStart=/usr/lib/snapd/snapd +EnvironmentFile=-/etc/environment +Restart=always +WatchdogSec=5m +Type=notify +SuccessExitStatus=42 +RestartPreventExitStatus=42 +KillMode=process + +[Install] +WantedBy=multi-user.target diff -Nru ruby-rouge-3.21.0/spec/visual/samples/velocity ruby-rouge-3.26.1/spec/visual/samples/velocity --- ruby-rouge-3.21.0/spec/visual/samples/velocity 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/velocity 2021-09-17 19:59:49.000000000 +0000 @@ -20,6 +20,7 @@
#end #set( $monkey.Say = ["Not", $my, "fault", 10, false, null] ) ## ArrayList +#set( $result = $foo($bar[$baz]) ) ${mudSlinger} ${customer.Address} ${purchase.getTotal(true)} diff -Nru ruby-rouge-3.21.0/spec/visual/samples/yaml ruby-rouge-3.26.1/spec/visual/samples/yaml --- ruby-rouge-3.21.0/spec/visual/samples/yaml 2020-07-14 19:56:23.000000000 +0000 +++ ruby-rouge-3.26.1/spec/visual/samples/yaml 2021-09-17 19:59:49.000000000 +0000 @@ -353,3 +353,8 @@ 语言: français référence: &réf_01 alias: *λ-01 + +# Scalars with special characters +foo/bar: We are great +foo.bar: Are we really? +foo+bar: Maybe not