tyrano_dsl 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +3 -0
  4. data/CODE_OF_CONDUCT.md +74 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +290 -0
  8. data/Rakefile +10 -0
  9. data/bin/setup +8 -0
  10. data/bin/tyrano_dsl.rb +21 -0
  11. data/lib/tyrano_dsl/elements/background.rb +31 -0
  12. data/lib/tyrano_dsl/elements/character.rb +49 -0
  13. data/lib/tyrano_dsl/elements/elements_module.rb +7 -0
  14. data/lib/tyrano_dsl/elements/jump_target.rb +18 -0
  15. data/lib/tyrano_dsl/elements/label.rb +19 -0
  16. data/lib/tyrano_dsl/elements/scene.rb +21 -0
  17. data/lib/tyrano_dsl/elements/stance.rb +26 -0
  18. data/lib/tyrano_dsl/elements/title_screen.rb +16 -0
  19. data/lib/tyrano_dsl/elements/variable.rb +22 -0
  20. data/lib/tyrano_dsl/elements/world.rb +62 -0
  21. data/lib/tyrano_dsl/elements_writers/background_writer.rb +30 -0
  22. data/lib/tyrano_dsl/elements_writers/character_writer.rb +32 -0
  23. data/lib/tyrano_dsl/elements_writers/characters_writer.rb +43 -0
  24. data/lib/tyrano_dsl/elements_writers/elements_writers_module.rb +27 -0
  25. data/lib/tyrano_dsl/elements_writers/scene_writer.rb +30 -0
  26. data/lib/tyrano_dsl/elements_writers/title_screen_writer.rb +87 -0
  27. data/lib/tyrano_dsl/elements_writers/variables_writer.rb +30 -0
  28. data/lib/tyrano_dsl/file_actions/clear_directory.rb +34 -0
  29. data/lib/tyrano_dsl/file_actions/create_file.rb +33 -0
  30. data/lib/tyrano_dsl/file_actions/file_copy.rb +36 -0
  31. data/lib/tyrano_dsl/file_actions/files_actions_module.rb +28 -0
  32. data/lib/tyrano_dsl/file_actions/json_patch.rb +47 -0
  33. data/lib/tyrano_dsl/main.rb +18 -0
  34. data/lib/tyrano_dsl/parsed_word.rb +22 -0
  35. data/lib/tyrano_dsl/parser.rb +58 -0
  36. data/lib/tyrano_dsl/parsing_context.rb +18 -0
  37. data/lib/tyrano_dsl/parsing_words/ask_question.rb +32 -0
  38. data/lib/tyrano_dsl/parsing_words/conditional_jump.rb +42 -0
  39. data/lib/tyrano_dsl/parsing_words/declare_background.rb +32 -0
  40. data/lib/tyrano_dsl/parsing_words/declare_character.rb +38 -0
  41. data/lib/tyrano_dsl/parsing_words/declare_label.rb +20 -0
  42. data/lib/tyrano_dsl/parsing_words/declare_variable.rb +30 -0
  43. data/lib/tyrano_dsl/parsing_words/display_text.rb +22 -0
  44. data/lib/tyrano_dsl/parsing_words/hide_character.rb +20 -0
  45. data/lib/tyrano_dsl/parsing_words/hide_message_window.rb +16 -0
  46. data/lib/tyrano_dsl/parsing_words/include_file.rb +26 -0
  47. data/lib/tyrano_dsl/parsing_words/jump.rb +22 -0
  48. data/lib/tyrano_dsl/parsing_words/parsing_words_module.rb +72 -0
  49. data/lib/tyrano_dsl/parsing_words/set_background.rb +21 -0
  50. data/lib/tyrano_dsl/parsing_words/set_character_stance.rb +23 -0
  51. data/lib/tyrano_dsl/parsing_words/set_title_screen_background.rb +25 -0
  52. data/lib/tyrano_dsl/parsing_words/show_character.rb +26 -0
  53. data/lib/tyrano_dsl/parsing_words/show_message_window.rb +16 -0
  54. data/lib/tyrano_dsl/parsing_words/start_scene.rb +30 -0
  55. data/lib/tyrano_dsl/parsing_words/update_variable.rb +37 -0
  56. data/lib/tyrano_dsl/tyrano_dsl.rb +3 -0
  57. data/lib/tyrano_dsl/tyrano_exception.rb +6 -0
  58. data/lib/tyrano_dsl/vocabulary.rb +84 -0
  59. data/lib/tyrano_dsl/writer.rb +114 -0
  60. data/lib/tyrano_dsl/writing_context.rb +123 -0
  61. data/lib/tyrano_dsl/writing_words/ask_question.rb +28 -0
  62. data/lib/tyrano_dsl/writing_words/conditional_jump.rb +37 -0
  63. data/lib/tyrano_dsl/writing_words/declare_background.rb +5 -0
  64. data/lib/tyrano_dsl/writing_words/declare_character.rb +5 -0
  65. data/lib/tyrano_dsl/writing_words/declare_label.rb +18 -0
  66. data/lib/tyrano_dsl/writing_words/declare_variable.rb +5 -0
  67. data/lib/tyrano_dsl/writing_words/display_text.rb +16 -0
  68. data/lib/tyrano_dsl/writing_words/hide_character.rb +13 -0
  69. data/lib/tyrano_dsl/writing_words/hide_message_window.rb +12 -0
  70. data/lib/tyrano_dsl/writing_words/include_file.rb +5 -0
  71. data/lib/tyrano_dsl/writing_words/jump.rb +18 -0
  72. data/lib/tyrano_dsl/writing_words/nop.rb +8 -0
  73. data/lib/tyrano_dsl/writing_words/set_background.rb +18 -0
  74. data/lib/tyrano_dsl/writing_words/set_character_stance.rb +20 -0
  75. data/lib/tyrano_dsl/writing_words/set_title_screen_background.rb +4 -0
  76. data/lib/tyrano_dsl/writing_words/show_character.rb +31 -0
  77. data/lib/tyrano_dsl/writing_words/show_message_window.rb +12 -0
  78. data/lib/tyrano_dsl/writing_words/start_scene.rb +9 -0
  79. data/lib/tyrano_dsl/writing_words/update_variable.rb +28 -0
  80. data/lib/tyrano_dsl/writing_words/writing_words_module.rb +43 -0
  81. data/tyrano_dsl.gemspec +37 -0
  82. metadata +210 -0
@@ -0,0 +1,87 @@
1
+ require_relative '../file_actions/create_file'
2
+ require_relative 'elements_writers_module'
3
+
4
+ # Write the title screen
5
+ class TyranoDsl::ElementsWriters::TitleScreenWriter
6
+
7
+ include TyranoDsl::ElementsWriters::ElementsWritersModule
8
+
9
+ # @param [TyranoDsl::Elements::World] world
10
+ # @return [Array]
11
+ def write(world)
12
+ log {'Writing title screen'}
13
+ background = get_background(world)
14
+ first_scene = get_first_scene(world)
15
+
16
+ content_text_content = title_screen_content(background, first_scene)
17
+ preload_text_content = preload_text([background.target_long_file_name])
18
+ [
19
+ TyranoDsl::FileActions::CreateFile.new(
20
+ File.join('data', 'scenario', "title_screen.ks"),
21
+ content_text_content
22
+ ),
23
+ TyranoDsl::FileActions::CreateFile.new(
24
+ File.join('data', 'scenario', 'system', "_title_screen.ks"),
25
+ preload_text_content
26
+ )
27
+
28
+ ]
29
+ end
30
+
31
+ private
32
+
33
+ # @param [TyranoDsl::Elements::Background] background
34
+ # @param [TyranoDsl::Elements::Scene] first_scene
35
+ def title_screen_content(background, first_scene)
36
+ <<HEREDOC
37
+ [_tb_system_call storage=system/_title_screen.ks]
38
+
39
+ [hidemenubutton]
40
+
41
+ [tb_keyconfig flag="0" ]
42
+ [tb_hide_message_window ]
43
+ [bg storage="#{background.target_short_file_name}" ]
44
+ *title
45
+
46
+ [glink text="New&nbsp;Game" x="600" y="370" target="*start" ]
47
+ [glink text="Load&nbsp;Game" x="600" y="470" target="*load" ]
48
+ [s ]
49
+ *start
50
+
51
+ [showmenubutton]
52
+
53
+ [cm ]
54
+ [tb_keyconfig flag="1" ]
55
+ [jump storage="#{first_scene.target_name}.ks" target="" ]
56
+ [s ]
57
+ *load
58
+
59
+ [cm ]
60
+ [showload]
61
+
62
+ [jump target="*title" storage="" ]
63
+ [s ]
64
+ HEREDOC
65
+ end
66
+
67
+ # @param [TyranoDsl::Elements::World] world
68
+ # @return [TyranoDsl::Elements::Scene]
69
+ def get_first_scene(world)
70
+ first_scene_name = world.title_screen.first_scene_name
71
+ unless first_scene_name
72
+ raise TyranoDsl::TyranoException, 'No scene defined'
73
+ end
74
+ world.scenes[first_scene_name]
75
+ end
76
+
77
+ # @param [TyranoDsl::Elements::World] world
78
+ # @return [TyranoDsl::Elements::Background]
79
+ def get_background(world)
80
+ background_name = world.title_screen.background
81
+ unless background_name
82
+ raise TyranoDsl::TyranoException, 'No background defined for the title screen'
83
+ end
84
+ world.backgrounds[background_name]
85
+ end
86
+
87
+ end
@@ -0,0 +1,30 @@
1
+ require_relative '../elements/variable'
2
+ require_relative '../file_actions/json_patch'
3
+ require_relative 'elements_writers_module'
4
+
5
+ # Write a variable
6
+ class TyranoDsl::ElementsWriters::VariablesWriter
7
+
8
+ include TyranoDsl::ElementsWriters::ElementsWritersModule
9
+
10
+ # @param [TyranoDsl::Elements::World] world
11
+ # @return [Array]
12
+ def write(world)
13
+ log {'Writing variables'}
14
+ variable_content = {}
15
+ world.variables.values.each do |variable|
16
+ variable_content[variable.target_name] = {
17
+ :val => variable.initial_value,
18
+ :kind => 'f'
19
+ }
20
+ end
21
+ [
22
+ TyranoDsl::FileActions::JsonPatch.new(
23
+ 'builder_config.json',
24
+ ['map_var'],
25
+ variable_content
26
+ )
27
+ ]
28
+ end
29
+
30
+ end
@@ -0,0 +1,34 @@
1
+ require 'fileutils'
2
+
3
+ require_relative 'files_actions_module'
4
+
5
+ # Remove all files from a directory
6
+
7
+ class TyranoDsl::FileActions::ClearDirectory
8
+
9
+ include TyranoDsl::FileActions::FileActionsModule
10
+
11
+ # @return [String]
12
+ attr_reader :path
13
+
14
+ # @param [String] path
15
+ def initialize(path)
16
+ @path = path
17
+ log {to_s}
18
+ end
19
+
20
+ # @param [String] tyrano_project_path
21
+ def run(tyrano_project_path)
22
+ full_path = File.join(tyrano_project_path, path)
23
+ log {"Cleaning [#{full_path}]"}
24
+ if File.exists? full_path
25
+ FileUtils.remove_entry full_path
26
+ end
27
+ FileUtils.mkdir_p full_path
28
+ end
29
+
30
+ def to_s
31
+ "Clear directory [#{path}]"
32
+ end
33
+
34
+ end
@@ -0,0 +1,33 @@
1
+ require_relative 'files_actions_module'
2
+
3
+ # Create a file with a custom content
4
+ class TyranoDsl::FileActions::CreateFile
5
+
6
+ include TyranoDsl::FileActions::FileActionsModule
7
+
8
+ # @return [String]
9
+ attr_reader :content
10
+ # @return [String]
11
+ attr_reader :path
12
+
13
+ # @param [String] path
14
+ # @param [String] content
15
+ def initialize(path, content)
16
+ @path = path
17
+ @content = content
18
+ log {self.to_s}
19
+ end
20
+
21
+ # @param [String] tyrano_project_path
22
+ def run(tyrano_project_path)
23
+ full_path = File.join(tyrano_project_path, path)
24
+ log {"Creating file [#{full_path}]"}
25
+ create_parent_dir_if_not_exist(full_path)
26
+ File.write(full_path, content)
27
+ end
28
+
29
+ def to_s
30
+ "Create file [#{path}]"
31
+ end
32
+
33
+ end
@@ -0,0 +1,36 @@
1
+ require 'fileutils'
2
+
3
+ require_relative 'files_actions_module'
4
+
5
+
6
+ # Direct copy of a file from a source to a destination
7
+ class TyranoDsl::FileActions::FileCopy
8
+
9
+ # @return [String]
10
+ attr_reader :from_path
11
+ # @return [String]
12
+ attr_reader :to_path
13
+
14
+ include TyranoDsl::FileActions::FileActionsModule
15
+
16
+ # @param [String] from_path
17
+ # @param [String] to_path
18
+ def initialize(from_path, to_path)
19
+ @from_path = from_path
20
+ @to_path = to_path
21
+ log {self.to_s}
22
+ end
23
+
24
+ # @param [String] tyrano_project_path
25
+ def run(tyrano_project_path)
26
+ full_path = File.join(tyrano_project_path, to_path)
27
+ log {"Copy file [#{from_path}] to [#{full_path}]"}
28
+ create_parent_dir_if_not_exist(full_path)
29
+ FileUtils.copy_file from_path, full_path
30
+ end
31
+
32
+ def to_s
33
+ "Copy file [#{from_path}] to [#{to_path}]"
34
+ end
35
+
36
+ end
@@ -0,0 +1,28 @@
1
+ require 'logger'
2
+
3
+ module TyranoDsl
4
+ module FileActions
5
+
6
+ # Helpers to write file actions
7
+ module FileActionsModule
8
+
9
+ protected
10
+
11
+ def create_parent_dir_if_not_exist(file_path)
12
+ parent_dir = File.dirname(file_path)
13
+ unless File.exists? parent_dir
14
+ FileUtils.mkdir_p parent_dir
15
+ end
16
+ end
17
+
18
+ def logger
19
+ @logger ||= Logger.new(STDOUT)
20
+ end
21
+
22
+ def log
23
+ logger.info(self.class) {yield}
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,47 @@
1
+ require 'json'
2
+
3
+ require_relative 'files_actions_module'
4
+
5
+ # Path a JSON file
6
+ class TyranoDsl::FileActions::JsonPatch
7
+
8
+ include TyranoDsl::FileActions::FileActionsModule
9
+
10
+ # @return [String]
11
+ attr_reader :file_path
12
+ # @return [Object]
13
+ attr_reader :patched_content
14
+ # @return [Array<String>]
15
+ attr_reader :patching_path
16
+
17
+ # @param [String] file_path
18
+ # @param [Array<String>] patching_path
19
+ # @param [Object] patched_content
20
+ def initialize(file_path, patching_path, patched_content)
21
+ @file_path = file_path
22
+ @patching_path = patching_path
23
+ @patched_content = patched_content
24
+ log {self.to_s}
25
+ end
26
+
27
+ # @param [String] tyrano_project_path
28
+ def run(tyrano_project_path)
29
+ full_path = File.join(tyrano_project_path, file_path)
30
+ log {"Patching file [#{full_path}] at #{patching_path}"}
31
+ unless File.exist? full_path
32
+ raise TyranoDsl::TyranoException, "Missing file [#{full_path}]"
33
+ end
34
+ content = JSON.parse(IO.read(full_path))
35
+ current_subtree = content
36
+ 0.upto(patching_path.length - 2) do |path_segment_index|
37
+ current_subtree = current_subtree[patching_path[path_segment_index]]
38
+ end
39
+ current_subtree[patching_path.last] = patched_content
40
+ File.write(full_path, JSON.pretty_generate(content))
41
+ end
42
+
43
+ def to_s
44
+ "Patch JSON [#{file_path}] at #{patching_path}"
45
+ end
46
+
47
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'parser'
2
+ require_relative 'parsing_context'
3
+ require_relative 'tyrano_exception'
4
+ require_relative 'tyrano_dsl'
5
+ require_relative 'writer'
6
+
7
+ class TyranoDsl::Main
8
+
9
+ # @param [String] file_path path to the DSL file
10
+ # @return [TyranoDsl::WritingContext]
11
+ def run(file_path)
12
+ parsing_context = TyranoDsl::ParsingContext.new
13
+ parser = TyranoDsl::Parser.new(parsing_context, file_path)
14
+ parser.include_file(file_path)
15
+ TyranoDsl::Writer.new.write(parsing_context.world, parsing_context.words)
16
+ end
17
+
18
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'tyrano_dsl'
2
+
3
+ # A parsed word
4
+ class TyranoDsl::ParsedWord
5
+
6
+ # @return [Hash]
7
+ attr_reader :parameters
8
+ # @return [String]
9
+ attr_reader :word
10
+ # @return [Array<String>]
11
+ attr_reader :word_location
12
+
13
+ # @param [String] word
14
+ # @param [Array<String>] word_location
15
+ # @param [Hash] parameters
16
+ def initialize(word, word_location, parameters)
17
+ @word = word
18
+ @word_location = word_location
19
+ @parameters = parameters
20
+ end
21
+
22
+ end
@@ -0,0 +1,58 @@
1
+ require 'logger'
2
+
3
+ require_relative 'parsed_word'
4
+ require_relative 'tyrano_exception'
5
+ require_relative 'tyrano_dsl'
6
+ require_relative 'vocabulary'
7
+
8
+ # Parse the DSL
9
+ class TyranoDsl::Parser
10
+
11
+ # @return [TyranoDsl::ParsingContext]
12
+ attr_reader :context
13
+ # @return [Array<String>]
14
+ attr_accessor :word_location
15
+ # @return [Array<String>]
16
+ attr_reader :included_files_hierarchy
17
+
18
+ TyranoDsl::Vocabulary.get_words_class('parsing_words') do |word, word_module|
19
+ include word_module
20
+
21
+ # Patch the method to store the location when a word is called
22
+ symbol_word = word.to_sym
23
+ old_method = instance_method(symbol_word)
24
+ define_method(symbol_word) do |*args|
25
+ self.word_location = caller
26
+ old_method.bind(self).call(*args)
27
+ end
28
+ end
29
+
30
+ # @param [TyranoDsl::ParsingContext] parsing_context
31
+ # @param [String] initial_file_path
32
+ def initialize(parsing_context, initial_file_path)
33
+ @context = parsing_context
34
+ @logger = Logger.new(STDOUT)
35
+ @included_files_hierarchy = [initial_file_path]
36
+ end
37
+
38
+ protected
39
+
40
+ # Add a parsed word
41
+ # @param [String] word
42
+ # @param [Hash{String => Object}] parameters
43
+ # @return [void]
44
+ def add_parsed_word(word, parameters = {})
45
+ context.words << TyranoDsl::ParsedWord.new(
46
+ word,
47
+ word_location,
48
+ parameters
49
+ )
50
+ end
51
+
52
+ private
53
+
54
+ def log
55
+ @logger.info(self.class) {yield}
56
+ end
57
+
58
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'elements/world'
2
+ require_relative 'parsed_word'
3
+ require_relative 'tyrano_dsl'
4
+
5
+ # Context for parsing, used by words to store content
6
+ class TyranoDsl::ParsingContext
7
+
8
+ # @return [Array<TyranoDsl::ParsedWord>]
9
+ attr_reader :words
10
+ # @return [TyranoDsl::Elements::World]
11
+ attr_reader :world
12
+
13
+ def initialize
14
+ @words = []
15
+ @world = TyranoDsl::Elements::World.new
16
+ end
17
+
18
+ end
@@ -0,0 +1,32 @@
1
+ require_relative '../vocabulary'
2
+ require_relative 'parsing_words_module'
3
+ module TyranoDsl::ParsingWords::AskQuestion
4
+
5
+ include TyranoDsl::ParsingWords::ParsingWordsModule
6
+
7
+ # @return [void]
8
+ # @raise [TyranoDsl::TyranoException]
9
+ # @param [Hash{String=>Hash\nil}] possible_answers
10
+ def ask_question(possible_answers)
11
+ symbolized_possible_answers = possible_answers.collect do |possible_answer|
12
+ unless possible_answer.is_a? Hash
13
+ raise TyranoDsl::TyranoException, 'Parameter is not a Hash'
14
+ end
15
+ symbolized_possible_answer = symbolize_keys(possible_answer)
16
+ [:text, :left, :top, :scene].each do |param_name|
17
+ unless symbolized_possible_answer.key? param_name
18
+ raise TyranoDsl::TyranoException, "Missing value for #{param_name}"
19
+ end
20
+ end
21
+ scene = symbolized_possible_answer[:scene]
22
+ label = symbolized_possible_answer[:label]
23
+ context.world.jump_targets << TyranoDsl::Elements::JumpTarget.new(scene, label ? context.world.label_value(label) : nil)
24
+ symbolized_possible_answer
25
+ end
26
+ add_parsed_word(
27
+ TyranoDsl::Vocabulary::ASK_QUESTION,
28
+ possible_answers: symbolized_possible_answers
29
+ )
30
+ end
31
+
32
+ end