treeline 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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