-
-
Save RezzedUp/e75847a72152871619eeec31f5700db2 to your computer and use it in GitHub Desktop.
Skim Compiler build #177, bootstrapped of course. Requires Skript 2.2, SkQuery, and SkUtilities. Not recommended for use (yet)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Skim-Compiler v0.0.1 compiled with Skim Compiler | |
#@: --> start 'plugins/Skript/projects/compiler/src/main.sk' @ 0 | |
options: | |
SOURCE_DIRECTORY: plugins/Skript/projects | |
SCRIPTS_DIRECTORY: plugins/Skript/scripts | |
STORAGE: compile-data | |
#@: --> start 'plugins/Skript/projects/compiler/src/errors/Error.sk' @ 0 | |
# | |
# ERRORS | |
# | |
# Append an error to a compile-data object. | |
# Returns the index of the error. | |
function appendCompilerError(data: text, error: text, file: text="", line: number=-1) :: text: | |
set {_size} to amount of {->%{_data}%::errors::*} | |
set {_index} to {_size} + 1 | |
set {_index} to "%{_index}%" | |
set {->%{_data}%::errors::%{_index}%} to {_error} | |
if length of {_file} is greater than 0: | |
set {->%{_data}%::errors::%{_index}%::file} to {_file} | |
if {_line} is greater than 0: | |
set {->%{_data}%::errors::%{_index}%::line} to {_line} | |
return {_index} | |
function throwCompilerError(data: text, error: text, file: text="", line: number=-1) :: text: | |
set {_index} to appendCompilerError({_data}, {_error}, {_file}, {_line}) | |
set {->%{_data}%::error-thrown} to {_index} | |
set {->%{_data}%::errors::%{_index}%::thrown} to true | |
return {_index} | |
sub "Skim:Compiler:print-errors": | |
set {_data} to parameter 1 | |
set {_size} to amount of {->%{_data}%::errors::*} | |
{_size} is greater than 0 | |
set {_to} to {->%{_data}%::sender} | |
if {->%{_data}%::error-thrown} is set: | |
set {_color} to "&c" | |
if {_size} is 1: | |
set {_amount} to "An error has occurred." | |
else: | |
set {_amount} to "Several errors have occurred." | |
else: | |
set {_color} to "&6" | |
if {_size} is 1: | |
set {_amount} to "A warning has occurred." | |
else: | |
set {_amount} to "Several warnings have occurred." | |
send "%{_color}%## --- [%script%.sk] --- %{_amount}%" to {_to} | |
loop {->%{_data}%::errors::*}: | |
set {_file} to {->%{_data}%::errors::%loop-index%::file} | |
set {_line} to {->%{_data}%::errors::%loop-index%::line} | |
set {_context} to "" | |
if {_file} is set: | |
set {_context} to "in %{_file}% " | |
if {_line} is set: | |
set {_context} to "%{_context}%@ line %{_line}%" | |
send "%{_color}%## &f%loop-value%" to {_to} | |
if length of {_context} is greater than 0: | |
send "%{_color}%## --> &7%{_context}%" to {_to} | |
delete {_file} | |
delete {_line} | |
send "%{_color}%## --- [end] ---" to {_to} | |
# | |
# Check if error is thrown | |
# | |
function canContinue(data: text) :: boolean: | |
if {->%{_data}%::error-thrown} is set: | |
return false | |
return true | |
function canContinueOtherwiseWarn(data: text) :: boolean: | |
set {_continue} to canContinue({_data}) | |
if not {_continue}: | |
invoke "Skim:Compiler:print-errors" from {_data} | |
return {_continue} | |
#@: --> end 'plugins/Skript/projects/compiler/src/errors/Error.sk' | |
#@: --> resume 'plugins/Skript/projects/compiler/src/main.sk' @ 8 | |
#@: --> start 'plugins/Skript/projects/compiler/src/project/ProjectConfig.sk' @ 0 | |
function parseProjectConfig(data: text): | |
invoke "debug" from script and "Called parseProjectConfig(%{_data}%)" | |
set {_file} to {->%{_data}%::project-config} | |
if file {_file} doesn't exist: | |
throwCompilerError({_data}, "Missing project configuration file.") | |
stop | |
loop yaml nodes with keys "" from file {_file}: | |
set {_value} to yaml value "%loop-value%" from file {_file} | |
set {_value} to "%{_value}%" | |
if {_value} starts with "[": | |
if {_value} ends with "]": | |
invoke "debug" from script and "'%{_value}%' is a list" | |
set {_nodes::%loop-value%} to "list" | |
add yaml list "%loop-value%" from file {_file} to {_nodes::%loop-value%::values::*} | |
if {_nodes::%loop-value%} is not set: | |
if {_value} doesn't start with "MemorySection[": | |
set {_nodes::%loop-value%} to "value" | |
set {_nodes::%loop-value%::value} to {_value} | |
#! TODO: @debug section | |
loop {_nodes::*}: | |
set {_node} to loop-index | |
replace all "." in {_node} with "-" | |
if loop-value is "list": | |
invoke "debug" from script and "yaml node %loop-index% is a list: '%{_nodes::%loop-index%::values::*}%'" | |
set {->%{_data}%::%{_node}%} to true | |
set {->%{_data}%::%{_node}%::*} to {_nodes::%loop-index%::values::*} | |
else: | |
invoke "debug" from script and "yaml node %loop-index% is a value: '%{_nodes::%loop-index%::value}%'" | |
set {_value} to {_nodes::%loop-index%::value} | |
if {_value} is "true": | |
set {->%{_data}%::%{_node}%} to true | |
else if {_value} is "false": | |
set {->%{_data}%::%{_node}%} to false | |
else: | |
set {->%{_data}%::%{_node}%} to {_value} | |
#@: --> end 'plugins/Skript/projects/compiler/src/project/ProjectConfig.sk' | |
#@: --> resume 'plugins/Skript/projects/compiler/src/main.sk' @ 10 | |
#@: --> start 'plugins/Skript/projects/compiler/src/Compiler.sk' @ 0 | |
#@: --> start 'plugins/Skript/projects/compiler/src/Files.sk' @ 0 | |
function getSourceFilePath(data: text, file: text) :: text: | |
set {_source} to {->%{_data}%::project-source} | |
set {_path} to "%{_source}%/%{_file}%" | |
if {_path} doesn't end with ".sk": | |
set {_path} to "%{_path}%.sk" | |
return {_path} | |
#@: --> end 'plugins/Skript/projects/compiler/src/Files.sk' | |
#@: --> resume 'plugins/Skript/projects/compiler/src/Compiler.sk' @ 1 | |
#@: --> start 'plugins/Skript/projects/compiler/src/Preprocessor.sk' @ 0 | |
function isAllowedByDebugState(data: text, file: text) :: boolean: | |
# Debugging is enabled, so allow all debugging. | |
if {->%{_data}%::debug} is true: | |
return true | |
# Debuggin isn't enabled and a debug section is open, so don't allow debugging. | |
if {->%{_data}%::files::%{_file}%::parser-options::debug} is set: | |
return false | |
# Allow everything else. | |
return true | |
# | |
# Parses the leading whitespace of a line. | |
# Submits results to: [data]->files->[file]->lines->[line]->whitespace | |
# Returns the remaining text. | |
# | |
function extractLeadingWhitespace(data: text, file: text, line: number, text: text) :: text: | |
set {_whitespace} to "" | |
if length of {_text} is 0: | |
set {_text} to "" | |
set {_chars::*} to {_text} split at "" | |
loop {_chars::*}: | |
if loop-value is " ": | |
set {_whitespace} to "%{_whitespace}%%loop-value%" | |
else: | |
set {->%{_data}%::files::%{_file}%::lines::%{_line}%::whitespace} to {_whitespace} | |
set {_whitespace-length} to length of {_whitespace} | |
set {_text-length} to length of {_text} | |
set {_return} to the last ({_text-length} - {_whitespace-length}) characters of {_text} | |
if {_return} isn't set: | |
set {_return} to "" | |
return {_return} | |
return {_text} | |
# | |
# | |
# | |
function parseCompilerDirective(data: text, file: text, line: number, text: text): | |
set {_submit} to "%{_data}%::files::%{_file}%" | |
set {_parts::*} to {_text} parsed as "@%string% <""?>%string%<""?>" | |
if amount of {_parts::*} is less than or equal to 0: | |
set {_parts::*} to {_text} parsed as "@%string%(\:| \-\-\>) %string%" | |
set {_directive} to {_parts::1} | |
set {_directive-text} to {_parts::2} | |
# | |
# @start "section" | |
# -- or -- | |
# @begin "section" | |
# | |
# @end "section" | |
# -- or -- | |
# @stop "section" | |
# | |
if {_directive} is "start" or "begin" or "end" or "stop": | |
if {_directive} is "start" or "begin": | |
set {->%{_submit}%::parser-options::%{_directive-text}%} to true | |
else: | |
delete {->%{_submit}%::parser-options::%{_directive-text}%} | |
stop | |
isAllowedByDebugState({_data}, {_file}) is true | |
# | |
# @debug: <an expression here> | |
# -- or -- | |
# @debug --> <an expression here> | |
# | |
if {_directive} is "debug": | |
if {->%{_submit}%::parser-options::debug} isn't set: | |
set {_reset-parser-option} to true | |
set {->%{_submit}%::parser-options::debug} to true | |
if isAllowedByDebugState({_data}, {_file}): | |
set {->%{_submit}%::lines::%{_line}%::directive-submission} to {_directive-text} | |
if {_reset-parser-option} is set: | |
delete {->%{_submit}%::parser-options::debug} | |
# | |
# @include "local-project/path" | |
# | |
else if {_directive} is "include": | |
if length of {->%{_submit}%::lines::%{_line}%::whitespace} is greater than 0: | |
throwCompilerError({_data}, "Whitespace before '%{_directive}%' is invalid", {_file}, {_line}) | |
stop | |
set {_include} to getSourceFilePath({_data}, {_directive-text}) | |
# If it's already included, then there's no reason to include it again. | |
{->%{_data}%::includes::%{_include}%::is-included} is not set | |
# Checking for circular inclusions... | |
if {->%{_data}%::includes::%{_include}%} is set: | |
set {_within} to {->%{_data}%::includes::%{_include}%::within-file} | |
set {_at-line} to {->%{_data}%::includes::%{_include}%::at-line} | |
set {_warning} to "Invalid inclusion: '%{_text}%' because its inclusion from within '%{_within}%' at line %{_at-line}% is incomplete" | |
throwCompilerError({_data}, {_warning}, {_file}, {_line}) | |
set {->%{_data}%::inclusion-error} to true | |
stop | |
set {->%{_data}%::includes::%{_include}%} to {_include} | |
set {->%{_data}%::includes::%{_include}%::within-file} to {_file} | |
set {->%{_data}%::includes::%{_include}%::at-line} to {_line} | |
invoke "Skim:Compiler:parse-file" from {_data} and {_include} | |
set {->%{_data}%::includes::%{_include}%::is-included} to true | |
if not canContinue({_data}): | |
{->%{_data}%::inclusion-error} is not set | |
throwCompilerError({_data}, "Invalid inclusion: '%{_text}%'", {_file}, {_line}) | |
set {->%{_data}%::inclusion-error} to true | |
stop | |
else: | |
appendCompilerError({_data}, "Unknown directive: '%{_text}%'", {_file}, {_line}) | |
# | |
# | |
# | |
function preprocessSkimLine(data: text, file: text, line: number, text: text) :: text: | |
if not canContinue({_data}): | |
return "" | |
# | |
# Parse a compiler directive. | |
# | |
if {_text} starts with "@": | |
parseCompilerDirective({_data}, {_file}, {_line}, {_text}) | |
# | |
# Resets the {_text} variable if a directive submission exists. | |
# '@debug: send "done."' -> 'send "done."' | |
# Otherwise excludes the line. | |
# | |
if {->%{_data}%::files::%{_file}%::lines::%{_line}%::directive-submission} is set: | |
set {_text} to {->%{_data}%::files::%{_file}%::lines::%{_line}%::directive-submission} | |
else: | |
return "##@:exclude" | |
# | |
# Don't parse skim within a "raw" section. | |
# | |
if {->%{_data}%::files::%{_file}%::parser-options::raw} is set: | |
return {_text} | |
# | |
# Exclude all lines within a "debug" section if debugging is disabled. | |
# | |
if not isAllowedByDebugState({_data}, {_file}): | |
return "##@:exclude" | |
# | |
# Remove skim comments. | |
# '#@' -> '<exclude line>' | |
# | |
if {_text} starts with "##@": | |
return "##@:exclude" | |
# | |
# Replace empty function definitions. | |
# 'function thing():' -> 'function thing(~: boolean=true):' | |
# | |
if {_text} starts with "function ": | |
set {_function::*} to {_text} parsed as "function %string%\(\)%string%[<##?@.*>]" | |
amount of {_function::*} is more than or equal to 2 | |
set {_function} to "function %{_function::1}%(~: boolean=true)" | |
set {_function-scope} to {_function::2} | |
if {_function-scope} starts with "::": | |
return "%{_function}% %{_function-scope}%" | |
else: | |
return "%{_function}%%{_function-scope}%" | |
# | |
# Replace empty returns with 'stop' | |
# | |
if {_text} is "return": | |
return "stop" | |
# | |
# Replace debug statements or remove them if debugging is disabled. | |
# 'debug "something"' -> 'invoke "debug" from script and "something"' | |
# | |
if {_text} starts with "debug ": | |
if {->%{_data}%::debug} is true: | |
set {_debug-text} to the last (length of {_text} - 6) characters of {_text} | |
return "invoke ""debug"" from script and %{_debug-text}%" | |
else: | |
return "##@:exclude" | |
return {_text} | |
#@: --> end 'plugins/Skript/projects/compiler/src/Preprocessor.sk' | |
#@: --> resume 'plugins/Skript/projects/compiler/src/Compiler.sk' @ 3 | |
# | |
# COMPILATION | |
# | |
function parseSkimStatement(data: text, file: text, line: number, text: text, in-string: boolean=false, in-expression: boolean=false) :: text: | |
if not canContinue({_data}): | |
return "" | |
set {_active} to true | |
if {_in-string}: | |
if not {_in-expression}: | |
set {_active} to false | |
set {_characters::*} to {_text} split at "" | |
set {_index} to 0 | |
set {_new} to "" | |
while {_index} is less than amount of {_characters::*}: | |
add 1 to {_index} | |
set {_char} to "" | |
set {_char} to {_characters::%{_index}%} | |
set {_next} to "" | |
set {_next-index} to {_index} + 1 | |
set {_next} to {_characters::%{_next-index}%} | |
if {_char} is "[": | |
{_state::special} is not set | |
set {_char} to "{_" | |
else if {_char} is "]": | |
delete {_state::special} | |
set {_char} to "}" | |
else if {_char} is "$": | |
if {_next} is "[": | |
set {_state::special} to true | |
set {_char} to "" | |
set {_new} to "%{_new}%%{_char}%" | |
return {_new} | |
# | |
# | |
# | |
sub "Skim:Compiler:parse-line": | |
set {_data} to parameter 1 | |
set {_file} to parameter 2 | |
# TODO: complete | |
# | |
# Parses a line then submits to the output | |
# | |
function parseSkimLine(data: text, file: text, line: number) :: text: | |
set {_var} to "%{_data}%::files::%{_file}%::lines::%{_line}%" | |
set {_text} to extractLeadingWhitespace({_data}, {_file}, {_line}, {->%{_var}%}) | |
set {_whitespace} to {->%{_var}%::whitespace} | |
set {_text} to preprocessSkimLine({_data}, {_file}, {_line}, {_text}) | |
if not canContinue({_data}): | |
return "" | |
set {_text} to parseSkimStatement({_data}, {_file}, {_line}, {_text}) | |
if {_text} starts with "##@:": | |
return {_text} | |
else: | |
return "%{_whitespace}%%{_text}%" | |
# | |
# Expected: | |
# Raw file contents at: | |
# [data]->files->[file]->lines::* | |
# Parsed output at: | |
# [data]->compiled-output->lines::* | |
# | |
sub "Skim:Compiler:parse-file": | |
set {_data} to parameter 1 | |
set {_file} to parameter 2 | |
if file {_file} doesn't exist: | |
throwCompilerError({_data}, "The file '%{_file}%' doesn't exist") | |
stop | |
add "##@: --> start '%{_file}%' @ 0" to {->%{_data}%::compiled-output::lines::*} | |
set {->%{_data}%::files::%{_file}%} to {_file} | |
set {->%{_data}%::files::%{_file}%::lines::*} to file contents of {_file} | |
add {_file} to {->%{_data}%::inclusion-stack::*} | |
set {_stack-index} to amount of {->%{_data}%::inclusion-stack::*} | |
loop {->%{_data}%::files::%{_file}%::lines::*}: | |
set {_line} to loop-index parsed as number | |
set {->%{_data}%::files::%{_file}%::current-line} to {_line} | |
set {_text} to "" | |
set {_text} to parseSkimLine({_data}, {_file}, {_line}) | |
if not canContinue({_data}): | |
stop | |
{_text} is not "##@:exclude" | |
add {_text} to {->%{_data}%::compiled-output::lines::*} | |
add "##@: --> end '%{_file}%'" to {->%{_data}%::compiled-output::lines::*} | |
delete {->%{_data}%::inclusion-stack::%{_stack-index}%} | |
set {_stack-size} to amount of {->%{_data}%::inclusion-stack::*} | |
if {_stack-size} is greater than or equal to 1: | |
set {_resume} to {->%{_data}%::inclusion-stack::%{_stack-size}%} | |
set {_resume-line} to {->%{_data}%::files::%{_resume}%::current-line} | |
add "##@: --> resume '%{_resume}%' @ %{_resume-line}%" to {->%{_data}%::compiled-output::lines::*} | |
# | |
# COMPILE SCRIPTS | |
# | |
function compileProject(data: text): | |
set {_main-file} to {->%{_data}%::project-main} | |
set {_main} to getSourceFilePath({_data}, {_main-file}) | |
if file {_main} doesn't exist: | |
throwCompilerError({_data}, "The main project file '%{_main}%' doesn't exist") | |
stop | |
set {->%{_data}%::includes::%{_main}%} to {_main} | |
set {->%{_data}%::includes::%{_main}%::within-file} to {_main} | |
set {->%{_data}%::includes::%{_main}%::at-line} to 0 | |
set {_name} to {->%{_data}%::project-name} | |
set {_version} to {->%{_data}%::project-version} | |
add "## %{_name}% v%{_version}% compiled with Skim Compiler" to {->%{_data}%::compiled-output::lines::*} | |
invoke "Skim:Compiler:parse-file" from {_data} and {_main} | |
canContinue({_data}) is true | |
set {_output} to {->%{_data}%::output-directory} | |
if file {_output} isn't a directory: | |
create directory {_output} | |
invoke "debug" from script and "Created directory: %{_output}%" | |
set {_filename} to {->%{_data}%::output-filename} | |
set {_file} to "%{_output}%/%{_filename}%" | |
if file {_file} exists: | |
delete file {_file} | |
create file {_file} | |
invoke "debug" from script and "Created file: %{_file}%" | |
set file contents of {_file} to {->%{_data}%::compiled-output::lines::*} | |
invoke "Skim:Compiler:save-build" from {_data} | |
# | |
# | |
# | |
sub "Skim:Compiler:save-build": | |
set {_data} to parameter 1 | |
{->%{_data}%::output-save-builds} is true | |
set {_output-dir} to {->%{_data}%::output-directory} | |
set {_build-dir} to "%{_output-dir}%/builds" | |
if file {_build-dir} isn't a directory: | |
create directory {_build-dir} | |
set {_latest-build-file} to "%{_build-dir}%/latest.build" | |
if file {_latest-build-file} doesn't exist: | |
create file {_latest-build-file} | |
set file contents of {_latest-build-file} to "0" | |
set {_latest-build-raw::*} to file contents of {_latest-build-file} | |
set {_latest-build-number} to "%{_latest-build-raw::1}%" parsed as number | |
set {_filename} to {->%{_data}%::output-filename} | |
replace ".sk" in {_filename} with "" | |
set {_saved} to false | |
while not {_saved}: | |
add 1 to {_latest-build-number} | |
set {_latest-build-filename} to "%{_filename}%-%{_latest-build-number}%.sk" | |
set {_latest-file} to "%{_build-dir}%/%{_latest-build-filename}%" | |
file {_latest-file} doesn't exist | |
set file contents of {_latest-build-file} to "%{_latest-build-number}%" | |
create file {_latest-file} | |
set file contents of {_latest-file} to {->%{_data}%::compiled-output::lines::*} | |
set {_saved} to true | |
# | |
# | |
# | |
function performCompilation(data: text): | |
set {_project-directory} to {->%{_data}%::project-directory} | |
if file "%{_project-directory}%" isn't a directory: | |
throwCompilerError({_data}, "The directory '%{_project-directory}%' does not exist") | |
else if {->%{_data}%::project-main} is not set: | |
throwCompilerError({_data}, "Missing 'main' entry in project.yml: cannot compile without main script", "project.yml") | |
canContinueOtherwiseWarn({_data}) is true | |
compileProject({_data}) | |
canContinueOtherwiseWarn({_data}) is true | |
set {_name} to {->%{_data}%::project-name} | |
send "&aDone. &fCompiled %{_name}%" to {->%{_data}%::sender} | |
if {->%{_data}%::deploy-enabled}: | |
set {_deploy} to {->%{_data}%::deploy-directory} | |
set {_filename} to {->%{_data}%::output-filename} | |
set {_deploy-path} to "%{_deploy}%/%{_filename}%" | |
if file {_deploy-path} exists: | |
delete file {_deploy-path} | |
set {_output-directory} to {->%{_data}%::output-directory} | |
set {_output-file} to "%{_output-directory}%/%{_filename}%" | |
create file {_deploy-path} | |
set file contents of {_deploy-path} to {->%{_data}%::compiled-output::lines::*} | |
send "&bDeployed." to {->%{_data}%::sender} | |
execute console command "/sk reload %{_filename}%" | |
invoke "Skim:Compiler:print-errors" from {_data} | |
#@: --> end 'plugins/Skript/projects/compiler/src/Compiler.sk' | |
#@: --> resume 'plugins/Skript/projects/compiler/src/main.sk' @ 12 | |
#@: --> start 'plugins/Skript/projects/compiler/src/CompileData.sk' @ 0 | |
on script load: | |
delete {->{@STORAGE}::*} | |
on script unload: | |
delete {->{@STORAGE}::*} | |
every 10 minutes: | |
loop {->{@STORAGE}::*}: | |
if {->{@STORAGE}::%loop-value%::discard-data} is set: | |
delete {->{@STORAGE}::%loop-value%::*} | |
delete {->{@STORAGE}::%loop-value%} | |
# | |
# Compile Data Constructor | |
# | |
function newCompileData(name: text) :: text: | |
set {_data} to "{@STORAGE}::%{_name}%" | |
if {->%{_data}%} is set: | |
delete {->%{_data}%::*} | |
delete {->%{_data}%} | |
set {->%{_data}%} to {_name} | |
set {->%{_data}%::project-name} to {_name} | |
set {->%{_data}%::project-version} to "1.0.0" | |
set {_project-directory} to "{@SOURCE_DIRECTORY}/%{_name}%" | |
set {->%{_data}%::project-directory} to {_project-directory} | |
set {->%{_data}%::project-config} to "%{_project-directory}%/project.yml" | |
set {->%{_data}%::project-source} to "%{_project-directory}%/src" | |
set {->%{_data}%::output-directory} to "%{_project-directory}%/out" | |
set {->%{_data}%::output-filename} to "%{_name}%.sk" | |
set {->%{_data}%::scripts-directory} to "{@SCRIPTS_DIRECTORY}" | |
set {->%{_data}%::deploy-enabled} to true | |
set {->%{_data}%::deploy-directory} to "{@SCRIPTS_DIRECTORY}" | |
set {->%{_data}%::output-save-builds} to true | |
set {->%{_data}%::content} to "## Generated by compile.sk%nl%" | |
parseProjectConfig({_data}) | |
return {_data} | |
# | |
# Discard data | |
# | |
function discardCompileData(data: text): | |
set {->%{_data}%::discard-data} to true | |
#@: --> end 'plugins/Skript/projects/compiler/src/CompileData.sk' | |
#@: --> resume 'plugins/Skript/projects/compiler/src/main.sk' @ 14 | |
on script load: | |
if file "{@SOURCE_DIRECTORY}" isn't a directory: | |
create directory "{@SOURCE_DIRECTORY}" | |
command /compile <text> <boolean=false>: | |
aliases: /skript-compiler, /compiler, /skc, /skrc, /skriptc, /skriptcompiler | |
trigger: | |
set {_data} to newCompileData(arg-1) | |
set {->%{_data}%::sender} to sender | |
set {->%{_data}%::debug} to arg-2 | |
performCompilation({_data}) | |
command /diagnose <text> <integer>: | |
aliases: /find-line, /findline, /skim-diagnose, /skim-find-line, /skim-findline, /skimfindline | |
trigger: | |
set {_filename} to arg-1 | |
set {_line} to arg-2 | |
if {_line} is less than 1: | |
send "&c&oError:&f The line number must be greater than 0." | |
stop | |
if {_filename} doesn't end with ".sk": | |
set {_filename} to "%{_filename}%.sk" | |
set {_file} to "{@SCRIPTS_DIRECTORY}/%{_filename}%" | |
if file {_file} doesn't exist: | |
send "&c&oError:&f The file '%{_file}%' doesn't exist." | |
stop | |
set {_lines::*} to file contents of {_file} | |
set {_line-count} to amount of {_lines::*} | |
if {_line-count} is less than {_line}: | |
send "&c&oError:&f The file '%{_file}%' only has %{_line-count}% lines." | |
stop | |
set {_line-displacement} to 0 | |
while {_line} is greater than 0: | |
set {_text} to "" | |
set {_text} to {_lines::%{_line}%} | |
delete {_meta::*} | |
if {_text} starts with "##@: --> ": | |
set {_meta::*} to {_text} parsed as "<##?>@: --\> %string% '%string%'" | |
set {_meta::*} to {_text} parsed as "<##?>@: --\> %string% '%string%' @ %integer%" | |
if {_meta::1} is "end": | |
set {_ignore::%{_meta::2}%} to {_meta::2} | |
else if {_meta::1} is "start" or "resume": | |
if {_meta::1} is "start": | |
if {_ignore::%{_meta::2}%} is set: | |
delete {_ignore::%{_meta::2}%} | |
amount of {_ignore::*} is less than or equal to 0: | |
set {_file-line} to {_line-displacement} + {_meta::3} | |
send "&3&oEstimated line location:&f Line %{_file-line}% in '%{_meta::2}%'" | |
stop | |
if amount of {_ignore::*} is less than or equal to 0: | |
add 1 to {_line-displacement} | |
set {_line} to {_line} - 1 | |
send "&c&oError:&f Unable to locate the original location for line %arg-2% in file '%{_file}%' (was it compiled with skim?)" | |
#@: --> end 'plugins/Skript/projects/compiler/src/main.sk' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment