glyph 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 (68) hide show
  1. data/README.textile +80 -0
  2. data/Rakefile +51 -0
  3. data/VERSION +1 -0
  4. data/bin/glyph +7 -0
  5. data/book/config.yml +5 -0
  6. data/book/document.glyph +55 -0
  7. data/book/images/glyph.png +0 -0
  8. data/book/images/glyph.svg +351 -0
  9. data/book/lib/macros/reference.rb +98 -0
  10. data/book/output/html/glyph.html +1809 -0
  11. data/book/output/html/images/glyph.png +0 -0
  12. data/book/output/html/images/glyph.svg +351 -0
  13. data/book/output/pdf/glyph.pdf +4277 -0
  14. data/book/snippets.yml +13 -0
  15. data/book/styles/css3.css +220 -0
  16. data/book/styles/default.css +190 -0
  17. data/book/text/authoring.textile +351 -0
  18. data/book/text/extending.textile +148 -0
  19. data/book/text/getting_started.textile +152 -0
  20. data/book/text/introduction.textile +88 -0
  21. data/book/text/ref_commands.textile +74 -0
  22. data/book/text/ref_config.textile +0 -0
  23. data/book/text/ref_macros.textile +256 -0
  24. data/book/text/troubleshooting.textile +118 -0
  25. data/config.yml +63 -0
  26. data/document.glyph +29 -0
  27. data/glyph.gemspec +138 -0
  28. data/lib/glyph.rb +128 -0
  29. data/lib/glyph/commands.rb +124 -0
  30. data/lib/glyph/config.rb +152 -0
  31. data/lib/glyph/document.rb +145 -0
  32. data/lib/glyph/glyph_language.rb +530 -0
  33. data/lib/glyph/glyph_language.treetop +27 -0
  34. data/lib/glyph/interpreter.rb +84 -0
  35. data/lib/glyph/macro.rb +69 -0
  36. data/lib/glyph/node.rb +126 -0
  37. data/lib/glyph/system_extensions.rb +77 -0
  38. data/macros/common.rb +66 -0
  39. data/macros/filters.rb +69 -0
  40. data/macros/html/block.rb +119 -0
  41. data/macros/html/inline.rb +43 -0
  42. data/macros/html/structure.rb +138 -0
  43. data/spec/files/container.textile +5 -0
  44. data/spec/files/document.glyph +2 -0
  45. data/spec/files/document_with_toc.glyph +3 -0
  46. data/spec/files/included.textile +4 -0
  47. data/spec/files/ligature.jpg +449 -0
  48. data/spec/files/markdown.markdown +8 -0
  49. data/spec/files/test.sass +2 -0
  50. data/spec/lib/commands_spec.rb +83 -0
  51. data/spec/lib/config_spec.rb +79 -0
  52. data/spec/lib/document_spec.rb +100 -0
  53. data/spec/lib/glyph_spec.rb +76 -0
  54. data/spec/lib/interpreter_spec.rb +90 -0
  55. data/spec/lib/macro_spec.rb +60 -0
  56. data/spec/lib/node_spec.rb +76 -0
  57. data/spec/macros/filters_spec.rb +42 -0
  58. data/spec/macros/macros_spec.rb +159 -0
  59. data/spec/spec_helper.rb +92 -0
  60. data/spec/tasks/generate_spec.rb +31 -0
  61. data/spec/tasks/load_spec.rb +37 -0
  62. data/spec/tasks/project_spec.rb +41 -0
  63. data/styles/css3.css +220 -0
  64. data/styles/default.css +190 -0
  65. data/tasks/generate.rake +57 -0
  66. data/tasks/load.rake +55 -0
  67. data/tasks/project.rake +33 -0
  68. metadata +192 -0
data/glyph.gemspec ADDED
@@ -0,0 +1,138 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{glyph}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Fabio Cevasco"]
12
+ s.date = %q{2010-04-09}
13
+ s.default_executable = %q{glyph}
14
+ s.description = %q{Glyph is a framework for structured document authoring.}
15
+ s.email = %q{h3rald@h3rald.com}
16
+ s.executables = ["glyph"]
17
+ s.extra_rdoc_files = [
18
+ "README.textile"
19
+ ]
20
+ s.files = [
21
+ "README.textile",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "bin/glyph",
25
+ "book/config.yml",
26
+ "book/document.glyph",
27
+ "book/images/glyph.png",
28
+ "book/images/glyph.svg",
29
+ "book/lib/macros/reference.rb",
30
+ "book/output/html/glyph.html",
31
+ "book/output/html/images/glyph.png",
32
+ "book/output/html/images/glyph.svg",
33
+ "book/output/pdf/glyph.pdf",
34
+ "book/snippets.yml",
35
+ "book/styles/css3.css",
36
+ "book/styles/default.css",
37
+ "book/text/authoring.textile",
38
+ "book/text/extending.textile",
39
+ "book/text/getting_started.textile",
40
+ "book/text/introduction.textile",
41
+ "book/text/ref_commands.textile",
42
+ "book/text/ref_config.textile",
43
+ "book/text/ref_macros.textile",
44
+ "book/text/troubleshooting.textile",
45
+ "config.yml",
46
+ "document.glyph",
47
+ "glyph.gemspec",
48
+ "lib/glyph.rb",
49
+ "lib/glyph/commands.rb",
50
+ "lib/glyph/config.rb",
51
+ "lib/glyph/document.rb",
52
+ "lib/glyph/glyph_language.rb",
53
+ "lib/glyph/glyph_language.treetop",
54
+ "lib/glyph/interpreter.rb",
55
+ "lib/glyph/macro.rb",
56
+ "lib/glyph/node.rb",
57
+ "lib/glyph/system_extensions.rb",
58
+ "macros/common.rb",
59
+ "macros/filters.rb",
60
+ "macros/html/block.rb",
61
+ "macros/html/inline.rb",
62
+ "macros/html/structure.rb",
63
+ "spec/files/container.textile",
64
+ "spec/files/document.glyph",
65
+ "spec/files/document_with_toc.glyph",
66
+ "spec/files/included.textile",
67
+ "spec/files/ligature.jpg",
68
+ "spec/files/markdown.markdown",
69
+ "spec/files/test.sass",
70
+ "spec/lib/commands_spec.rb",
71
+ "spec/lib/config_spec.rb",
72
+ "spec/lib/document_spec.rb",
73
+ "spec/lib/glyph_spec.rb",
74
+ "spec/lib/interpreter_spec.rb",
75
+ "spec/lib/macro_spec.rb",
76
+ "spec/lib/node_spec.rb",
77
+ "spec/macros/filters_spec.rb",
78
+ "spec/macros/macros_spec.rb",
79
+ "spec/spec_helper.rb",
80
+ "spec/tasks/generate_spec.rb",
81
+ "spec/tasks/load_spec.rb",
82
+ "spec/tasks/project_spec.rb",
83
+ "styles/css3.css",
84
+ "styles/default.css",
85
+ "tasks/generate.rake",
86
+ "tasks/load.rake",
87
+ "tasks/project.rake"
88
+ ]
89
+ s.homepage = %q{http://www.h3rald.com/glyph/}
90
+ s.rdoc_options = ["--charset=UTF-8"]
91
+ s.require_paths = ["lib"]
92
+ s.rubygems_version = %q{1.3.5}
93
+ s.summary = %q{Glyph -- A Ruby-powered Document Authoring Framework}
94
+ s.test_files = [
95
+ "spec/macros/filters_spec.rb",
96
+ "spec/macros/macros_spec.rb",
97
+ "spec/lib/interpreter_spec.rb",
98
+ "spec/lib/commands_spec.rb",
99
+ "spec/lib/node_spec.rb",
100
+ "spec/lib/macro_spec.rb",
101
+ "spec/lib/config_spec.rb",
102
+ "spec/lib/glyph_spec.rb",
103
+ "spec/lib/document_spec.rb",
104
+ "spec/tasks/load_spec.rb",
105
+ "spec/tasks/generate_spec.rb",
106
+ "spec/tasks/project_spec.rb",
107
+ "spec/spec_helper.rb"
108
+ ]
109
+
110
+ if s.respond_to? :specification_version then
111
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
112
+ s.specification_version = 3
113
+
114
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
115
+ s.add_runtime_dependency(%q<gli>, [">= 0.3.1"])
116
+ s.add_runtime_dependency(%q<extlib>, [">= 0.9.12"])
117
+ s.add_runtime_dependency(%q<treetop>, [">= 0.4.3"])
118
+ s.add_runtime_dependency(%q<rake>, [">= 0.8.7"])
119
+ s.add_development_dependency(%q<rspec>, [">= 0"])
120
+ s.add_development_dependency(%q<yard>, [">= 0"])
121
+ else
122
+ s.add_dependency(%q<gli>, [">= 0.3.1"])
123
+ s.add_dependency(%q<extlib>, [">= 0.9.12"])
124
+ s.add_dependency(%q<treetop>, [">= 0.4.3"])
125
+ s.add_dependency(%q<rake>, [">= 0.8.7"])
126
+ s.add_dependency(%q<rspec>, [">= 0"])
127
+ s.add_dependency(%q<yard>, [">= 0"])
128
+ end
129
+ else
130
+ s.add_dependency(%q<gli>, [">= 0.3.1"])
131
+ s.add_dependency(%q<extlib>, [">= 0.9.12"])
132
+ s.add_dependency(%q<treetop>, [">= 0.4.3"])
133
+ s.add_dependency(%q<rake>, [">= 0.8.7"])
134
+ s.add_dependency(%q<rspec>, [">= 0"])
135
+ s.add_dependency(%q<yard>, [">= 0"])
136
+ end
137
+ end
138
+
data/lib/glyph.rb ADDED
@@ -0,0 +1,128 @@
1
+ # Copyright (c) 2009-2010 Fabio Cevasco
2
+ # website: http://www.h3rald.com/glyph
3
+ # license: BSD
4
+
5
+ require 'rubygems'
6
+ require 'pathname'
7
+ require 'yaml'
8
+ require 'gli'
9
+ require 'extlib'
10
+ require 'treetop'
11
+ require 'rake'
12
+
13
+ # Glyph is a Rapid Document Authoring Framework able to produce structured documents effortlessly.
14
+ module Glyph
15
+
16
+ LIB = Pathname(__FILE__).dirname.expand_path/'glyph'
17
+
18
+ HOME = LIB/'../../'
19
+
20
+ require LIB/'system_extensions'
21
+ require LIB/'config'
22
+ require LIB/'node'
23
+ require LIB/'document'
24
+ require LIB/'glyph_language'
25
+ require LIB/'macro'
26
+ require LIB/'interpreter'
27
+
28
+ VERSION = file_load HOME/'VERSION'
29
+
30
+ SPEC_DIR = Pathname(__FILE__).dirname.expand_path/'../spec'
31
+
32
+ TASKS_DIR = Pathname(__FILE__).dirname.expand_path/'../tasks'
33
+
34
+ APP = Rake.application
35
+
36
+ SNIPPETS = {}
37
+
38
+ MACROS = {}
39
+
40
+ TODOS = []
41
+
42
+ ERRORS = []
43
+
44
+ # Returns true if Glyph is running in test mode
45
+ def self.testing?
46
+ const_defined? :TEST_MODE rescue false
47
+ end
48
+
49
+ PROJECT = (Glyph.testing?) ? Glyph::SPEC_DIR/"test_project" : Pathname.new(Dir.pwd)
50
+
51
+ CONFIG = Glyph::Config.new :resettable => true, :mutable => false
52
+
53
+ home_dir = Pathname.new(RUBY_PLATFORM.match(/win32|mingw/) ? ENV['HOMEPATH'] : ENV['HOME'])
54
+ SYSTEM_CONFIG = Glyph::Config.new(:file => HOME/'config.yml')
55
+ GLOBAL_CONFIG = Glyph.testing? ? Glyph::Config.new(:file => SPEC_DIR/'.glyphrc') : Glyph::Config.new(:file => home_dir/'.glyphrc')
56
+ PROJECT_CONFIG = Glyph::Config.new(:file => PROJECT/'config.yml')
57
+
58
+ # Loads all Rake tasks
59
+ def self.setup
60
+ FileList["#{TASKS_DIR}/**/*.rake"].each do |f|
61
+ load f
62
+ end
63
+ end
64
+
65
+ # Overrides a configuration setting
66
+ # @param setting [String, Symbol] the configuration setting to change
67
+ # @param value the new value
68
+ def self.config_override(setting, value)
69
+ PROJECT_CONFIG.set setting, value
70
+ reset_config
71
+ end
72
+
73
+ # Resets Glyph configuration
74
+ def self.reset_config
75
+ CONFIG.merge!(SYSTEM_CONFIG.merge(GLOBAL_CONFIG.merge(PROJECT_CONFIG)))
76
+ end
77
+
78
+ # Returns true if the PROJECT constant is set to a valid Glyph project directory
79
+ def self.project?
80
+ children = ["styles", "text", "output", "snippets.yml", "config.yml", "document.glyph"].sort
81
+ actual_children = PROJECT.children.map{|c| c.basename.to_s}.sort
82
+ (actual_children & children) == children
83
+ end
84
+
85
+ # Enables a Rake task
86
+ # @param task the task to enable
87
+ def self.enable(task)
88
+ Rake::Task[task].reenable
89
+ end
90
+
91
+ # Reenables and runs a Rake task
92
+ # @param task the task to enable
93
+ # @param *args the task arguments
94
+ def self.run!(task, *args)
95
+ Rake::Task[task].reenable
96
+ self.run task, *args
97
+ end
98
+
99
+ # Runs a Rake task
100
+ # @param task the task to enable
101
+ # @param *args the task arguments
102
+ def self.run(task, *args)
103
+ Rake::Task[task].invoke *args
104
+ end
105
+
106
+ # Defines a new macro
107
+ # @param name [Symbol, String] the name of the macro
108
+ def self.macro(name, &block)
109
+ MACROS[name] = block
110
+ end
111
+
112
+ # Defines an alias for an existing macro
113
+ # @param [Hash] pair the single-key hash defining the alias
114
+ # @example
115
+ # {:old_name => :new_name}
116
+ def self.macro_alias(pair)
117
+ name = pair.keys[0].to_sym
118
+ found = MACROS[name]
119
+ if found then
120
+ warning "Invalid alias: macro '#{name}' already exists."
121
+ return
122
+ end
123
+ MACROS[name] = MACROS[pair.values[0].to_sym]
124
+ end
125
+
126
+ end
127
+
128
+ Glyph.setup
@@ -0,0 +1,124 @@
1
+ include GLI
2
+
3
+
4
+ GLI.desc "Enable debugging"
5
+ switch [:d, :debug]
6
+
7
+ GLI.desc 'Create a new Glyph project'
8
+ command :init do |c|
9
+ c.action do |global_options,options,args|
10
+ Glyph.run 'project:create', Dir.pwd
11
+ end
12
+ end
13
+
14
+ GLI.desc 'Add a new text file to the project'
15
+ arg_name "file_name"
16
+ command :add do |c|
17
+ c.action do |global_options,options,args|
18
+ raise ArgumentError, "Please specify a file name." if args.blank?
19
+ Glyph.run 'project:add', args[0]
20
+ end
21
+ end
22
+
23
+ GLI.desc 'Compile the project'
24
+ arg_name "[output_target]"
25
+ command :compile do |c|
26
+ c.desc "Specify a glyph file to compile (default: document.glyph)"
27
+ c.flag [:s, :source]
28
+ c.desc "Specify the format of the output file (default: html)"
29
+ c.flag [:f, :format]
30
+ c.action do |global_options, options, args|
31
+ Glyph.run 'load:config'
32
+ output_targets = Glyph::CONFIG.get('document.output_targets')
33
+ target = nil
34
+ Glyph.config_override('document.output', options[:f]) if options[:f]
35
+ target = cfg('document.output')
36
+ target = nil if target.blank?
37
+ target ||= cfg('filters.target')
38
+ Glyph.config_override('document.source', options[:s]) if options[:s]
39
+ raise ArgumentError, "Output target not specified" unless target
40
+ raise ArgumentError, "Unknown output target '#{target}'" unless output_targets.include? target.to_sym
41
+ Glyph.run "generate:#{target}"
42
+ end
43
+ end
44
+
45
+ GLI.desc 'Display all project TODO items'
46
+ command :todo do |c|
47
+ c.action do |global_options, options, args|
48
+ Glyph.run "generate:document"
49
+ unless Glyph::TODOS.blank?
50
+ info "*** TODOs: ***"
51
+ Glyph::TODOS.each do |t|
52
+ info t
53
+ end
54
+ else
55
+ info "Nothing left to do."
56
+ end
57
+ end
58
+ end
59
+
60
+ GLI.desc 'Get/set configuration settings'
61
+ arg_name "setting [new_value]"
62
+ command :config do |c|
63
+ c.desc "Save to global configuration"
64
+ c.switch [:g, :global]
65
+ c.action do |global_options,options,args|
66
+ Glyph.run 'load:config'
67
+ if options[:g] then
68
+ cfg = Glyph::GLOBAL_CONFIG
69
+ else
70
+ cfg = Glyph::PROJECT_CONFIG
71
+ end
72
+ case args.length
73
+ when 0 then
74
+ raise ArgumentError, "Too few arguments."
75
+ when 1 then # read current config
76
+ setting = cfg(args[0])
77
+ raise RuntimeError, "Unknown setting '#{args[0]}'" if setting.blank?
78
+ info Glyph::CONFIG.get(args[0])
79
+ when 2 then
80
+ cfg.set args[0], args[1]
81
+ Glyph.reset_config
82
+ else
83
+ raise ArgumentError, "Too many arguments."
84
+ end
85
+ end
86
+ end
87
+
88
+ pre do |global,command,options,args|
89
+ # Pre logic here
90
+ # Return true to proceed; false to abourt and not call the
91
+ # chosen command
92
+ if global[:d] then
93
+ Glyph::DEBUG = true
94
+ end
95
+ if !command || command.name == :help then
96
+ puts "====================================="
97
+ puts "Glyph v#{Glyph::VERSION}"
98
+ puts "====================================="
99
+ end
100
+ true
101
+ end
102
+
103
+ post do |global,command,options,args|
104
+ # Post logic here
105
+ end
106
+
107
+ on_error do |exception|
108
+ if exception.is_a? MacroError then
109
+ #warning exception.message
110
+ puts exception.message
111
+ false
112
+ else
113
+ if Glyph.const_defined? :DEBUG then
114
+ puts "Exception: #{exception.message}"
115
+ puts "Backtrace:"
116
+ exception.backtrace.each do |b|
117
+ puts b
118
+ end
119
+ end
120
+ true
121
+ end
122
+ # Error logic here
123
+ # return false to skip default error handling
124
+ end
@@ -0,0 +1,152 @@
1
+ module Glyph
2
+
3
+ # The Glyph::Config class is used (you don't say!) to store configuration data. Essentially it wraps a Hash of Hashes
4
+ # and provides some useful methods to access keys and subkeys.
5
+ class Config
6
+
7
+ # Initializes the configuration with a hash of options:
8
+ # * :file (default: nil) - A YAML file to read data from
9
+ # * :data (default: {})- The initial contents
10
+ # * :resettable (default: false) - Whether the configuration can be reset (cleared) or not
11
+ # * :mutable (default: true) - Whether the configuration can be changed or not
12
+ #
13
+ # @param [Hash] options the configuration options (merged with the the defaults)
14
+ def initialize(options={})
15
+ default_options = {:file => nil, :data => {}, :resettable => false, :mutable => true}
16
+ @options = default_options.merge options
17
+ @file = @options[:file]
18
+ @data = @options[:data]
19
+ read if @file
20
+ end
21
+
22
+ # Returns the underlying data hash
23
+ # @return [Hash] Configuration data
24
+ def to_hash
25
+ @data
26
+ end
27
+
28
+ # Resets all configuration data
29
+ # @param [Hash] hash the new configuration data to store
30
+ # @raise [RuntimeError] unless the configuration is resettable or if no hash is passed
31
+ # @return [Hash] Configuration data
32
+ def reset(hash={})
33
+ raise RuntimeError, "Configuration cannot be reset" unless @options[:resettable]
34
+ raise RuntimeError, "Configuration data is not stored in a Hash" unless hash.is_a? Hash
35
+ @data = hash
36
+ end
37
+
38
+ # Updates configuration data by applying Hash#update to each sub-hash of data, recursively.
39
+ # @param [Glyph::Config] cfg the configuration to update from
40
+ # @raise [ArgumentError] unless cfg is a Glyph::Config
41
+ # @return self
42
+ def update(cfg)
43
+ merge_or_update cfg, :update
44
+ end
45
+
46
+ # Merges configuration data by applying Hash#merge to each sub-hash of data, recursively.
47
+ # @param [Glyph::Config] cfg the configuration to merge with
48
+ # @raise [ArgumentError] unless cfg is a Glyph::Config
49
+ # @return [Glyph::Config] a new merged configuration
50
+ def merge(cfg)
51
+ merge_or_update cfg, :merge
52
+ end
53
+
54
+ alias merge! update
55
+
56
+ # Reads the contents of a file and stores them as configuration data
57
+ # @return [Hash] Configuration data
58
+ # @raise [RuntimeError] if self is not linked to a file or if the file does not contain a serialized Hash
59
+ def read
60
+ raise RuntimeError, "Configuration is not stored in a file." if @file.blank?
61
+ if @file.exist? then
62
+ contents = yaml_load @file
63
+ raise RuntimeError, "Invalid configuration file '#{@file}'" unless contents.is_a? Hash
64
+ @data = contents
65
+ else
66
+ @data = {}
67
+ end
68
+ @data
69
+ end
70
+
71
+ # Updates a configuration setting
72
+ # @param [String, Symbol] setting the setting to update
73
+ # @param [Object] value the value to store. Where applicable (Array, Hash, Boolean, Nil), attempts
74
+ # to evaluate string values
75
+ # @return [Object] the new value
76
+ # @raise [RuntimeError] unless the configuration is mutable
77
+ # @raise [ArgumentError] if the setting refers to an invalid namespace
78
+ # @example
79
+ # cfg = Glyph::Config.new
80
+ # cfg.set "quiet", true # Sets :quiet => true
81
+ # cfg.set "test.test_value", "[1,2,3]" # Sets :test => {:test_value => [1,2,3]}
82
+ # cfg.sef :quiet, "false" # Sets :quiet => false
83
+ def set(setting, value)
84
+ raise RuntimeError, "Configuration cannot be changed" unless @options[:mutable]
85
+ if value.is_a?(String) && value.match(/^(["'].*["']|:.+|\[.*\]|\{.*\}|true|false|nil)$/) then
86
+ value = Kernel.instance_eval value
87
+ end
88
+ hash = @data
89
+ path = setting.to_s.split(".").map{|s| s.intern}
90
+ count = 1
91
+ path.each do |s|
92
+ if hash.has_key? s then
93
+ if count == path.length then
94
+ # destination
95
+ hash[s] = value
96
+ else
97
+ if hash[s].is_a?(Hash) then
98
+ hash = hash[s]
99
+ count +=1
100
+ else
101
+ raise ArgumentError, "Invalid namespace #{s}"
102
+ end
103
+ end
104
+ else
105
+ # key not found
106
+ if count == path.length then # destination
107
+ hash[s] = value
108
+ else
109
+ # create a new namespace
110
+ hash[s] = {}
111
+ hash = hash[s]
112
+ count +=1
113
+ end
114
+ end
115
+ end
116
+ value
117
+ end
118
+
119
+ # Returns a configuration setting
120
+ # @param [String, Symbol] setting the setting to retrieve
121
+ # @return [Object] the new value
122
+ # @see Glyph::Config#set
123
+ # @example
124
+ # cfg = Glyph::Config.new
125
+ # cfg.get :quiet # true
126
+ # cfg.get "test.test_value" # [1,2,3]
127
+ def get(setting)
128
+ @data.instance_eval "self#{setting.to_s.split(".").map{|key| "[:#{key}]" }.join}" rescue nil
129
+ end
130
+
131
+ # Serialize configuration data and writes it to a file
132
+ # @raise [RuntimeError] if the configuration is not linked to a file
133
+ def write
134
+ raise RuntimeError, "Configuration is not stored in a file." if @file.blank?
135
+ yaml_dump @file, @data
136
+ end
137
+
138
+ private
139
+
140
+ def merge_or_update(cfg, method=:merge)
141
+ raise ArgumentError, "#{cfg} is not a Glyph::Config" unless cfg.is_a? Glyph::Config
142
+ block = lambda do |key, v1, v2|
143
+ (v1.is_a?(Hash) && v2.is_a?(Hash)) ? v1.send(method, v2, &block) : v2
144
+ end
145
+ new_data = @data.send(method, cfg.to_hash, &block)
146
+ opts = @options.merge :data => new_data, :file => nil
147
+ (method == :merge) ? Config.new(opts) : self
148
+ end
149
+
150
+ end
151
+
152
+ end