Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preserver previous command results (avoid rerunning commands) #128

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
4 changes: 4 additions & 0 deletions shard.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
version: 2.0
shards:
crystalizer:
git: https://github.com/j8r/crystalizer.git
version: 1.0.0

readline:
git: https://github.com/crystal-lang/crystal-readline.git
version: 0.1.0+git.commit.0fb7d186da8e1b157998d98d1c96e99699b791eb
Expand Down
3 changes: 3 additions & 0 deletions shard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ dependencies:
readline:
github: crystal-lang/crystal-readline
branch: master
crystalizer:
github: j8r/crystalizer
version: ">= 1.0"

authors:
- Potapov Sergey <blake131313@gmail.com>
Expand Down
3 changes: 3 additions & 0 deletions src/icr.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ require "io/memory"
require "random/secure"
require "colorize"

require "crystalizer/json"

require "compiler/crystal/syntax"

require "./icr/command"
Expand All @@ -13,6 +15,7 @@ require "./icr/syntax_check_result"
require "./icr/highlighter"
require "./icr/console"


module Icr
VERSION = "0.8.0"
AUTHOR = "Potapov Sergey"
Expand Down
3 changes: 3 additions & 0 deletions src/icr/cli.cr
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,8 @@ end
print_usage_warning unless usage_warning_accepted
check_for_update unless update_check_disabled

libs.push(%{require "crystalizer/json"})
libs.push(%{require "json"})
libs.push(%{require "base64"})
code = libs.join(";")
Icr::Console.new(debug: is_debug, prompt_mode: prompt_mode).start(code)
31 changes: 31 additions & 0 deletions src/icr/command.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,39 @@ module Icr
# * type - type of input(require, class, module, method, regular, etc)
class Command
getter :type, :value
property cached_results = ""

def initialize(@type : Symbol, @value : String)
end

def regular?
type == :regular
end

def parsed_value
return value unless regular?

run_cmd = "__previous_result = (#{value});
Base64.strict_encode({
result: __previous_result.inspect,
serialized: %Q(#{encoded_var_value("__previous_result")} #{encoded_var_value(calc_var_name)})
}.to_json) + #{DELIMITER.inspect}"
cached_results.empty? ? run_cmd : cached_results
end

def encoded_var_value(var_name : String)
return "" if var_name.empty?

serialized = "\#{Crystalizer::JSON.serialize(#{var_name}).inspect}"
var_type = "\#{typeof(#{var_name})}"
"#{var_name} = Crystalizer::JSON.deserialize(#{serialized}, #{var_type}); "
end

# TODO: calc all variable names from the command
def calc_var_name
value.gsub(/\"(.*?)\"/, "")
.match(/(\w+) ?= ?(.*)/)
.try(&.[1]).to_s
end
end
end
2 changes: 1 addition & 1 deletion src/icr/command_stack.cr
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ module Icr
end

private def code(command_type, indent_level = 0)
cmds = @commands.select { |cmd| cmd.type == command_type }.map &.value
cmds = @commands.select { |cmd| cmd.type == command_type }.map &.parsed_value
cmds.map { |cmd| (" " * indent_level) + cmd }.join("\n")
end
end
Expand Down
3 changes: 2 additions & 1 deletion src/icr/console.cr
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ module Icr
end

private def process_command(command : String)
command = command.to_s.gsub(/\b__\b/) { last_value.to_s.strip }
command = command.to_s.gsub(/\b__\b/) { "__previous_result" }
result = check_syntax(command)
process_result(result, command)
end
Expand Down Expand Up @@ -168,6 +168,7 @@ module Icr
else
puts " => #{result.value}"
end
puts "\n"
else
puts " => ok"
end
Expand Down
19 changes: 19 additions & 0 deletions src/icr/executer.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require "base64"
require "json"
module Icr
# Build crystal source code file based on commands in CommandStack, executes it
# as crystal program and returns result as an instance of ExecutionResult.
Expand Down Expand Up @@ -26,6 +28,8 @@ module Icr
File.delete(@tmp_file_path)

if status.success?
return parse_regular_result(io_out.to_s) if @command_stack.commands.last.regular?

output, value = io_out.to_s.split(DELIMITER, 2)
new_output = output.sub(@previous_output, "")
@previous_output = output
Expand All @@ -43,6 +47,21 @@ module Icr
end
end

def parse_regular_result(io_result : String)
output, enc_cmd_res, cmd_output = io_result.to_s.split(DELIMITER)
result = decode_regular_result(enc_cmd_res)
@command_stack.commands.last.cached_results = result["serialized"]
res_output = (cmd_output.to_s[1..-1] + output.to_s)
@previous_output = res_output
ExecutionResult.new(true, result["result"], res_output, nil)
end

#@return { result: "...", serialized: "..." }
def decode_regular_result(enc_cmd_res)
str_cmd_res = Base64.decode_string(enc_cmd_res.gsub("\"", ""))
Hash(String, String).from_json(str_cmd_res)
end

def print_source_file
puts
puts "========================= ICR FILE BEGIN =========================="
Expand Down