psychgus 1.0.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.
data/Rakefile ADDED
@@ -0,0 +1,158 @@
1
+ # encoding: UTF-8
2
+
3
+ #--
4
+ # This file is part of Psychgus.
5
+ # Copyright (c) 2019 Jonathan Bradley Whited (@esotericpig)
6
+ #
7
+ # Psychgus is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # Psychgus is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with Psychgus. If not, see <http://www.gnu.org/licenses/>.
19
+ #++
20
+
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'yard'
25
+
26
+ require 'psychgus/version'
27
+
28
+ require 'rake/clean'
29
+ require 'rake/testtask'
30
+
31
+ task default: [:test]
32
+
33
+ CLEAN.exclude('.git/','stock/')
34
+ CLOBBER.include('doc/')
35
+
36
+ module PsychgusRake
37
+ # Remove if exists
38
+ def self.rm_exist(filename,output=true)
39
+ if File.exist?(filename)
40
+ puts "Delete [#{filename}]" if output
41
+ File.delete(filename)
42
+ end
43
+ end
44
+ end
45
+
46
+ # Execute "rake ghp_doc" for a dry run
47
+ # Execute "rake ghp_doc[true]" for actually deploying
48
+ desc %q(Rsync "doc/" to my GitHub Page's repo; not useful for others)
49
+ task :ghp_doc,[:deploy] do |task,args|
50
+ dry_run = args.deploy ? '' : '--dry-run'
51
+ rsync_cmd = "rsync -ahv --delete-after --progress #{dry_run} 'doc/' '../esotericpig.github.io/docs/psychgus/yardoc/'"
52
+
53
+ sh rsync_cmd
54
+
55
+ if dry_run
56
+ puts
57
+ puts 'Execute "rake ghp_doc[true]" for actually deploying (non-dry-run)'
58
+ end
59
+ end
60
+
61
+ Rake::TestTask.new() do |task|
62
+ task.libs = ['lib','test']
63
+ task.pattern = 'test/**/*_test.rb'
64
+ task.description += " ('#{task.pattern}')"
65
+ #task.options = '--verbose' # Execute "rake test TESTOPT=-v" instead
66
+ task.verbose = true
67
+ task.warning = true
68
+ end
69
+
70
+ desc 'Run all tests (including writing to temp files, etc.)'
71
+ task :test_all do |task|
72
+ ENV['PSYCHGUS_TEST'] = 'all'
73
+
74
+ test_task = Rake::Task[:test]
75
+ test_task.reenable()
76
+ test_task.invoke()
77
+ end
78
+
79
+ # Execute "rake clobber yard" for pristine docs
80
+ YARD::Rake::YardocTask.new() do |task|
81
+ task.files = ['lib/**/*.rb']
82
+
83
+ task.options += ['--files','LICENSE.txt']
84
+ task.options += ['--readme','README.md']
85
+
86
+ task.options << '--protected' # Show protected methods
87
+ task.options += ['--template-path','yard/templates/']
88
+ task.options += ['--title',"Psychgus v#{Psychgus::VERSION} Doc"]
89
+ end
90
+
91
+ desc 'Fix (find & replace) text in the YARD files for GitHub differences'
92
+ task :yard_fix,[:dev] do |task,args|
93
+ # Delete this file as it's never used (index.html is an exact copy)
94
+ PsychgusRake.rm_exist('doc/file.README.html')
95
+
96
+ ['doc/index.html'].each do |filename|
97
+ puts "File [#{filename}]:"
98
+
99
+ lines = []
100
+ write = false
101
+
102
+ File.open(filename,'r') do |file|
103
+ file.each_line do |line|
104
+ out = false
105
+
106
+ # CSS
107
+ if line =~ /^\s*\<\/head\>\s*$/i
108
+ line = '<link href="'
109
+ line << (args.dev ? '../../esotericpig.github.io/' : '../../../')
110
+ line << 'css/prism.css" rel="stylesheet" /> </head>'
111
+
112
+ out = true
113
+ end
114
+
115
+ # JS
116
+ if line =~ /^\s*\<\/body\>\s*$/i
117
+ line = '<script src="'
118
+ line << (args.dev ? '../../esotericpig.github.io/' : '../../../')
119
+ line << 'js/prism.js"></script> </body>'
120
+
121
+ out = true
122
+ end
123
+
124
+ # Contents relative links
125
+ tag = 'href="#'
126
+ if !(i = line.index(Regexp.new(Regexp.quote(tag) + '[a-z]'))).nil?()
127
+ i += tag.length
128
+ j = line.index('"',i)
129
+
130
+ href = line[i...j].split('-').map(&:capitalize).join('_')
131
+ line = "#{line[0...i]}#{href}#{line[j..-1]}"
132
+
133
+ out = true
134
+ end
135
+
136
+ out ||= !line.gsub!('href="LICENSE.txt"','href="file.LICENSE.html"').nil?()
137
+ out ||= !line.gsub!('code class="Ruby"','code class="language-ruby"').nil?()
138
+
139
+ if out
140
+ puts " #{line}"
141
+ write = true
142
+ end
143
+
144
+ lines << line
145
+ end
146
+ end
147
+
148
+ if write
149
+ File.open(filename,'w') do |file|
150
+ file.puts lines
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ desc 'Generate pristine YARDoc'
157
+ task :yard_fresh => [:clobber,:yard,:yard_fix] do |task|
158
+ end
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ #--
5
+ # This file is part of Psychgus.
6
+ # Copyright (c) 2017-2019 Jonathan Bradley Whited (@esotericpig)
7
+ #
8
+ # Psychgus is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Lesser General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # Psychgus is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Lesser General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU Lesser General Public License
19
+ # along with Psychgus. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+
22
+
23
+ module Psychgus
24
+ ###
25
+ # This is the OOP way to style your classes/modules/etc.
26
+ #
27
+ # Even though it's unnecessary to mix in (include) this module, it's recommended because new methods may be
28
+ # added in the future, so this pseudo-guarantees your class won't break in a new version.
29
+ #
30
+ # A complete example:
31
+ # require 'psychgus'
32
+ #
33
+ # class MyClass
34
+ # include Psychgus::Blueberry
35
+ #
36
+ # attr_reader :my_hash
37
+ #
38
+ # def initialize()
39
+ # @my_hash = {:key1=>'val1',:key2=>'val2'}
40
+ # end
41
+ #
42
+ # def psychgus_stylers(sniffer)
43
+ # return MyClassStyler.new(sniffer)
44
+ # end
45
+ # end
46
+ #
47
+ # class MyClassStyler
48
+ # include Psychgus::Styler
49
+ #
50
+ # def initialize(sniffer)
51
+ # @level = sniffer.level
52
+ # end
53
+ #
54
+ # def style_mapping(sniffer,node)
55
+ # node.style = Psychgus::MAPPING_FLOW
56
+ #
57
+ # relative_level = sniffer.level - @level
58
+ # end
59
+ # end
60
+ #
61
+ # my_class = MyClass.new()
62
+ # puts my_class.to_yaml()
63
+ #
64
+ # Alternatively, MyClass could have been the {Blueberry} and the {Styler}, without the need for
65
+ # MyClassStyler:
66
+ # class MyClass
67
+ # include Psychgus::Blueberry
68
+ # include Psychgus::Styler
69
+ #
70
+ # # ...
71
+ #
72
+ # def psychgus_stylers(sniffer)
73
+ # @level = sniffer.level # This will be included in the output of to_yaml()
74
+ #
75
+ # return self
76
+ # end
77
+ #
78
+ # def style_mapping(sniffer,node)
79
+ # # ...
80
+ # end
81
+ # end
82
+ #
83
+ # However, it's best to put the styling logic inside of a separate class (or inner class) away from the main
84
+ # logic. This also prevents extra helper vars, like @level, from showing up in the output.
85
+ #
86
+ # After your class and its children have been processed, the styler(s) will be removed from the logic for
87
+ # the next sibling object(s). Therefore, you can safely do class-specific checks on level, etc. without it
88
+ # affecting the sibling object(s). See {Ext::YAMLTreeExt} and {Ext::YAMLTreeExt#accept} for details.
89
+ #
90
+ # "The Blueberry" is the name of Gus's car from the TV show Psych.
91
+ #
92
+ # @author Jonathan Bradley Whited (@esotericpig)
93
+ # @since 1.0.0
94
+ #
95
+ # @see Ext::YAMLTreeExt
96
+ # @see Ext::YAMLTreeExt#accept
97
+ ###
98
+ module Blueberry
99
+ # Duck Type this method to return the {Styler}(s) for your class/module/etc.
100
+ #
101
+ # @param sniffer [SuperSniffer] passed in from {StyledTreeBuilder}; use this for storing the level,
102
+ # position, etc. for styling your instance variables later relative to your
103
+ # class/module/etc.
104
+ #
105
+ # @return [Styler,Array<Styler>,nil] {Styler}(s) for this class/module/etc.
106
+ def psychgus_stylers(sniffer)
107
+ return nil
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ #--
5
+ # This file is part of Psychgus.
6
+ # Copyright (c) 2019 Jonathan Bradley Whited (@esotericpig)
7
+ #
8
+ # Psychgus is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Lesser General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # Psychgus is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Lesser General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU Lesser General Public License
19
+ # along with Psychgus. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+
22
+
23
+ module Psychgus
24
+ module Ext
25
+ ###
26
+ # Core extensions to Object.
27
+ #
28
+ # @author Jonathan Bradley Whited (@esotericpig)
29
+ # @since 1.0.0
30
+ #
31
+ # @see https://github.com/ruby/psych/blob/master/lib/psych/core_ext.rb
32
+ ###
33
+ module ObjectExt
34
+ # Convert an Object to YAML.
35
+ #
36
+ # +options+ can also be a Hash, so can be a drop-in-replacement for Psych.
37
+ #
38
+ # @example
39
+ # class MyStyler
40
+ # include Psychgus::Styler
41
+ #
42
+ # def style_sequence(sniffer,node)
43
+ # node.style = Psychgus::SEQUENCE_FLOW
44
+ # end
45
+ # end
46
+ #
47
+ # my_obj = {
48
+ # :Foods => {
49
+ # :Fruits => %w(Apple Banana Blueberry Pear),
50
+ # :Veggies => %w(Bean Carrot Celery Pea)
51
+ # }}
52
+ #
53
+ # puts my_obj.to_yaml(indentation: 5,stylers: MyStyler.new)
54
+ #
55
+ # # Or, pass in a Hash:
56
+ # #puts my_obj.to_yaml({:indentation=>5,:stylers=>MyStyler.new})
57
+ #
58
+ # # Output:
59
+ # # ---
60
+ # # :Foods:
61
+ # # :Fruits: [Apple, Banana, Blueberry, Pear]
62
+ # # :Veggies: [Bean, Carrot, Celery, Pea]
63
+ #
64
+ # @param options [Hash] the options (or keyword args) to pass to {Psychgus.dump}
65
+ #
66
+ # @return [String] the YAML generated from this Object
67
+ #
68
+ # @see Psychgus.dump
69
+ def to_yaml(**options)
70
+ # Do not use Psych.dump() if no Stylers, because a class might be a Blueberry
71
+ return Psychgus.dump(self,**options)
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ Object.prepend(Psychgus::Ext::ObjectExt)
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ #--
5
+ # This file is part of Psychgus.
6
+ # Copyright (c) 2019 Jonathan Bradley Whited (@esotericpig)
7
+ #
8
+ # Psychgus is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Lesser General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # Psychgus is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Lesser General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU Lesser General Public License
19
+ # along with Psychgus. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+
22
+
23
+ require 'psych'
24
+
25
+ module Psychgus
26
+ module Ext
27
+ ###
28
+ # Extensions to Psych::Nodes::Node.
29
+ #
30
+ # @author Jonathan Bradley Whited (@esotericpig)
31
+ # @since 1.0.0
32
+ ###
33
+ module NodeExt
34
+ # Check if this Node is of a certain type (Alias, Mapping, Scalar, Sequence, etc.).
35
+ #
36
+ # New versions of Psych have alias?(), mapping?(), etc., so this is for old versions.
37
+ #
38
+ # This is equivalent to the following (with less typing):
39
+ # node.is_a?(Psych::Nodes::Alias)
40
+ # node.is_a?(Psych::Nodes::Mapping)
41
+ # node.is_a?(Psych::Nodes::Scalar)
42
+ # node.is_a?(Psych::Nodes::Sequence)
43
+ #
44
+ # @example
45
+ # node.node_of?(:alias)
46
+ # node.node_of?(:mapping)
47
+ # node.node_of?(:scalar)
48
+ # node.node_of?(:sequence)
49
+ # node.node_of?(:alias,:mapping,:scalar,:sequence) # OR
50
+ # node.node_of?(:doc,:map,:seq) # OR
51
+ #
52
+ # @param names [Symbol,String] the type(s) to check using OR
53
+ #
54
+ # @return [true,false] true if this Node is one of the +names+ type, else false
55
+ #
56
+ # @see Psychgus.node_class
57
+ def node_of?(*names)
58
+ names.each do |name|
59
+ return true if is_a?(Psychgus.node_class(name))
60
+ end
61
+
62
+ return false
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ Psych::Nodes::Node.prepend(Psychgus::Ext::NodeExt)
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ #--
5
+ # This file is part of Psychgus.
6
+ # Copyright (c) 2019 Jonathan Bradley Whited (@esotericpig)
7
+ #
8
+ # Psychgus is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Lesser General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # Psychgus is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Lesser General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU Lesser General Public License
19
+ # along with Psychgus. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+
22
+
23
+ require 'psych'
24
+
25
+ require 'psychgus/styled_tree_builder'
26
+
27
+ module Psychgus
28
+ module Ext
29
+ ###
30
+ # Extensions to Psych::Visitors::YAMLTree::Registrar.
31
+ #
32
+ # @author Jonathan Bradley Whited (@esotericpig)
33
+ # @since 1.0.0
34
+ ###
35
+ module RegistrarExt
36
+ # Remove +target+ from this Registrar to prevent it becoming an alias.
37
+ #
38
+ # @param target [Object] the Object to remove from this Registrar
39
+ def remove_alias(target)
40
+ @obj_to_node.delete(target.object_id)
41
+ end
42
+ end
43
+
44
+ ###
45
+ # Extensions to Psych::Visitors::YAMLTree.
46
+ #
47
+ # @author Jonathan Bradley Whited (@esotericpig)
48
+ # @since 1.0.0
49
+ ###
50
+ module YAMLTreeExt
51
+ # Accepts a new Object to convert to YAML.
52
+ #
53
+ # This is roughly the same place where Psych checks if +target+ responds to :encode_with.
54
+ #
55
+ # This will check if @emitter is a {StyledTreeBuilder} and if +target+ is a {Blueberry}.
56
+ # 1. If the above is true, get the {Styler}(s) and add them to @emitter.
57
+ # 2. Call super.
58
+ # 3. If the above is true, remove the {Styler}(s) from @emitter.
59
+ # 4. Return the result of super.
60
+ #
61
+ # @param target [Object] the Object to pass to super
62
+ #
63
+ # @return the result of super
64
+ #
65
+ # @see Psych::Visitors::YAMLTree
66
+ # @see Blueberry
67
+ # @see Styler
68
+ # @see StyledTreeBuilder
69
+ def accept(target)
70
+ styler_count = 0
71
+
72
+ if @emitter.is_a?(StyledTreeBuilder)
73
+ # Blueberry?
74
+ if target.respond_to?(:psychgus_stylers)
75
+ stylers = target.psychgus_stylers(@emitter.sniffer)
76
+ stylers_old_len = @emitter.stylers.length
77
+
78
+ @emitter.add_styler(*stylers)
79
+
80
+ styler_count = @emitter.stylers.length - stylers_old_len
81
+ end
82
+
83
+ # Dereference aliases?
84
+ if @emitter.deref_aliases?()
85
+ @st.remove_alias(target) if target.respond_to?(:object_id) && @st.key?(target)
86
+ end
87
+ end
88
+
89
+ result = super(target)
90
+
91
+ # Check styler_count because @emitter may not be a StyledTreeBuilder and target may not be a Blueberry
92
+ @emitter.pop_styler(styler_count) if styler_count > 0
93
+
94
+ return result
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ Psych::Visitors::YAMLTree.prepend(Psychgus::Ext::YAMLTreeExt)
101
+ Psych::Visitors::YAMLTree::Registrar.prepend(Psychgus::Ext::RegistrarExt)
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ #--
5
+ # This file is part of Psychgus.
6
+ # Copyright (c) 2019 Jonathan Bradley Whited (@esotericpig)
7
+ #
8
+ # Psychgus is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Lesser General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # Psychgus is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Lesser General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU Lesser General Public License
19
+ # along with Psychgus. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+
22
+
23
+ module Psychgus
24
+ ###
25
+ # Contains all of the extensions (monkey patching) to core/Psych classes/modules.
26
+ #
27
+ # @author Jonathan Bradley Whited (@esotericpig)
28
+ # @since 1.0.0
29
+ ###
30
+ module Ext
31
+ end
32
+ end
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ #--
5
+ # This file is part of Psychgus.
6
+ # Copyright (c) 2019 Jonathan Bradley Whited (@esotericpig)
7
+ #
8
+ # Psychgus is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU Lesser General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # Psychgus is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU Lesser General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU Lesser General Public License
19
+ # along with Psychgus. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+
22
+
23
+ require 'psych'
24
+
25
+ require 'psychgus/styled_tree_builder'
26
+
27
+ module Psychgus
28
+ ###
29
+ # Use this wherever Psych::Handlers::DocumentStream would have been used, to enable styling.
30
+ #
31
+ # @author Jonathan Bradley Whited (@esotericpig)
32
+ # @since 1.0.0
33
+ #
34
+ # @see Psychgus.parse_stream Psychgus.parse_stream
35
+ # @see Psych::Handlers::DocumentStream
36
+ ###
37
+ class StyledDocumentStream < StyledTreeBuilder
38
+ # Initialize this class with {Styler}(s) and a block.
39
+ #
40
+ # @param stylers [Styler] {Styler}(s) to use for styling this DocumentStream
41
+ # @param deref_aliases [true,false] whether to dereference aliases; output the actual value
42
+ # instead of the alias
43
+ # @param block [Proc] a block to call in {#end_document} to denote a new YAML document
44
+ def initialize(*stylers,deref_aliases: false,**options,&block)
45
+ super(*stylers,deref_aliases: deref_aliases,**options)
46
+
47
+ @block = block
48
+ end
49
+
50
+ # This mimics the behavior of Psych::Handlers::DocumentStream#end_document.
51
+ #
52
+ # @see Psych::Handlers::DocumentStream#end_document
53
+ def end_document(implicit_end=!streaming?())
54
+ @last.implicit_end = implicit_end
55
+ @block.call(pop)
56
+ end
57
+
58
+ # This mimics the behavior of Psych::Handlers::DocumentStream#start_document.
59
+ #
60
+ # @see Psych::Handlers::DocumentStream#start_document
61
+ def start_document(version,tag_directives,implicit)
62
+ node = Psych::Nodes::Document.new(version,tag_directives,implicit)
63
+ push(node)
64
+ end
65
+ end
66
+ end