From ba0d43672b783d4a7195b21bfb378e7ba0c4d6ab Mon Sep 17 00:00:00 2001 From: Keith Hall Date: Sun, 4 Apr 2021 22:41:48 +0300 Subject: [PATCH 01/11] add example syslog file for highlighting tests --- tests/syntax-tests/source/Syslog/example.syslog | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 tests/syntax-tests/source/Syslog/example.syslog diff --git a/tests/syntax-tests/source/Syslog/example.syslog b/tests/syntax-tests/source/Syslog/example.syslog new file mode 100644 index 00000000..944bd7dd --- /dev/null +++ b/tests/syntax-tests/source/Syslog/example.syslog @@ -0,0 +1,5 @@ +Apr 4 00:00:01 hostname-here systemd[1]: logrotate.service: Succeeded. +Apr 4 00:00:01 hostname-here systemd[1]: Finished Rotate log files. +Apr 4 00:00:21 hostname-here kernel: [55604.908232] audit: type=1400 audit(1617483621.094:28): apparmor="DENIED" operation="capable" profile="/usr/sbin/cups-browsed" pid=59311 comm="cups-browsed" capability=23 capname="sys_nice" +Apr 4 09:30:01 hostname-here CRON[89278]: (root) CMD ([ -x /etc/init.d/anacron ] && if [ ! -d /run/systemd/system ]; then /usr/sbin/invoke-rc.d anacron start >/dev/null; fi) +Apr 4 22:00:45 hostname-here dbus-daemon[1094]: [session uid=1000 pid=1094] Successfully activated service 'io.github.celluloid_player.Celluloid' From 1537733e6b0d764e092b701565de94c51ef3ecf1 Mon Sep 17 00:00:00 2001 From: Keith Hall Date: Sun, 4 Apr 2021 22:42:13 +0300 Subject: [PATCH 02/11] replace Syslog dependency with a custom syntax --- .gitmodules | 4 -- CHANGELOG.md | 2 + assets/syntaxes/02_Extra/Syslog | 1 - .../syntaxes/02_Extra/syslog.sublime-syntax | 70 +++++++++++++++++++ .../highlighted/Syslog/example.syslog | 5 ++ 5 files changed, 77 insertions(+), 5 deletions(-) delete mode 160000 assets/syntaxes/02_Extra/Syslog create mode 100644 assets/syntaxes/02_Extra/syslog.sublime-syntax create mode 100644 tests/syntax-tests/highlighted/Syslog/example.syslog diff --git a/.gitmodules b/.gitmodules index 4b6bc34e..5cafb38e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -97,10 +97,6 @@ [submodule "assets/syntaxes/Assembly (ARM)"] path = assets/syntaxes/02_Extra/Assembly (ARM) url = https://github.com/tvi/Sublime-ARM-Assembly -[submodule "assets/syntaxes/syslog-syntax"] - path = assets/syntaxes/02_Extra/Syslog - url = https://github.com/caos21/syslog-syntax.git - branch = master [submodule "assets/syntaxes/protobuf-syntax-highlighting"] path = assets/syntaxes/02_Extra/Protobuf url = https://github.com/VcamX/protobuf-syntax-highlighting.git diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b02eb41..75e73ed8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ ## Syntaxes +- Improved the Syslog syntax highlighting, see #1606 (@keith-hall) + ## New themes ## `bat` as a library diff --git a/assets/syntaxes/02_Extra/Syslog b/assets/syntaxes/02_Extra/Syslog deleted file mode 160000 index 7628d4e0..00000000 --- a/assets/syntaxes/02_Extra/Syslog +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7628d4e0b89d3b4f0dcc014bfb4a3e3433f5133a diff --git a/assets/syntaxes/02_Extra/syslog.sublime-syntax b/assets/syntaxes/02_Extra/syslog.sublime-syntax new file mode 100644 index 00000000..6233da17 --- /dev/null +++ b/assets/syntaxes/02_Extra/syslog.sublime-syntax @@ -0,0 +1,70 @@ +%YAML 1.2 +--- +# http://www.sublimetext.com/docs/3/syntax.html +name: syslog +file_extensions: + - syslog +scope: text.syslog +contexts: + main: + - match: '^\w+\s+\d+\s+\d{2}:\d{2}:\d{2}' + scope: meta.datetime.syslog constant.numeric.syslog + push: loghost + loghost: + - match: '[\w-]+' + scope: entity.other.attribute-name.loghost.syslog + set: process + process: + - match: ([\w-]+)(?:(\[)(\d+)(\]))?(:) + captures: + 1: support.function.process.syslog + 2: punctuation.separator.pid.begin.syslog + 3: meta.pid.syslog meta.number.integer.syslog constant.numeric.value.syslog + 4: punctuation.separator.mapping.syslog + set: structured-data + structured-data: + - match: '\[' + scope: punctuation.section.mapping.begin.syslog + push: + - match: \] + scope: punctuation.section.mapping.end.syslog + pop: true + - match: \w+ + scope: variable.parameter.syslog + - match: = + scope: keyword.operator.assignment.syslog + push: + - match: '[^\s\]]+' + scope: constant.other.syslog + pop: true + - match: (?=\]) + pop: true + - match: (?=\S) + set: text + text: + - match: (\w+)(=) + captures: + 1: variable.parameter.syslog + 2: keyword.operator.assignment.syslog + - match: (')([^']*)(') + scope: string.quoted.single.syslog + captures: + 1: punctuation.definition.string.begin.syslog + 3: punctuation.definition.string.end.syslog + - match: (")([^"]*)(") + scope: string.quoted.double.syslog + captures: + 1: punctuation.definition.string.begin.syslog + 3: punctuation.definition.string.end.syslog + - match: \d+ + scope: meta.number.integer.syslog constant.numeric.value.syslog + - match: \b(CMD)\b\s+(\() + captures: + 1: entity.name.label.syslog + 2: punctuation.section.block.begin.syslog + embed: scope:source.shell.bash + escape: \) + escape_captures: + 0: punctuation.section.block.end.syslog + - match: $ + pop: true diff --git a/tests/syntax-tests/highlighted/Syslog/example.syslog b/tests/syntax-tests/highlighted/Syslog/example.syslog new file mode 100644 index 00000000..5ea6d9eb --- /dev/null +++ b/tests/syntax-tests/highlighted/Syslog/example.syslog @@ -0,0 +1,5 @@ +Apr 4 00:00:01 hostname-here systemd[1]: logrotate.service: Succeeded. +Apr 4 00:00:01 hostname-here systemd[1]: Finished Rotate log files. +Apr 4 00:00:21 hostname-here kernel: [55604.908232] audit: type=1400 audit(1617483621.094:28): apparmor="DENIED" operation="capable" profile="/usr/sbin/cups-browsed" pid=59311 comm="cups-browsed" capability=23 capname="sys_nice" +Apr 4 09:30:01 hostname-here CRON[89278]: (root) CMD ([ -x /etc/init.d/anacron ] && if [ ! -d /run/systemd/system ]; then /usr/sbin/invoke-rc.d anacron start >/dev/null; fi) +Apr 4 22:00:45 hostname-here dbus-daemon[1094]: [session uid=1000 pid=1094] Successfully activated service 'io.github.celluloid_player.Celluloid' From 782ede5db5ad601e44468c9ca32bd201e5c75aaa Mon Sep 17 00:00:00 2001 From: Keith Hall Date: Mon, 5 Apr 2021 22:17:47 +0300 Subject: [PATCH 03/11] improve syslog syntax --- .../syntaxes/02_Extra/syslog.sublime-syntax | 51 +++++++++++++++++-- .../highlighted/Syslog/example.syslog | 16 ++++-- .../syntax-tests/source/Syslog/example.syslog | 6 +++ 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/assets/syntaxes/02_Extra/syslog.sublime-syntax b/assets/syntaxes/02_Extra/syslog.sublime-syntax index 6233da17..9b243c9c 100644 --- a/assets/syntaxes/02_Extra/syslog.sublime-syntax +++ b/assets/syntaxes/02_Extra/syslog.sublime-syntax @@ -5,10 +5,15 @@ name: syslog file_extensions: - syslog scope: text.syslog +variables: + ipv4_part: (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?) contexts: main: - - match: '^\w+\s+\d+\s+\d{2}:\d{2}:\d{2}' + - match: ^(\w+\s+\d+)\s+(\d{2}:\d{2}:\d{2}) scope: meta.datetime.syslog constant.numeric.syslog + captures: + 1: meta.date.syslog + 2: meta.time.syslog push: loghost loghost: - match: '[\w-]+' @@ -20,7 +25,8 @@ contexts: 1: support.function.process.syslog 2: punctuation.separator.pid.begin.syslog 3: meta.pid.syslog meta.number.integer.syslog constant.numeric.value.syslog - 4: punctuation.separator.mapping.syslog + 4: punctuation.separator.pid.end.syslog + 5: punctuation.separator.mapping.syslog set: structured-data structured-data: - match: '\[' @@ -56,15 +62,50 @@ contexts: captures: 1: punctuation.definition.string.begin.syslog 3: punctuation.definition.string.end.syslog - - match: \d+ - scope: meta.number.integer.syslog constant.numeric.value.syslog + - include: numbers - match: \b(CMD)\b\s+(\() captures: 1: entity.name.label.syslog 2: punctuation.section.block.begin.syslog embed: scope:source.shell.bash - escape: \) + escape: \)$ escape_captures: 0: punctuation.section.block.end.syslog + - match: '<\w+>' + scope: constant.language.syslog + - match: (?i:fail(?:ure|ed)?|error) + scope: invalid.illegal.error.syslog - match: $ pop: true + numbers: + - match: (?=(?:{{ipv4_part}}\.){3}{{ipv4_part}}) + push: + - meta_scope: meta.ipaddress.v4.syslog meta.number.integer.decimal.syslog + - match: \d+ + scope: constant.numeric.value.syslog + - match: \. + scope: punctuation.separator.sequence.syslog + - match: '' + pop: true + - match: (?=(?:\h{0,4}:){2,6}\h{1,4}) + push: + - meta_scope: meta.ipaddress.v6.syslog meta.number.integer.hexadecimal.syslog + - match: \h{1,4} + scope: constant.numeric.value.syslog + - match: ':' + scope: punctuation.separator.sequence.syslog + - match: '' + pop: true + - match: (0x)(\h+)(?:(\.)(\h+))? + scope: meta.number.float.hexadecimal.syslog + captures: + 1: constant.numeric.base.syslog + 2: constant.numeric.value.syslog + 3: constant.numeric.value.syslog punctuation.separator.decimal.syslog + 4: constant.numeric.value.syslog + - match: \b\d+(\.)\d+\b + scope: meta.number.float.syslog constant.numeric.value.syslog + captures: + 1: punctuation.separator.decimal.syslog + - match: \b\d+\b + scope: meta.number.integer.syslog constant.numeric.value.syslog diff --git a/tests/syntax-tests/highlighted/Syslog/example.syslog b/tests/syntax-tests/highlighted/Syslog/example.syslog index 5ea6d9eb..35002a83 100644 --- a/tests/syntax-tests/highlighted/Syslog/example.syslog +++ b/tests/syntax-tests/highlighted/Syslog/example.syslog @@ -1,5 +1,11 @@ -Apr 4 00:00:01 hostname-here systemd[1]: logrotate.service: Succeeded. -Apr 4 00:00:01 hostname-here systemd[1]: Finished Rotate log files. -Apr 4 00:00:21 hostname-here kernel: [55604.908232] audit: type=1400 audit(1617483621.094:28): apparmor="DENIED" operation="capable" profile="/usr/sbin/cups-browsed" pid=59311 comm="cups-browsed" capability=23 capname="sys_nice" -Apr 4 09:30:01 hostname-here CRON[89278]: (root) CMD ([ -x /etc/init.d/anacron ] && if [ ! -d /run/systemd/system ]; then /usr/sbin/invoke-rc.d anacron start >/dev/null; fi) -Apr 4 22:00:45 hostname-here dbus-daemon[1094]: [session uid=1000 pid=1094] Successfully activated service 'io.github.celluloid_player.Celluloid' +Apr 4 00:00:01 hostname-here systemd[1]: logrotate.service: Succeeded. +Apr 4 00:00:01 hostname-here systemd[1]: Finished Rotate log files. +Apr 4 00:00:01 hostname-here colord[920]: failed to get session [pid 137485]: No data available +Apr 4 00:00:21 hostname-here kernel: [55604.908232] audit: type=1400 audit(1617483621.094:28): apparmor="DENIED" operation="capable" profile="/usr/sbin/cups-browsed" pid=59311 comm="cups-browsed" capability=23 capname="sys_nice" +Apr 4 00:01:38 hostname-here systemd-resolved[721]: Server returned error NXDOMAIN, mitigating potential DNS violation DVE-2018-0001, retrying transaction with reduced feature level UDP. +Apr 4 00:04:46 hostname-here ntpd[952]: Soliciting pool server 255.76.59.37 +Apr 4 00:05:21 hostname-here ntpd[952]: ::1 local addr 0:0:0:0:0:0:0:1 ->  +Apr 4 00:06:29 hostname-here ntpd[952]: receive: Unexpected origin timestamp 0xe414a8d1.82e825f5 does not match aorg 0xe414a8d5.82c50d8c from server@127.0.0.1 xmt 0xe414a8d1.e671d7c4 +Apr 4 09:30:01 hostname-here CRON[89278]: (root) CMD ([ -x /etc/init.d/anacron ] && if [ ! -d /run/systemd/system ]; then /usr/sbin/invoke-rc.d anacron start >/dev/null; fi) +Apr 4 16:32:07 hostname-here NetworkManager[740]:  [1617629527.1101] manager: NetworkManager state is now CONNECTED_GLOBAL +Apr 4 22:00:45 hostname-here dbus-daemon[1094]: [session uid=1000 pid=1094] Successfully activated service 'io.github.celluloid_player.Celluloid' diff --git a/tests/syntax-tests/source/Syslog/example.syslog b/tests/syntax-tests/source/Syslog/example.syslog index 944bd7dd..337f1434 100644 --- a/tests/syntax-tests/source/Syslog/example.syslog +++ b/tests/syntax-tests/source/Syslog/example.syslog @@ -1,5 +1,11 @@ Apr 4 00:00:01 hostname-here systemd[1]: logrotate.service: Succeeded. Apr 4 00:00:01 hostname-here systemd[1]: Finished Rotate log files. +Apr 4 00:00:01 hostname-here colord[920]: failed to get session [pid 137485]: No data available Apr 4 00:00:21 hostname-here kernel: [55604.908232] audit: type=1400 audit(1617483621.094:28): apparmor="DENIED" operation="capable" profile="/usr/sbin/cups-browsed" pid=59311 comm="cups-browsed" capability=23 capname="sys_nice" +Apr 4 00:01:38 hostname-here systemd-resolved[721]: Server returned error NXDOMAIN, mitigating potential DNS violation DVE-2018-0001, retrying transaction with reduced feature level UDP. +Apr 4 00:04:46 hostname-here ntpd[952]: Soliciting pool server 255.76.59.37 +Apr 4 00:05:21 hostname-here ntpd[952]: ::1 local addr 0:0:0:0:0:0:0:1 -> +Apr 4 00:06:29 hostname-here ntpd[952]: receive: Unexpected origin timestamp 0xe414a8d1.82e825f5 does not match aorg 0xe414a8d5.82c50d8c from server@127.0.0.1 xmt 0xe414a8d1.e671d7c4 Apr 4 09:30:01 hostname-here CRON[89278]: (root) CMD ([ -x /etc/init.d/anacron ] && if [ ! -d /run/systemd/system ]; then /usr/sbin/invoke-rc.d anacron start >/dev/null; fi) +Apr 4 16:32:07 hostname-here NetworkManager[740]: [1617629527.1101] manager: NetworkManager state is now CONNECTED_GLOBAL Apr 4 22:00:45 hostname-here dbus-daemon[1094]: [session uid=1000 pid=1094] Successfully activated service 'io.github.celluloid_player.Celluloid' From 7c4edacb2be13eef3afe0e2b23fb83c7ca813dd7 Mon Sep 17 00:00:00 2001 From: Keith Hall Date: Tue, 6 Apr 2021 23:50:52 +0300 Subject: [PATCH 04/11] Add independent log syntax --- assets/syntaxes/02_Extra/log.sublime-syntax | 114 ++++++++++++++++++ .../syntaxes/02_Extra/syslog.sublime-syntax | 62 ++-------- .../syntax-tests/highlighted/Log/example.log | 2 + tests/syntax-tests/source/Log/example.log | 2 + 4 files changed, 125 insertions(+), 55 deletions(-) create mode 100644 assets/syntaxes/02_Extra/log.sublime-syntax create mode 100644 tests/syntax-tests/highlighted/Log/example.log create mode 100644 tests/syntax-tests/source/Log/example.log diff --git a/assets/syntaxes/02_Extra/log.sublime-syntax b/assets/syntaxes/02_Extra/log.sublime-syntax new file mode 100644 index 00000000..2c961008 --- /dev/null +++ b/assets/syntaxes/02_Extra/log.sublime-syntax @@ -0,0 +1,114 @@ +%YAML 1.2 +--- +# See http://www.sublimetext.com/docs/3/syntax.html +file_extensions: + - log +scope: text.log +variables: + ipv4_part: (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?) +contexts: + main: + - match: (\w+)(=) + captures: + 1: variable.parameter.log + 2: keyword.operator.assignment.log + - match: (')([^']*)(') + scope: string.quoted.single.log + captures: + 1: punctuation.definition.string.begin.log + 3: punctuation.definition.string.end.log + - match: (")([^"]*)(") + scope: string.quoted.double.log + captures: + 1: punctuation.definition.string.begin.log + 3: punctuation.definition.string.end.log + - include: dates + - include: ip_addresses + - include: numbers + - match: \b(?i:fail(?:ure|ed)?|error)\b + scope: invalid.illegal.error.log + #- include: scope:text.html.markdown#autolink-inet + - match: \b\w+:/{2,3} + scope: markup.underline.link.scheme.log + push: url-host + dates: + - match: \b\d{4}-\d{2}-\d{2}\b + scope: meta.date.log meta.number.integer.decimal.log constant.numeric.value.log + - match: \b\d{4}/\d{2}/\d{2}\b + scope: meta.date.log meta.number.integer.decimal.log constant.numeric.value.log + - match: \b(?:[01]\d|2[0-3]):(?:[0-5]\d):(?:[0-5]\d)(?:(\.)\d{3})?\b + scope: meta.time.log meta.number.integer.decimal.log constant.numeric.value.log + captures: + 1: punctuation.separator.decimal.log + ip_addresses: + - match: (?=(?:{{ipv4_part}}\.){3}{{ipv4_part}}) + push: + - meta_scope: meta.ipaddress.v4.log meta.number.integer.decimal.log + - match: \d+ + scope: constant.numeric.value.log + - match: \. + scope: punctuation.separator.sequence.log + - match: '' + pop: true + - match: (?=(?:\h{0,4}:){2,6}\h{1,4}) + push: + - meta_scope: meta.ipaddress.v6.log meta.number.integer.hexadecimal.log + - match: \h{1,4} + scope: constant.numeric.value.log + - match: ':' + scope: punctuation.separator.sequence.log + - match: '' + pop: true + numbers: + - match: (0x)(\h+)(?:(\.)(\h+))? + scope: meta.number.float.hexadecimal.log + captures: + 1: constant.numeric.base.log + 2: constant.numeric.value.log + 3: constant.numeric.value.log punctuation.separator.decimal.log + 4: constant.numeric.value.log + - match: \b\d+(\.)\d+\b + scope: meta.number.float.log constant.numeric.value.log + captures: + 1: punctuation.separator.decimal.log + - match: \b\d+\b + scope: meta.number.integer.log constant.numeric.value.log + url-host: + - meta_content_scope: markup.underline.link.host.log + - match: \[ + scope: punctuation.section.brackets.begin.log + push: + - match: \] + scope: punctuation.section.brackets.end.log + pop: true + - include: ip_addresses + - match: '[^:/\s]+' + - match: '' + set: url-after-host + url-after-host: + - match: (:)(\d+) + scope: markup.underline.link.port.log + captures: + 1: punctuation.separator.mapping.port.log + 2: constant.numeric.value.log + #- include: scope:text.html.markdown#url-escaped-chars + - match: (%)\h{2} + scope: markup.underline.link.path.log constant.character.escape.url.log + captures: + 1: punctuation.definition.escape.log + # After a valid domain, zero or more non-space non-< characters may follow + - match: (?=[?!.,:*_~]*[\s<]) # Trailing punctuation (specifically, ?, !, ., ,, :, *, _, and ~) will not be considered part of the autolink, though they may be included in the interior of the link + pop: true + - match: \( # When an autolink ends in ), we scan the entire autolink for the total number of parentheses. If there is a greater number of closing parentheses than opening ones, we don’t consider the last character part of the autolink, in order to facilitate including an autolink inside a parenthesis + push: + - meta_scope: markup.underline.link.path.log + - match: (?=[?!.,:*_~]*[\s<]) + pop: true + - match: \) + pop: true + - match: (?=\)[?!.,:*_~]*[\s<]) + pop: true + - match: '[^?!.,:*_~\s<&()%]+|\S' + scope: markup.underline.link.path.log + - match: '' + pop: true diff --git a/assets/syntaxes/02_Extra/syslog.sublime-syntax b/assets/syntaxes/02_Extra/syslog.sublime-syntax index 9b243c9c..23730b70 100644 --- a/assets/syntaxes/02_Extra/syslog.sublime-syntax +++ b/assets/syntaxes/02_Extra/syslog.sublime-syntax @@ -5,8 +5,6 @@ name: syslog file_extensions: - syslog scope: text.syslog -variables: - ipv4_part: (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?) contexts: main: - match: ^(\w+\s+\d+)\s+(\d{2}:\d{2}:\d{2}) @@ -15,6 +13,8 @@ contexts: 1: meta.date.syslog 2: meta.time.syslog push: loghost + - match: ^ + push: text loghost: - match: '[\w-]+' scope: entity.other.attribute-name.loghost.syslog @@ -48,21 +48,10 @@ contexts: - match: (?=\S) set: text text: - - match: (\w+)(=) - captures: - 1: variable.parameter.syslog - 2: keyword.operator.assignment.syslog - - match: (')([^']*)(') - scope: string.quoted.single.syslog - captures: - 1: punctuation.definition.string.begin.syslog - 3: punctuation.definition.string.end.syslog - - match: (")([^"]*)(") - scope: string.quoted.double.syslog - captures: - 1: punctuation.definition.string.begin.syslog - 3: punctuation.definition.string.end.syslog - - include: numbers + - match: $ + pop: true + - match: '<\w+>' + scope: constant.language.syslog - match: \b(CMD)\b\s+(\() captures: 1: entity.name.label.syslog @@ -71,41 +60,4 @@ contexts: escape: \)$ escape_captures: 0: punctuation.section.block.end.syslog - - match: '<\w+>' - scope: constant.language.syslog - - match: (?i:fail(?:ure|ed)?|error) - scope: invalid.illegal.error.syslog - - match: $ - pop: true - numbers: - - match: (?=(?:{{ipv4_part}}\.){3}{{ipv4_part}}) - push: - - meta_scope: meta.ipaddress.v4.syslog meta.number.integer.decimal.syslog - - match: \d+ - scope: constant.numeric.value.syslog - - match: \. - scope: punctuation.separator.sequence.syslog - - match: '' - pop: true - - match: (?=(?:\h{0,4}:){2,6}\h{1,4}) - push: - - meta_scope: meta.ipaddress.v6.syslog meta.number.integer.hexadecimal.syslog - - match: \h{1,4} - scope: constant.numeric.value.syslog - - match: ':' - scope: punctuation.separator.sequence.syslog - - match: '' - pop: true - - match: (0x)(\h+)(?:(\.)(\h+))? - scope: meta.number.float.hexadecimal.syslog - captures: - 1: constant.numeric.base.syslog - 2: constant.numeric.value.syslog - 3: constant.numeric.value.syslog punctuation.separator.decimal.syslog - 4: constant.numeric.value.syslog - - match: \b\d+(\.)\d+\b - scope: meta.number.float.syslog constant.numeric.value.syslog - captures: - 1: punctuation.separator.decimal.syslog - - match: \b\d+\b - scope: meta.number.integer.syslog constant.numeric.value.syslog + - include: scope:text.log diff --git a/tests/syntax-tests/highlighted/Log/example.log b/tests/syntax-tests/highlighted/Log/example.log new file mode 100644 index 00000000..8387670c --- /dev/null +++ b/tests/syntax-tests/highlighted/Log/example.log @@ -0,0 +1,2 @@ +2021-03-06 23:22:21.392 https://[2001:db8:4006:812::200e]:8080/path/the%20page.html +2021-03-06 23:22:21 https://example.com:8080/path/the%20page(with_parens).html diff --git a/tests/syntax-tests/source/Log/example.log b/tests/syntax-tests/source/Log/example.log new file mode 100644 index 00000000..35eb1c78 --- /dev/null +++ b/tests/syntax-tests/source/Log/example.log @@ -0,0 +1,2 @@ +2021-03-06 23:22:21.392 https://[2001:db8:4006:812::200e]:8080/path/the%20page.html +2021-03-06 23:22:21 https://example.com:8080/path/the%20page(with_parens).html From 867cf63dd9db70adad65f4e8a9ac38a4fce352e9 Mon Sep 17 00:00:00 2001 From: Keith Hall Date: Wed, 7 Apr 2021 22:01:10 +0300 Subject: [PATCH 05/11] add word boundaries to log syntax highlighting --- assets/syntaxes/02_Extra/log.sublime-syntax | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/syntaxes/02_Extra/log.sublime-syntax b/assets/syntaxes/02_Extra/log.sublime-syntax index 2c961008..5e4501b8 100644 --- a/assets/syntaxes/02_Extra/log.sublime-syntax +++ b/assets/syntaxes/02_Extra/log.sublime-syntax @@ -25,7 +25,7 @@ contexts: - include: dates - include: ip_addresses - include: numbers - - match: \b(?i:fail(?:ure|ed)?|error)\b + - match: \b(?i:fail(?:ure|ed)?|error|exception)\b scope: invalid.illegal.error.log #- include: scope:text.html.markdown#autolink-inet - match: \b\w+:/{2,3} @@ -41,7 +41,7 @@ contexts: captures: 1: punctuation.separator.decimal.log ip_addresses: - - match: (?=(?:{{ipv4_part}}\.){3}{{ipv4_part}}) + - match: \b(?=(?:{{ipv4_part}}\.){3}{{ipv4_part}}\b) push: - meta_scope: meta.ipaddress.v4.log meta.number.integer.decimal.log - match: \d+ @@ -50,7 +50,7 @@ contexts: scope: punctuation.separator.sequence.log - match: '' pop: true - - match: (?=(?:\h{0,4}:){2,6}\h{1,4}) + - match: (?=(?:\h{0,4}:){2,6}\h{1,4}\b) push: - meta_scope: meta.ipaddress.v6.log meta.number.integer.hexadecimal.log - match: \h{1,4} @@ -60,7 +60,7 @@ contexts: - match: '' pop: true numbers: - - match: (0x)(\h+)(?:(\.)(\h+))? + - match: \b(0x)(\h+)(?:(\.)(\h+))?\b scope: meta.number.float.hexadecimal.log captures: 1: constant.numeric.base.log From b3ab8439547b6204167cb05ac7360160b54a1568 Mon Sep 17 00:00:00 2001 From: Keith Hall Date: Fri, 9 Apr 2021 22:09:01 +0300 Subject: [PATCH 06/11] add warning highlighting to log file syntax definition --- assets/patches/Monokai-Extended.tmTheme.patch | 18 ++++++++++++++++++ assets/syntaxes/02_Extra/log.sublime-syntax | 4 +++- assets/syntaxes/02_Extra/syslog.sublime-syntax | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/assets/patches/Monokai-Extended.tmTheme.patch b/assets/patches/Monokai-Extended.tmTheme.patch index 24573a7b..c237f53d 100644 --- a/assets/patches/Monokai-Extended.tmTheme.patch +++ b/assets/patches/Monokai-Extended.tmTheme.patch @@ -16,3 +16,21 @@ index 9c2aa3e..180cbbf 100644 +@@ -1027,7 +1027,7 @@ + name + Invalid + scope +- invalid ++ invalid, markup.error + settings + + background +@@ -1042,7 +1042,7 @@ + name + Invalid deprecated + scope +- invalid.deprecated ++ invalid.deprecated, markup.warning + settings + + background diff --git a/assets/syntaxes/02_Extra/log.sublime-syntax b/assets/syntaxes/02_Extra/log.sublime-syntax index 5e4501b8..3c699d2e 100644 --- a/assets/syntaxes/02_Extra/log.sublime-syntax +++ b/assets/syntaxes/02_Extra/log.sublime-syntax @@ -26,7 +26,9 @@ contexts: - include: ip_addresses - include: numbers - match: \b(?i:fail(?:ure|ed)?|error|exception)\b - scope: invalid.illegal.error.log + scope: markup.error.log + - match: \b(?i:warn(?:ing)?)\b + scope: markup.warning.log #- include: scope:text.html.markdown#autolink-inet - match: \b\w+:/{2,3} scope: markup.underline.link.scheme.log diff --git a/assets/syntaxes/02_Extra/syslog.sublime-syntax b/assets/syntaxes/02_Extra/syslog.sublime-syntax index 23730b70..ce782e50 100644 --- a/assets/syntaxes/02_Extra/syslog.sublime-syntax +++ b/assets/syntaxes/02_Extra/syslog.sublime-syntax @@ -4,7 +4,7 @@ name: syslog file_extensions: - syslog -scope: text.syslog +scope: text.log.syslog contexts: main: - match: ^(\w+\s+\d+)\s+(\d{2}:\d{2}:\d{2}) From fc88040b31635631327432da9babcf73b0c1278f Mon Sep 17 00:00:00 2001 From: Ersikan Date: Mon, 29 Mar 2021 14:33:27 +0200 Subject: [PATCH 07/11] Add Solidity and Vyper syntax --- .gitmodules | 3 +++ assets/syntaxes/02_Extra/SublimeEthereum | 1 + 2 files changed, 4 insertions(+) create mode 160000 assets/syntaxes/02_Extra/SublimeEthereum diff --git a/.gitmodules b/.gitmodules index 12beb70c..db5c1b5d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -216,3 +216,6 @@ [submodule "assets/syntaxes/02_Extra/SystemVerilog"] path = assets/syntaxes/02_Extra/SystemVerilog url = https://github.com/TheClams/SystemVerilog.git +[submodule "assets/syntaxes/02_Extra/SublimeEthereum"] + path = assets/syntaxes/02_Extra/SublimeEthereum + url = https://github.com/davidhq/SublimeEthereum.git diff --git a/assets/syntaxes/02_Extra/SublimeEthereum b/assets/syntaxes/02_Extra/SublimeEthereum new file mode 160000 index 00000000..4f775259 --- /dev/null +++ b/assets/syntaxes/02_Extra/SublimeEthereum @@ -0,0 +1 @@ +Subproject commit 4f775259cd15a50a3a18f433cbd4024f46d30ce3 From c933be926dfed57f9601c31cef918a3eff86a843 Mon Sep 17 00:00:00 2001 From: Ersikan Date: Mon, 29 Mar 2021 14:50:28 +0200 Subject: [PATCH 08/11] Add syntax tests for Solidity language. --- .../highlighted/Solidity/ERC721.sol | 376 ++++++++++++++++++ tests/syntax-tests/source/Solidity/ERC721.sol | 376 ++++++++++++++++++ tests/syntax-tests/source/Solidity/LICENSE.md | 27 ++ 3 files changed, 779 insertions(+) create mode 100644 tests/syntax-tests/highlighted/Solidity/ERC721.sol create mode 100644 tests/syntax-tests/source/Solidity/ERC721.sol create mode 100644 tests/syntax-tests/source/Solidity/LICENSE.md diff --git a/tests/syntax-tests/highlighted/Solidity/ERC721.sol b/tests/syntax-tests/highlighted/Solidity/ERC721.sol new file mode 100644 index 00000000..a04bea91 --- /dev/null +++ b/tests/syntax-tests/highlighted/Solidity/ERC721.sol @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./IERC721.sol"; +import "./IERC721Receiver.sol"; +import "./extensions/IERC721Metadata.sol"; +import "../../utils/Address.sol"; +import "../../utils/Context.sol"; +import "../../utils/Strings.sol"; +import "../../utils/introspection/ERC165.sol"; + +/** + * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including + * the Metadata extension, but not including the Enumerable extension, which is available separately as + * {ERC721Enumerable}. + */ +contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { + using Address for address; + using Strings for uint256; + + // Token name + string private _name; + + // Token symbol + string private _symbol; + + // Mapping from token ID to owner address + mapping (uint256 => address) private _owners; + + // Mapping owner address to token count + mapping (address => uint256) private _balances; + + // Mapping from token ID to approved address + mapping (uint256 => address) private _tokenApprovals; + + // Mapping from owner to operator approvals + mapping (address => mapping (address => bool)) private _operatorApprovals; + + /** + * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. + */ + constructor (string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + return interfaceId == type(IERC721).interfaceId + || interfaceId == type(IERC721Metadata).interfaceId + || super.supportsInterface(interfaceId); + } + + /** + * @dev See {IERC721-balanceOf}. + */ + function balanceOf(address owner) public view virtual override returns (uint256) { + require(owner != address(0), "ERC721: balance query for the zero address"); + return _balances[owner]; + } + + /** + * @dev See {IERC721-ownerOf}. + */ + function ownerOf(uint256 tokenId) public view virtual override returns (address) { + address owner = _owners[tokenId]; + require(owner != address(0), "ERC721: owner query for nonexistent token"); + return owner; + } + + /** + * @dev See {IERC721Metadata-name}. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev See {IERC721Metadata-symbol}. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev See {IERC721Metadata-tokenURI}. + */ + function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { + require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); + + string memory baseURI = _baseURI(); + return bytes(baseURI).length > 0 + ? string(abi.encodePacked(baseURI, tokenId.toString())) + : ''; + } + + /** + * @dev Base URI for computing {tokenURI}. Empty by default, can be overriden + * in child contracts. + */ + function _baseURI() internal view virtual returns (string memory) { + return ""; + } + + /** + * @dev See {IERC721-approve}. + */ + function approve(address to, uint256 tokenId) public virtual override { + address owner = ERC721.ownerOf(tokenId); + require(to != owner, "ERC721: approval to current owner"); + + require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()), + "ERC721: approve caller is not owner nor approved for all" + ); + + _approve(to, tokenId); + } + + /** + * @dev See {IERC721-getApproved}. + */ + function getApproved(uint256 tokenId) public view virtual override returns (address) { + require(_exists(tokenId), "ERC721: approved query for nonexistent token"); + + return _tokenApprovals[tokenId]; + } + + /** + * @dev See {IERC721-setApprovalForAll}. + */ + function setApprovalForAll(address operator, bool approved) public virtual override { + require(operator != _msgSender(), "ERC721: approve to caller"); + + _operatorApprovals[_msgSender()][operator] = approved; + emit ApprovalForAll(_msgSender(), operator, approved); + } + + /** + * @dev See {IERC721-isApprovedForAll}. + */ + function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { + return _operatorApprovals[owner][operator]; + } + + /** + * @dev See {IERC721-transferFrom}. + */ + function transferFrom(address from, address to, uint256 tokenId) public virtual override { + //solhint-disable-next-line max-line-length + require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); + + _transfer(from, to, tokenId); + } + + /** + * @dev See {IERC721-safeTransferFrom}. + */ + function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { + safeTransferFrom(from, to, tokenId, ""); + } + + /** + * @dev See {IERC721-safeTransferFrom}. + */ + function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override { + require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); + _safeTransfer(from, to, tokenId, _data); + } + + /** + * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients + * are aware of the ERC721 protocol to prevent tokens from being forever locked. + * + * `_data` is additional data, it has no specified format and it is sent in call to `to`. + * + * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. + * implement alternative mechanisms to perform token transfer, such as signature-based. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `tokenId` token must exist and be owned by `from`. + * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. + * + * Emits a {Transfer} event. + */ + function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual { + _transfer(from, to, tokenId); + require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); + } + + /** + * @dev Returns whether `tokenId` exists. + * + * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. + * + * Tokens start existing when they are minted (`_mint`), + * and stop existing when they are burned (`_burn`). + */ + function _exists(uint256 tokenId) internal view virtual returns (bool) { + return _owners[tokenId] != address(0); + } + + /** + * @dev Returns whether `spender` is allowed to manage `tokenId`. + * + * Requirements: + * + * - `tokenId` must exist. + */ + function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { + require(_exists(tokenId), "ERC721: operator query for nonexistent token"); + address owner = ERC721.ownerOf(tokenId); + return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); + } + + /** + * @dev Safely mints `tokenId` and transfers it to `to`. + * + * Requirements: + * + * - `tokenId` must not exist. + * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. + * + * Emits a {Transfer} event. + */ + function _safeMint(address to, uint256 tokenId) internal virtual { + _safeMint(to, tokenId, ""); + } + + /** + * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is + * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. + */ + function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual { + _mint(to, tokenId); + require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); + } + + /** + * @dev Mints `tokenId` and transfers it to `to`. + * + * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible + * + * Requirements: + * + * - `tokenId` must not exist. + * - `to` cannot be the zero address. + * + * Emits a {Transfer} event. + */ + function _mint(address to, uint256 tokenId) internal virtual { + require(to != address(0), "ERC721: mint to the zero address"); + require(!_exists(tokenId), "ERC721: token already minted"); + + _beforeTokenTransfer(address(0), to, tokenId); + + _balances[to] += 1; + _owners[tokenId] = to; + + emit Transfer(address(0), to, tokenId); + } + + /** + * @dev Destroys `tokenId`. + * The approval is cleared when the token is burned. + * + * Requirements: + * + * - `tokenId` must exist. + * + * Emits a {Transfer} event. + */ + function _burn(uint256 tokenId) internal virtual { + address owner = ERC721.ownerOf(tokenId); + + _beforeTokenTransfer(owner, address(0), tokenId); + + // Clear approvals + _approve(address(0), tokenId); + + _balances[owner] -= 1; + delete _owners[tokenId]; + + emit Transfer(owner, address(0), tokenId); + } + + /** + * @dev Transfers `tokenId` from `from` to `to`. + * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - `tokenId` token must be owned by `from`. + * + * Emits a {Transfer} event. + */ + function _transfer(address from, address to, uint256 tokenId) internal virtual { + require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); + require(to != address(0), "ERC721: transfer to the zero address"); + + _beforeTokenTransfer(from, to, tokenId); + + // Clear approvals from the previous owner + _approve(address(0), tokenId); + + _balances[from] -= 1; + _balances[to] += 1; + _owners[tokenId] = to; + + emit Transfer(from, to, tokenId); + } + + /** + * @dev Approve `to` to operate on `tokenId` + * + * Emits a {Approval} event. + */ + function _approve(address to, uint256 tokenId) internal virtual { + _tokenApprovals[tokenId] = to; + emit Approval(ERC721.ownerOf(tokenId), to, tokenId); + } + + /** + * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. + * The call is not executed if the target address is not a contract. + * + * @param from address representing the previous owner of the given token ID + * @param to target address that will receive the tokens + * @param tokenId uint256 ID of the token to be transferred + * @param _data bytes optional data to send along with the call + * @return bool whether the call correctly returned the expected magic value + */ + function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) + private returns (bool) + { + if (to.isContract()) { + try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) { + return retval == IERC721Receiver(to).onERC721Received.selector; + } catch (bytes memory reason) { + if (reason.length == 0) { + revert("ERC721: transfer to non ERC721Receiver implementer"); + } else { + // solhint-disable-next-line no-inline-assembly + assembly { + revert(add(32, reason), mload(reason)) + } + } + } + } else { + return true; + } + } + + /** + * @dev Hook that is called before any token transfer. This includes minting + * and burning. + * + * Calling conditions: + * + * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be + * transferred to `to`. + * - When `from` is zero, `tokenId` will be minted for `to`. + * - When `to` is zero, ``from``'s `tokenId` will be burned. + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { } +} diff --git a/tests/syntax-tests/source/Solidity/ERC721.sol b/tests/syntax-tests/source/Solidity/ERC721.sol new file mode 100644 index 00000000..b617f3d2 --- /dev/null +++ b/tests/syntax-tests/source/Solidity/ERC721.sol @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./IERC721.sol"; +import "./IERC721Receiver.sol"; +import "./extensions/IERC721Metadata.sol"; +import "../../utils/Address.sol"; +import "../../utils/Context.sol"; +import "../../utils/Strings.sol"; +import "../../utils/introspection/ERC165.sol"; + +/** + * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including + * the Metadata extension, but not including the Enumerable extension, which is available separately as + * {ERC721Enumerable}. + */ +contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { + using Address for address; + using Strings for uint256; + + // Token name + string private _name; + + // Token symbol + string private _symbol; + + // Mapping from token ID to owner address + mapping (uint256 => address) private _owners; + + // Mapping owner address to token count + mapping (address => uint256) private _balances; + + // Mapping from token ID to approved address + mapping (uint256 => address) private _tokenApprovals; + + // Mapping from owner to operator approvals + mapping (address => mapping (address => bool)) private _operatorApprovals; + + /** + * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. + */ + constructor (string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + return interfaceId == type(IERC721).interfaceId + || interfaceId == type(IERC721Metadata).interfaceId + || super.supportsInterface(interfaceId); + } + + /** + * @dev See {IERC721-balanceOf}. + */ + function balanceOf(address owner) public view virtual override returns (uint256) { + require(owner != address(0), "ERC721: balance query for the zero address"); + return _balances[owner]; + } + + /** + * @dev See {IERC721-ownerOf}. + */ + function ownerOf(uint256 tokenId) public view virtual override returns (address) { + address owner = _owners[tokenId]; + require(owner != address(0), "ERC721: owner query for nonexistent token"); + return owner; + } + + /** + * @dev See {IERC721Metadata-name}. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev See {IERC721Metadata-symbol}. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev See {IERC721Metadata-tokenURI}. + */ + function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { + require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); + + string memory baseURI = _baseURI(); + return bytes(baseURI).length > 0 + ? string(abi.encodePacked(baseURI, tokenId.toString())) + : ''; + } + + /** + * @dev Base URI for computing {tokenURI}. Empty by default, can be overriden + * in child contracts. + */ + function _baseURI() internal view virtual returns (string memory) { + return ""; + } + + /** + * @dev See {IERC721-approve}. + */ + function approve(address to, uint256 tokenId) public virtual override { + address owner = ERC721.ownerOf(tokenId); + require(to != owner, "ERC721: approval to current owner"); + + require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()), + "ERC721: approve caller is not owner nor approved for all" + ); + + _approve(to, tokenId); + } + + /** + * @dev See {IERC721-getApproved}. + */ + function getApproved(uint256 tokenId) public view virtual override returns (address) { + require(_exists(tokenId), "ERC721: approved query for nonexistent token"); + + return _tokenApprovals[tokenId]; + } + + /** + * @dev See {IERC721-setApprovalForAll}. + */ + function setApprovalForAll(address operator, bool approved) public virtual override { + require(operator != _msgSender(), "ERC721: approve to caller"); + + _operatorApprovals[_msgSender()][operator] = approved; + emit ApprovalForAll(_msgSender(), operator, approved); + } + + /** + * @dev See {IERC721-isApprovedForAll}. + */ + function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { + return _operatorApprovals[owner][operator]; + } + + /** + * @dev See {IERC721-transferFrom}. + */ + function transferFrom(address from, address to, uint256 tokenId) public virtual override { + //solhint-disable-next-line max-line-length + require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); + + _transfer(from, to, tokenId); + } + + /** + * @dev See {IERC721-safeTransferFrom}. + */ + function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { + safeTransferFrom(from, to, tokenId, ""); + } + + /** + * @dev See {IERC721-safeTransferFrom}. + */ + function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override { + require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); + _safeTransfer(from, to, tokenId, _data); + } + + /** + * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients + * are aware of the ERC721 protocol to prevent tokens from being forever locked. + * + * `_data` is additional data, it has no specified format and it is sent in call to `to`. + * + * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. + * implement alternative mechanisms to perform token transfer, such as signature-based. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `tokenId` token must exist and be owned by `from`. + * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. + * + * Emits a {Transfer} event. + */ + function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual { + _transfer(from, to, tokenId); + require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); + } + + /** + * @dev Returns whether `tokenId` exists. + * + * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. + * + * Tokens start existing when they are minted (`_mint`), + * and stop existing when they are burned (`_burn`). + */ + function _exists(uint256 tokenId) internal view virtual returns (bool) { + return _owners[tokenId] != address(0); + } + + /** + * @dev Returns whether `spender` is allowed to manage `tokenId`. + * + * Requirements: + * + * - `tokenId` must exist. + */ + function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { + require(_exists(tokenId), "ERC721: operator query for nonexistent token"); + address owner = ERC721.ownerOf(tokenId); + return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); + } + + /** + * @dev Safely mints `tokenId` and transfers it to `to`. + * + * Requirements: + * + * - `tokenId` must not exist. + * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. + * + * Emits a {Transfer} event. + */ + function _safeMint(address to, uint256 tokenId) internal virtual { + _safeMint(to, tokenId, ""); + } + + /** + * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is + * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. + */ + function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual { + _mint(to, tokenId); + require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); + } + + /** + * @dev Mints `tokenId` and transfers it to `to`. + * + * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible + * + * Requirements: + * + * - `tokenId` must not exist. + * - `to` cannot be the zero address. + * + * Emits a {Transfer} event. + */ + function _mint(address to, uint256 tokenId) internal virtual { + require(to != address(0), "ERC721: mint to the zero address"); + require(!_exists(tokenId), "ERC721: token already minted"); + + _beforeTokenTransfer(address(0), to, tokenId); + + _balances[to] += 1; + _owners[tokenId] = to; + + emit Transfer(address(0), to, tokenId); + } + + /** + * @dev Destroys `tokenId`. + * The approval is cleared when the token is burned. + * + * Requirements: + * + * - `tokenId` must exist. + * + * Emits a {Transfer} event. + */ + function _burn(uint256 tokenId) internal virtual { + address owner = ERC721.ownerOf(tokenId); + + _beforeTokenTransfer(owner, address(0), tokenId); + + // Clear approvals + _approve(address(0), tokenId); + + _balances[owner] -= 1; + delete _owners[tokenId]; + + emit Transfer(owner, address(0), tokenId); + } + + /** + * @dev Transfers `tokenId` from `from` to `to`. + * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - `tokenId` token must be owned by `from`. + * + * Emits a {Transfer} event. + */ + function _transfer(address from, address to, uint256 tokenId) internal virtual { + require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); + require(to != address(0), "ERC721: transfer to the zero address"); + + _beforeTokenTransfer(from, to, tokenId); + + // Clear approvals from the previous owner + _approve(address(0), tokenId); + + _balances[from] -= 1; + _balances[to] += 1; + _owners[tokenId] = to; + + emit Transfer(from, to, tokenId); + } + + /** + * @dev Approve `to` to operate on `tokenId` + * + * Emits a {Approval} event. + */ + function _approve(address to, uint256 tokenId) internal virtual { + _tokenApprovals[tokenId] = to; + emit Approval(ERC721.ownerOf(tokenId), to, tokenId); + } + + /** + * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. + * The call is not executed if the target address is not a contract. + * + * @param from address representing the previous owner of the given token ID + * @param to target address that will receive the tokens + * @param tokenId uint256 ID of the token to be transferred + * @param _data bytes optional data to send along with the call + * @return bool whether the call correctly returned the expected magic value + */ + function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) + private returns (bool) + { + if (to.isContract()) { + try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) { + return retval == IERC721Receiver(to).onERC721Received.selector; + } catch (bytes memory reason) { + if (reason.length == 0) { + revert("ERC721: transfer to non ERC721Receiver implementer"); + } else { + // solhint-disable-next-line no-inline-assembly + assembly { + revert(add(32, reason), mload(reason)) + } + } + } + } else { + return true; + } + } + + /** + * @dev Hook that is called before any token transfer. This includes minting + * and burning. + * + * Calling conditions: + * + * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be + * transferred to `to`. + * - When `from` is zero, `tokenId` will be minted for `to`. + * - When `to` is zero, ``from``'s `tokenId` will be burned. + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { } +} diff --git a/tests/syntax-tests/source/Solidity/LICENSE.md b/tests/syntax-tests/source/Solidity/LICENSE.md new file mode 100644 index 00000000..a8d93c12 --- /dev/null +++ b/tests/syntax-tests/source/Solidity/LICENSE.md @@ -0,0 +1,27 @@ +The `ERC721.sol` file has been added from +[](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol) +under the following license: + +The MIT License (MIT) + +Copyright (c) 2016-2020 zOS Global Limited + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + From 9eb26b702c0a7a8e501ebcec1cb38fbf1d7e196f Mon Sep 17 00:00:00 2001 From: Ersikan Date: Mon, 29 Mar 2021 15:11:31 +0200 Subject: [PATCH 09/11] Add syntax test for Vyper language --- .../highlighted/Vyper/crowdsale.vy | 89 ++++++++ tests/syntax-tests/source/Vyper/LICENSE.md | 205 ++++++++++++++++++ tests/syntax-tests/source/Vyper/crowdsale.vy | 89 ++++++++ 3 files changed, 383 insertions(+) create mode 100644 tests/syntax-tests/highlighted/Vyper/crowdsale.vy create mode 100644 tests/syntax-tests/source/Vyper/LICENSE.md create mode 100644 tests/syntax-tests/source/Vyper/crowdsale.vy diff --git a/tests/syntax-tests/highlighted/Vyper/crowdsale.vy b/tests/syntax-tests/highlighted/Vyper/crowdsale.vy new file mode 100644 index 00000000..c2eb7cc6 --- /dev/null +++ b/tests/syntax-tests/highlighted/Vyper/crowdsale.vy @@ -0,0 +1,89 @@ +# IndividuallyCappedCrowdsale +# Contributors: Binod Nirvan +# This file is released under Apache 2.0 license. +# @dev Crowdsale with a limit for total contributions. +# Ported from Open Zeppelin +# https://github.com/OpenZeppelin +#  +# See https://github.com/OpenZeppelin +# Open Zeppelin tests ported: Crowdsale.test.js + + +#@dev ERC20/223 Features referenced by this contract +contract TokenContract: + def transfer(_to: address, _value: uint256) -> bool: modifying + +# Event for token purchase logging +# @param _purchaser who paid for the tokens +# @param _beneficiary who got the tokens +# @param _value weis paid for purchase +# @param _amount amount of tokens purchased +TokenPurchase: event({_purchaser: indexed(address), _beneficiary: indexed(address), _value: uint256(wei), _amount: uint256}) + +# The token being sold +token: public(address) + +#Address where funds are collected +wallet: public(address) + +# How many token units a buyer gets per wei. +# The rate is the conversion between wei and the smallest and indivisible token unit. +# So, if you are using a rate of 1 with a DetailedERC20 token with 3 decimals called TOK +# 1 wei will give you 1 unit, or 0.001 TOK. +rate: public(uint256) + +#Amount of wei raised +weiRaised: public(uint256(wei)) + +@public +def __init__(_rate: uint256, _wallet: address, _token: address): + """ + @dev Initializes this contract + @param _rate Number of token units a buyer gets per wei + @param _wallet Address where collected funds will be forwarded to + @param _token Address of the token being sold + """ + + assert _rate > 0, "Invalid value supplied for the parameter \"_rate\"." + assert _wallet != ZERO_ADDRESS, "Invalid wallet address." + assert _token != ZERO_ADDRESS, "Invalid token address." + + self.rate = _rate + self.wallet = _wallet + self.token = _token + +@private +@constant +def getTokenAmount(_weiAmount: uint256) -> uint256: + return _weiAmount * self.rate + + +@private +def processTransaction(_sender: address, _beneficiary: address, _weiAmount: uint256(wei)): + #pre validate + assert _beneficiary != ZERO_ADDRESS, "Invalid address." + assert _weiAmount != 0, "Invalid amount received." + + #calculate the number of tokens for the Ether contribution. + tokens: uint256 = self.getTokenAmount(as_unitless_number(_weiAmount)) +  + self.weiRaised += _weiAmount + + #process purchase + assert TokenContract(self.token).transfer(_beneficiary, tokens), "Could not forward funds due to an unknown error." + log.TokenPurchase(_sender, _beneficiary, _weiAmount, tokens) + + #forward funds to the receiving wallet address. + send(self.wallet, _weiAmount) + + #post validate + +@public +@payable +def buyTokens(_beneficiary: address): + self.processTransaction(msg.sender, _beneficiary, msg.value) + +@public +@payable +def __default__(): + self.processTransaction(msg.sender, msg.sender, msg.value) diff --git a/tests/syntax-tests/source/Vyper/LICENSE.md b/tests/syntax-tests/source/Vyper/LICENSE.md new file mode 100644 index 00000000..5bbdd36b --- /dev/null +++ b/tests/syntax-tests/source/Vyper/LICENSE.md @@ -0,0 +1,205 @@ +The `crowdsale.vy` file has been added from +[](https://github.com/binodnp/vyper-crowdsale/blob/master/contracts/crowdsale.v.py) +under the following license: + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/tests/syntax-tests/source/Vyper/crowdsale.vy b/tests/syntax-tests/source/Vyper/crowdsale.vy new file mode 100644 index 00000000..8a74cf93 --- /dev/null +++ b/tests/syntax-tests/source/Vyper/crowdsale.vy @@ -0,0 +1,89 @@ +# IndividuallyCappedCrowdsale +# Contributors: Binod Nirvan +# This file is released under Apache 2.0 license. +# @dev Crowdsale with a limit for total contributions. +# Ported from Open Zeppelin +# https://github.com/OpenZeppelin +# +# See https://github.com/OpenZeppelin +# Open Zeppelin tests ported: Crowdsale.test.js + + +#@dev ERC20/223 Features referenced by this contract +contract TokenContract: + def transfer(_to: address, _value: uint256) -> bool: modifying + +# Event for token purchase logging +# @param _purchaser who paid for the tokens +# @param _beneficiary who got the tokens +# @param _value weis paid for purchase +# @param _amount amount of tokens purchased +TokenPurchase: event({_purchaser: indexed(address), _beneficiary: indexed(address), _value: uint256(wei), _amount: uint256}) + +# The token being sold +token: public(address) + +#Address where funds are collected +wallet: public(address) + +# How many token units a buyer gets per wei. +# The rate is the conversion between wei and the smallest and indivisible token unit. +# So, if you are using a rate of 1 with a DetailedERC20 token with 3 decimals called TOK +# 1 wei will give you 1 unit, or 0.001 TOK. +rate: public(uint256) + +#Amount of wei raised +weiRaised: public(uint256(wei)) + +@public +def __init__(_rate: uint256, _wallet: address, _token: address): + """ + @dev Initializes this contract + @param _rate Number of token units a buyer gets per wei + @param _wallet Address where collected funds will be forwarded to + @param _token Address of the token being sold + """ + + assert _rate > 0, "Invalid value supplied for the parameter \"_rate\"." + assert _wallet != ZERO_ADDRESS, "Invalid wallet address." + assert _token != ZERO_ADDRESS, "Invalid token address." + + self.rate = _rate + self.wallet = _wallet + self.token = _token + +@private +@constant +def getTokenAmount(_weiAmount: uint256) -> uint256: + return _weiAmount * self.rate + + +@private +def processTransaction(_sender: address, _beneficiary: address, _weiAmount: uint256(wei)): + #pre validate + assert _beneficiary != ZERO_ADDRESS, "Invalid address." + assert _weiAmount != 0, "Invalid amount received." + + #calculate the number of tokens for the Ether contribution. + tokens: uint256 = self.getTokenAmount(as_unitless_number(_weiAmount)) + + self.weiRaised += _weiAmount + + #process purchase + assert TokenContract(self.token).transfer(_beneficiary, tokens), "Could not forward funds due to an unknown error." + log.TokenPurchase(_sender, _beneficiary, _weiAmount, tokens) + + #forward funds to the receiving wallet address. + send(self.wallet, _weiAmount) + + #post validate + +@public +@payable +def buyTokens(_beneficiary: address): + self.processTransaction(msg.sender, _beneficiary, msg.value) + +@public +@payable +def __default__(): + self.processTransaction(msg.sender, msg.sender, msg.value) From e219c8fc03b632272d7a75f30f364fcdcee0a9b0 Mon Sep 17 00:00:00 2001 From: Ersikan Date: Tue, 30 Mar 2021 17:44:15 +0200 Subject: [PATCH 10/11] Update SublimeEthereum version A fix I submitted upstream was merged, and this commit bumps the submodule to include it. --- assets/syntaxes/02_Extra/SublimeEthereum | 2 +- tests/syntax-tests/highlighted/Solidity/ERC721.sol | 2 +- tests/syntax-tests/highlighted/Vyper/crowdsale.vy | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/syntaxes/02_Extra/SublimeEthereum b/assets/syntaxes/02_Extra/SublimeEthereum index 4f775259..b60e0a3e 160000 --- a/assets/syntaxes/02_Extra/SublimeEthereum +++ b/assets/syntaxes/02_Extra/SublimeEthereum @@ -1 +1 @@ -Subproject commit 4f775259cd15a50a3a18f433cbd4024f46d30ce3 +Subproject commit b60e0a3e00e68263fcf35ba1a2e0bd0f6e3544f9 diff --git a/tests/syntax-tests/highlighted/Solidity/ERC721.sol b/tests/syntax-tests/highlighted/Solidity/ERC721.sol index a04bea91..7a30e357 100644 --- a/tests/syntax-tests/highlighted/Solidity/ERC721.sol +++ b/tests/syntax-tests/highlighted/Solidity/ERC721.sol @@ -15,7 +15,7 @@  * the Metadata extension, but not including the Enumerable extension, which is available separately as  * {ERC721Enumerable}.  */ -contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { +contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {  using Address for address;  using Strings for uint256; diff --git a/tests/syntax-tests/highlighted/Vyper/crowdsale.vy b/tests/syntax-tests/highlighted/Vyper/crowdsale.vy index c2eb7cc6..4f5f3217 100644 --- a/tests/syntax-tests/highlighted/Vyper/crowdsale.vy +++ b/tests/syntax-tests/highlighted/Vyper/crowdsale.vy @@ -10,7 +10,7 @@ #@dev ERC20/223 Features referenced by this contract -contract TokenContract: +contract TokenContract:  def transfer(_to: address, _value: uint256) -> bool: modifying # Event for token purchase logging From 91a347bf6d549ba543f1b4bfdc2a05f269c975c8 Mon Sep 17 00:00:00 2001 From: Allen Wild Date: Sun, 2 May 2021 14:58:12 -0400 Subject: [PATCH 11/11] Fix less version parsing for minor versions of less Less 581.2 is here, and it has a ".2" in the version string, which can't be parsed as a usize. Update the check to find a non-digit character rather than a space. This ignores the minor version, but parses the major version correctly. --- src/less.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/less.rs b/src/less.rs index 34b57549..f1adca81 100644 --- a/src/less.rs +++ b/src/less.rs @@ -11,7 +11,7 @@ pub fn retrieve_less_version(less_path: &dyn AsRef) -> Option { fn parse_less_version(output: &[u8]) -> Option { if output.starts_with(b"less ") { let version = std::str::from_utf8(&output[5..]).ok()?; - let end = version.find(' ')?; + let end = version.find(|c: char| !c.is_ascii_digit())?; version[..end].parse::().ok() } else { None @@ -57,6 +57,19 @@ Home page: http://www.greenwoodsoftware.com/less"; assert_eq!(Some(551), parse_less_version(output)); } +#[test] +fn test_parse_less_version_581_2() { + let output = b"less 581.2 (PCRE2 regular expressions) +Copyright (C) 1984-2021 Mark Nudelman + +less comes with NO WARRANTY, to the extent permitted by law. +For information about the terms of redistribution, +see the file named README in the less distribution. +Home page: https://greenwoodsoftware.com/less"; + + assert_eq!(Some(581), parse_less_version(output)); +} + #[test] fn test_parse_less_version_wrong_program() { let output = b"more from util-linux 2.34";