treeline 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.
@@ -0,0 +1 @@
1
+ /pkg/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # gem's dependencies are specified in treeline.gemspec
4
+ gemspec
@@ -0,0 +1,14 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ treeline (0.1.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+
10
+ PLATFORMS
11
+ ruby
12
+
13
+ DEPENDENCIES
14
+ treeline!
@@ -0,0 +1,158 @@
1
+ The Don't Be a Dick License
2
+ ===========================
3
+ _version 0.1_
4
+
5
+ **Project:** [Treeline](http://github.com/CraigCottingham/treeline) v0.1
6
+ **Author:** Craig S. Cottingham (<craig.cottingham@gmail.com>)
7
+
8
+ The purpose of this license is to permit the broadest feasible scope for reuse and modification of creative work,
9
+ restricted only by the requirement that one is not a dick about it.
10
+
11
+ 1. Legal Parameters
12
+ -------------------
13
+ For legal purposes, the DBAD license is a superset of the [Apache License, Version 2.0][1] and incorporates all
14
+ terms, conditions, privileges and limitations therein. The following text is a binding part of this license for
15
+ this project:
16
+
17
+ > Copyright 2011 Craig S. Cottingham
18
+
19
+ > Licensed under the Apache License, Version 2.0 (the "License");
20
+ you may not use this file except in compliance with the License.
21
+ You may obtain a copy of the License at
22
+
23
+ > <http://www.apache.org/licenses/LICENSE-2.0>
24
+
25
+ > Unless required by applicable law or agreed to in writing, software
26
+ distributed under the License is distributed on an "AS IS" BASIS,
27
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28
+ See the License for the specific language governing permissions and
29
+ limitations under the License.
30
+
31
+ Nothing in the following text should be construed to inhibit, contradict, or override any part of the Apache
32
+ License, Version 2.0.
33
+
34
+ 2. Definitions
35
+ --------------
36
+ The following terms and definitions shall be in effect for the rest of this document.
37
+
38
+ > **NOTE:** Singular nouns and pronouns are used throughout this License for
39
+ grammatical convenience. However, any of the terms below _may_ refer to a
40
+ collective work or group of people. If this pegs your punctiliousness, you
41
+ are directed to mentally substitute "Person _or persons_," "Dick _or
42
+ dicks,_" etc., throughout this license. Just don't tell us about it.
43
+
44
+ ### A. Project
45
+
46
+ A creative work of (software | writing | visual art | music) into which significant time and energy have been
47
+ invested by people who _are not you,_ and which has been released into the world for the benefit of the general
48
+ public (_including you._)
49
+
50
+ The **Project** may include, incorporate, derive from, or be inspired by other works. The Author, being a
51
+ Reasonable Person, has made use of such source materials only as permitted by their own licenses or applicable
52
+ law. The License you are reading applies only to those portions of the Project which are original and distinct to
53
+ it. Source materials may be covered by their own licenses or conditions, and should not be assumed to have
54
+ coverage under this License. (However, you are strongly encouraged not to be a dick about them either.)
55
+
56
+ ### B. Author
57
+
58
+ A person who has invested significant time and energy into the Project licensed herein. Given the Author's
59
+ release of the Project to the world under a liberal license, the Author is declared a Reasonable Person (at least
60
+ within this context) and inherits all attributes, freedoms, and responsibilities thereof. No other assumptions
61
+ are made about the Author, nor should you make any.
62
+
63
+ ### C. Reasonable Person
64
+
65
+ A person who respects the time and energy that have been invested in the Project licensed herein, and acts
66
+ accordingly. A Reasonable Person is broadly characterized as one who exercises his or her privilege to use,
67
+ _not_ use, redistribute, modify, improve, worsen, review, report issues upon, participate in the community of,
68
+ or ignore the work _without_ placing undue demands upon the Author. I.e., a Reasonable Person is a constituent
69
+ of the majority of open source users and the population at large who are not Dicks.
70
+
71
+ ### D. Dick
72
+
73
+ A person who _does not_ respect the time and energy that have been invested in the Project, and acts to punish
74
+ such effort by giving others associated with the Project -- including, but not limited to, the Author -- a hard
75
+ time. A Dick is nearly always selfish, but not necessarily with deliberate intent; some Dicks are merely
76
+ thoughtless. The distinguishing characteristic of a Dick is that he or she places burdens upon Reasonable People,
77
+ reducing their motivation to engage in open source activities. This damping effect is a significant detriment to
78
+ the Project, to open source in general, to the production of new intellectual value in the world -- and,
79
+ ultimately, to the Dick himself or herself.
80
+
81
+ > **NOTE:** Despite its original gender association, the word "Dick" is used herein in a _cultural_ context
82
+ and not a _genital_ context. This License has chosen to adopt the term for its linguistic force and psychological
83
+ impact, and sincerely regrets any inference of sexism. For purposes of the terms and conditions contained herein,
84
+ it is understood that both men and women are equally capable of being Dicks.
85
+
86
+ > (But they shouldn't be.)
87
+
88
+ 3. Permissions
89
+ --------------
90
+
91
+ The following privileges are granted explicitly and exclusively to Reasonable People. Although the Author
92
+ acknowledges the practical unfeasibility of barring Dicks from enjoying the same privileges, they are nevertheless
93
+ asked to refrain from any activity related to the Project _and/or_ to reconsider their behavior and stop
94
+ being Dicks.
95
+
96
+ 1. You are permitted to use the Project or any component of the Project.
97
+
98
+ 2. You are permitted to redistribute the Project or any component of the Project, by itself or as part of a
99
+ different work, provided that you give fair and reasonable credit back to the Author.
100
+
101
+ 3. You are permitted to change the Project for your own needs or anyone else's. You may keep your changes to
102
+ yourself or submit them back to the Author or the community, as you see fit, provided you are not a Dick about it.
103
+
104
+ 4. You are permitted and encouraged to participate in any community related to the Project, or to create new
105
+ communities.
106
+
107
+ 5. You are permitted to report issues or problems with the Project, and to request that they be addressed,
108
+ so long as the request is made in a reasonable fashion. (This privilege does _not_ oblige the Author to respond.)
109
+
110
+ 6. You are permitted to make money from the Project. No recompense is owed to the Author unless by separate
111
+ agreement, although sharing opportunities for mutual benefit is by no means discouraged.
112
+
113
+ 7. You are permitted to discuss the Project in any medium, in any positive or negative spirit, so long as
114
+ criticism is not libelous nor _ad hominem._ (I.e., don't lie, and keep it about the _work_ and not the _people._)
115
+
116
+ 8. You are permitted to ignore the Project completely and make no use of it whatsoever. This right is
117
+ irrevocable and absolute, and extended to Dicks and Reasonable People alike.
118
+
119
+ 4. Limitations
120
+ --------------
121
+
122
+ The following restrictions are imposed explicitly and exclusively upon Dicks. These limitations are the inverse
123
+ of the above privileges and are also tautological, as the prohibited actions are those _definitive_ of Dickhood.
124
+
125
+ 1. You may not impede Reasonable People from exercising their privilege to use, redistribute, change, participate
126
+ in, profit from, discuss, or ignore the Project.
127
+
128
+ 2. You may not withhold the Author's credit for the Project, nor otherwise present the work of anyone else as
129
+ your own.
130
+
131
+ 3. You may not hold the Author responsible for any use or abuse of the Project by you or anyone else.
132
+
133
+ 4. You may not troll, flame, nor dumb down any community associated with the Project.
134
+
135
+ 5. Barring separate agreements, you may not _demand_ any time or attention on the part of the Author nor anyone
136
+ else in the community. You may not hold the Author personally accountable for any issues you discover nor
137
+ otherwise spread your own problems to other people.
138
+
139
+ 6. You may not attempt to _compel_ time nor money from the Author nor any other community member by any means,
140
+ including but not limited to legal action, intimidation, or annoyance.
141
+
142
+ 7. You may not engage in _ad hominem_ (i.e. personal) attacks or criticism of the Author in the course of
143
+ criticizing the Project.
144
+
145
+ 8. You may not impede the absolute and irrevocable privilege of the Author and other members of the community
146
+ to ignore you.
147
+
148
+ 5. Contact
149
+ ----------
150
+ For more information about this Project, contact the Author at:
151
+
152
+ * Craig S. Cottingham - <craig.cottingham@gmail.com>
153
+
154
+ For more information about the DBAD License, contact the Author, or the originator of the License at:
155
+
156
+ * Stephen Eley - <sfeley@gmail.com>
157
+
158
+ [1]: http://apache.org/licenses/LICENSE-2.0
@@ -0,0 +1,91 @@
1
+ # Treeline
2
+
3
+ Treeline turns indented-line input into a tree structure.
4
+
5
+ Given a sequence of lines with varying levels of indentation, like this:
6
+
7
+ line 1
8
+ line 2
9
+ line 3
10
+ line 4
11
+ line 5
12
+
13
+ Treeline will produce a hash like this:
14
+
15
+ {
16
+ "line 1" => {
17
+ "line 2" => {},
18
+ "line 3" => {
19
+ "line 4" => {},
20
+ },
21
+ "line 5" => {},
22
+ },
23
+ }
24
+
25
+ ## Installation
26
+
27
+ $ gem install treeline
28
+
29
+ ## Usage
30
+
31
+ The `parse` method on `Treeline::Parser` does the heavy lifting.
32
+
33
+ parser = Treeline::Parser.new
34
+ tree = parser.parse lines
35
+
36
+ The parser is bone-headed simple. The first line of input is taken to be the root of a new tree.
37
+ For each subsequent line, the amount of indentation is compared to the amount in the previous line, and
38
+
39
+ * if the indentation is the same, the new line is added as a sibling of the previous;
40
+ * if the indentation is greater, the new line is added as a child of the previous; or
41
+ * if the indentation is less, the parser climbs back towards the root until one of the previous
42
+ two rules applies.
43
+
44
+ `parse` optionally takes a block. Each line of the input will be passed to the block, which should
45
+ return the line modified as desired. For instance, to force all of the text to lowercase:
46
+
47
+ parser = Treeline::Parser.new
48
+ tree = parser.parse(lines) do | line |
49
+ line.downcase
50
+ end
51
+
52
+ The block is called *before* the amount of indentation is determined, so you can change the indentation
53
+ if you want to.
54
+
55
+ ## Dependencies
56
+
57
+ None at the moment.
58
+
59
+ ## Support
60
+
61
+ Wiki: <https://github.com/CraigCottingham/treeline/wiki>
62
+
63
+ ## To do
64
+
65
+ Some things I'm considering adding:
66
+
67
+ * Allow the first line to have leading whitespace, and strip that amount of whitespace from each
68
+ subsequent line
69
+
70
+ ## Contributing
71
+
72
+ Treeline has been written the particular need I have *right now* in mind. I'm trying hard not to bulk it up
73
+ with stuff that I or someone else might want someday. That being said, if you have a particular need that
74
+ Treeline doesn't quite satisfy in its current state, I'm happy to consider requests or (better yet)
75
+ contributions.
76
+
77
+ Here’s the most direct way to get your work merged into the project:
78
+
79
+ 1. Fork the project.
80
+ 2. Clone down your fork ( git clone git://github.com/<username>/treeline.git ).
81
+ 3. Create a topic branch to contain your change ( git checkout -b my_awesome_feature ).
82
+ 4. Hack away, add tests. Not necessarily in that order.
83
+ 5. Make sure everything still passes by running `rake test`.
84
+ 6. If necessary, rebase your commits into logical chunks, without errors.
85
+ 7. Push the branch up ( git push origin my_awesome_feature ).
86
+ 8. Send a pull request.
87
+
88
+ ## License
89
+
90
+ Copyright &copy; 2011 Craig S. Cottingham.
91
+ It is free software, and may be redistributed under the terms specified in the LICENSE file.
@@ -0,0 +1,41 @@
1
+ require 'bundler'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require File.expand_path('../lib/treeline/version', __FILE__)
5
+
6
+ Bundler::GemHelper.install_tasks
7
+
8
+ Rake::TestTask.new(:test) do |test|
9
+ test.libs << 'lib' << 'test'
10
+ test.pattern = 'test/**/*_test.rb'
11
+ end
12
+
13
+ # namespace :test do
14
+ # Rake::TestTask.new(:lint) do |test|
15
+ # test.libs << 'lib' << 'test'
16
+ # test.pattern = 'test/test_active_model_lint.rb'
17
+ # end
18
+ #
19
+ # task :all => ['test', 'test:lint']
20
+ # end
21
+
22
+ # task :default => 'test:all'
23
+ task :default => 'test'
24
+
25
+ desc 'Builds the gem'
26
+ task :build do
27
+ sh "gem build treeline.gemspec"
28
+ end
29
+
30
+ desc 'Builds and installs the gem'
31
+ task :install => :build do
32
+ sh "gem install pkg/treeline-#{Treeline::VERSION}.gem"
33
+ end
34
+
35
+ desc 'Tags version, pushes to remote, and pushes gem'
36
+ task :release => :build do
37
+ sh "git tag v#{Treeline::VERSION}"
38
+ sh "git push origin master"
39
+ sh "git push origin v#{Treeline::VERSION}"
40
+ sh "gem push treeline-#{Treeline::VERSION}.gem"
41
+ end
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby -wKU
2
+
3
+ module Treeline
4
+ class Parser
5
+
6
+ def parse(lines)
7
+ tree = {}
8
+ @path = []
9
+
10
+ lines.each do | line |
11
+ # line.chomp!
12
+ line.rstrip!
13
+ line = yield(line) if block_given?
14
+
15
+ # first, catch root elements (with no indent)
16
+ if (line =~ /^\S/)
17
+ @path = [ [ line, 0 ] ]
18
+ else
19
+ # next, catch indented elements
20
+ matched = /^(\s+)/.match(line)
21
+ unless (matched.nil?)
22
+ indent = matched[1].length
23
+ while (indent <= @path[0][1])
24
+ @path.shift
25
+ end
26
+ line.lstrip!
27
+ @path.unshift [ line, indent ]
28
+ end
29
+ end
30
+
31
+ # puts self.to_s
32
+ make_path_to_node(tree, @path.reverse)
33
+
34
+ end
35
+
36
+ tree
37
+ end
38
+
39
+ protected
40
+
41
+ def make_path_to_node(tree, path)
42
+ make_path_to_node(tree[path[0][0]], path[1..-1]) if (path.count > 1)
43
+ tree[path[0][0]] = {} if (path.count == 1)
44
+ tree
45
+ end
46
+
47
+ private
48
+
49
+ def to_s
50
+ @path.reverse.map { | item | item[0] }.join(" > ")
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,3 @@
1
+ module Treeline
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env ruby -wKU
2
+
3
+ require "test/unit"
4
+ require File.expand_path('lib/treeline/parser')
5
+
6
+ class ParserTest < Test::Unit::TestCase
7
+
8
+ def test_parser
9
+ lines = []
10
+ lines << "A"
11
+ lines << " A::B1"
12
+ lines << " A::B2"
13
+ lines << " A::B2::C"
14
+ lines << " A::B3"
15
+ lines << " A::B3::D1"
16
+ lines << " A::B3::D2"
17
+
18
+ parser = Treeline::Parser.new
19
+
20
+ tree = parser.parse lines
21
+ assert_not_nil tree
22
+ assert_equal 1, tree.keys.count
23
+ assert_has_key tree, 'A'
24
+
25
+ subtree = tree['A']
26
+ assert_not_nil subtree
27
+ assert_equal 3, subtree.keys.count
28
+ assert_has_key subtree, 'A::B1'
29
+ assert_has_key subtree, 'A::B2'
30
+ assert_has_key subtree, 'A::B3'
31
+
32
+ subsubtree = subtree['A::B1']
33
+ assert_not_nil subsubtree
34
+ assert_equal 0, subsubtree.keys.count
35
+
36
+ subsubtree = subtree['A::B2']
37
+ assert_not_nil subsubtree
38
+ assert_equal 1, subsubtree.keys.count
39
+ assert_has_key subsubtree, 'A::B2::C'
40
+
41
+ subsubtree = subtree['A::B3']
42
+ assert_not_nil subsubtree
43
+ assert_equal 2, subsubtree.keys.count
44
+ assert_has_key subsubtree, 'A::B3::D1'
45
+ assert_has_key subsubtree, 'A::B3::D2'
46
+ end
47
+
48
+ def test_parser_with_block
49
+ lines = []
50
+ lines << "A"
51
+ lines << " A::B1"
52
+ lines << " A::B2"
53
+ lines << " A::B2::C"
54
+ lines << " A::B3"
55
+ lines << " A::B3::D1"
56
+ lines << " A::B3::D2"
57
+
58
+ parser = Treeline::Parser.new
59
+
60
+ tree = parser.parse(lines) do | item |
61
+ item.downcase
62
+ end
63
+ assert_not_nil tree
64
+ assert_equal 1, tree.keys.count
65
+ assert_has_key tree, 'a'
66
+
67
+ subtree = tree['a']
68
+ assert_not_nil subtree
69
+ assert_equal 3, subtree.keys.count
70
+ assert_has_key subtree, 'a::b1'
71
+ assert_has_key subtree, 'a::b2'
72
+ assert_has_key subtree, 'a::b3'
73
+
74
+ subsubtree = subtree['a::b1']
75
+ assert_not_nil subsubtree
76
+ assert_equal 0, subsubtree.keys.count
77
+
78
+ subsubtree = subtree['a::b2']
79
+ assert_not_nil subsubtree
80
+ assert_equal 1, subsubtree.keys.count
81
+ assert_has_key subsubtree, 'a::b2::c'
82
+
83
+ subsubtree = subtree['a::b3']
84
+ assert_not_nil subsubtree
85
+ assert_equal 2, subsubtree.keys.count
86
+ assert_has_key subsubtree, 'a::b3::d1'
87
+ assert_has_key subsubtree, 'a::b3::d2'
88
+ end
89
+
90
+ def test_block_changing_indentation
91
+ lines = []
92
+ lines << "0 A"
93
+ lines << "1 A::B1"
94
+ lines << "1 A::B2"
95
+ lines << "2 A::B2::C"
96
+ lines << "1 A::B3"
97
+ lines << "2 A::B3::D1"
98
+ lines << "2 A::B3::D2"
99
+
100
+ parser = Treeline::Parser.new
101
+
102
+ tree = parser.parse(lines) do | item |
103
+ matched = /^(\d+)\s+(.*)$/.match(item)
104
+ (" " * matched[1].to_i) + matched[2]
105
+ end
106
+ assert_not_nil tree
107
+ assert_equal 1, tree.keys.count
108
+ assert_has_key tree, 'A'
109
+
110
+ subtree = tree['A']
111
+ assert_not_nil subtree
112
+ assert_equal 3, subtree.keys.count
113
+ assert_has_key subtree, 'A::B1'
114
+ assert_has_key subtree, 'A::B2'
115
+ assert_has_key subtree, 'A::B3'
116
+
117
+ subsubtree = subtree['A::B1']
118
+ assert_not_nil subsubtree
119
+ assert_equal 0, subsubtree.keys.count
120
+
121
+ subsubtree = subtree['A::B2']
122
+ assert_not_nil subsubtree
123
+ assert_equal 1, subsubtree.keys.count
124
+ assert_has_key subsubtree, 'A::B2::C'
125
+
126
+ subsubtree = subtree['A::B3']
127
+ assert_not_nil subsubtree
128
+ assert_equal 2, subsubtree.keys.count
129
+ assert_has_key subsubtree, 'A::B3::D1'
130
+ assert_has_key subsubtree, 'A::B3::D2'
131
+ end
132
+
133
+ protected
134
+
135
+ def assert_has_key(tree, key, msg=nil)
136
+ msg = "Key '#{key}' not found" if msg.nil?
137
+ flunk msg unless tree.has_key?(key)
138
+ end
139
+
140
+ end
@@ -0,0 +1,24 @@
1
+ # treeline.gemspec
2
+ # -*- encoding: utf-8 -*-
3
+ $:.push File.expand_path("../lib", __FILE__)
4
+ require "treeline/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "treeline"
8
+ s.version = Treeline::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ["Craig S. Cottingham"]
11
+ s.email = ["craig.cottingham@gmail.com"]
12
+ s.homepage = "https://github.com/CraigCottingham/treeline"
13
+ s.summary = %q{Turns indented-line input into a tree structure.}
14
+ s.description = %q{Turns indented-line input into a tree structure.}
15
+
16
+ # s.add_development_dependency "rspec"
17
+
18
+ # s.rubyforge_project = ""
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: treeline
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Craig S. Cottingham
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-13 00:00:00 Z
14
+ dependencies: []
15
+
16
+ description: Turns indented-line input into a tree structure.
17
+ email:
18
+ - craig.cottingham@gmail.com
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files: []
24
+
25
+ files:
26
+ - .gitignore
27
+ - Gemfile
28
+ - Gemfile.lock
29
+ - LICENSE.md
30
+ - README.md
31
+ - Rakefile
32
+ - lib/treeline/parser.rb
33
+ - lib/treeline/version.rb
34
+ - test/01_parser_test.rb
35
+ - treeline.gemspec
36
+ homepage: https://github.com/CraigCottingham/treeline
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.8.2
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: Turns indented-line input into a tree structure.
63
+ test_files:
64
+ - test/01_parser_test.rb