mastodon2 0.3.1

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.md
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE.md
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+ doc
23
+ .yardoc
data/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Colin Shea
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ **THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.**
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # Mastodon
2
+ A [todo.txt][ttxt] parser.
3
+
4
+ [ttxt]: http://ginatrapani.github.com/todo.txt-cli/
5
+
6
+ ## Installation
7
+
8
+ sudo gem install mastodon
9
+
10
+ ## Usage
11
+
12
+ require 'mastodon'
13
+ mast = Mastodon.new(File.readlines("todo.txt"))
14
+ # List all the projects
15
+ mast.projects
16
+ # List all the contexts
17
+ mast.contexts
18
+
19
+
20
+ ## See Also
21
+ There are other links you can take a look at. If you care to, that is.
22
+
23
+ * [Run Code Run][rcr] (continuous integration)
24
+ * [Caliper & metric\_fu report][calip]
25
+ * [RDoc.info Documentation][rdoci] ([yardoc.org][yardoc])
26
+
27
+ [rcr]: http://runcoderun.com/evaryont/mastodon
28
+ [calip]: http://getcaliper.com/caliper/project?repo=git%3A%2F%2Fgithub.com%2Fevaryont%2Fmastodon.git
29
+ [rdoci]: http://rdoc.info/projects/evaryont/mastodon
30
+ [yardoc]: http://yardoc.org/docs/evaryont-mastodon
31
+
32
+ ## Copyright
33
+ Mastodon is released under the MIT license. Copyright (C) Colin Shea 2009. For
34
+ more information, consult LICENSE.txt for more information.
data/Rakefile ADDED
@@ -0,0 +1,83 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ task :default => :test
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gem|
9
+ gem.name = "mastodon2"
10
+ gem.summary = %Q{A Ruby parser for todo.txt files}
11
+ gem.description = %Q{A Ruby parser for todo.txt files}
12
+ gem.email = "colin@evaryont.me"
13
+ gem.homepage = "http://evaryont.me"
14
+ gem.authors = ["Colin Shea"]
15
+ gem.add_development_dependency "riot", ">= 0"
16
+ gem.add_development_dependency "yard", ">= 0"
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
+ end
22
+
23
+ require 'rake/testtask'
24
+ Rake::TestTask.new(:test) do |test|
25
+ test.libs << 'lib' << 'test'
26
+ test.pattern = 'test/**/*_test.rb'
27
+ test.verbose = true
28
+ end
29
+ task :test => :check_dependencies
30
+
31
+ begin
32
+ require 'rcov/rcovtask'
33
+ Rcov::RcovTask.new do |test|
34
+ test.libs << 'test'
35
+ test.pattern = 'test/**/*_test.rb'
36
+ test.verbose = true
37
+ end
38
+ rescue LoadError
39
+ task :rcov do
40
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
41
+ end
42
+ end
43
+
44
+ begin
45
+ require 'reek/adapters/rake_task'
46
+ Reek::RakeTask.new do |t|
47
+ t.fail_on_error = true
48
+ t.verbose = false
49
+ t.source_files = 'lib/**/*.rb'
50
+ end
51
+ rescue LoadError
52
+ task :reek do
53
+ abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
54
+ end
55
+ end
56
+
57
+ begin
58
+ require 'roodi'
59
+ require 'roodi_task'
60
+ RoodiTask.new do |t|
61
+ t.verbose = false
62
+ end
63
+ rescue LoadError
64
+ task :roodi do
65
+ abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi"
66
+ end
67
+ end
68
+
69
+ begin
70
+ require 'yard'
71
+ YARD::Rake::YardocTask.new do |t|
72
+ t.files = ["lib/**/*.rb"]
73
+ end
74
+ rescue LoadError
75
+ task :yard do
76
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
77
+ end
78
+ end
79
+
80
+ namespace :release do
81
+ desc "Release to all locations: Git, GitHub and GemCutter"
82
+ task :all => ["git:release", "github:release", "gemcutter:release"]
83
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 3
4
+ :patch: 1
5
+ :build:
@@ -0,0 +1,15 @@
1
+ class String
2
+ # Given 'string', find all matches of regular expression (removed from
3
+ # +string+) and return them as an array of strings.
4
+ def pull_regex(regexp)
5
+ found_values = []
6
+
7
+ until ((value = self[regexp]).nil?)
8
+ vindex = index(value)
9
+ self[ vindex .. (vindex + value.length) ] = ""
10
+ found_values << value.match(regexp)[1]
11
+ end
12
+
13
+ return found_values
14
+ end
15
+ end
data/lib/mastodon.rb ADDED
@@ -0,0 +1,76 @@
1
+ require 'set'
2
+
3
+ require 'core_ext/string/pull_regex'
4
+
5
+ require 'mastodon/todo'
6
+
7
+ class Mastodon
8
+ # A context is: An at-sign (@) followed by one or more non-whitespace characters.
9
+ Context_Regex = /(?<!\+)\B@(\S+)/
10
+ # A project is: An plus sign (+) followed by one or more non-whitespace characters.
11
+ Project_Regex = /(?<!@)\B\+(\S+)/
12
+ # A priority is: A capital letter (A-Z) surrounded by parentheses, at the beginning of the line.
13
+ Priority_Regex = /^\(([A-Z])\)/
14
+
15
+ attr_reader :contexts, :projects, :todos
16
+
17
+ # +todo+: An array of strings (each being an individual todo item)
18
+ def initialize(todos)
19
+ @contexts = Set.new
20
+ @projects = Set.new
21
+ @todos = []
22
+
23
+ parse! todos.map{|line| line.strip}
24
+
25
+ @contexts = @contexts.to_a
26
+ @projects = @projects.to_a
27
+ end
28
+
29
+ def parse!(todos)
30
+ todos.each do |todo|
31
+ # Looping through the string, find the metadata (context, project,
32
+ # priority). Store it in a temporary variable, then clear it from
33
+ # the original string. Strip all remaining whitespace at the end.
34
+
35
+ current_contexts = []
36
+ current_projects = []
37
+ current_priority = nil
38
+
39
+ current_contexts = todo.pull_regex(Context_Regex)
40
+ unless current_contexts.empty?
41
+ @contexts.merge(current_contexts)
42
+ end
43
+
44
+ current_projects = todo.pull_regex(Project_Regex)
45
+ unless current_projects.empty?
46
+ @projects.merge(current_projects)
47
+ end
48
+
49
+ current_priority = todo.pull_regex(Priority_Regex)
50
+
51
+ todo.strip!
52
+ @todos << Mastodon::Todo.new(todo, current_contexts, current_projects, current_priority.first)
53
+ end
54
+ end
55
+
56
+ # How many todos there are.
57
+ def size
58
+ @todos.size
59
+ end
60
+
61
+ # Get an individual todo. The id and line number are the same. 0 index, not
62
+ # 1, as files are numbered. So line 3 is id 2. XXX: Change?
63
+ def [](id)
64
+ @todos[id]
65
+ end
66
+
67
+ # Find all todos that have the context @+context+
68
+ def find_context(context)
69
+ @todos.select { |todo| todo.contexts.include? context }
70
+ end
71
+
72
+ # Find all todos that have the project ++project+
73
+ def find_project(project)
74
+ @todos.select { |todo| todo.projects.include? project }
75
+ end
76
+ end
@@ -0,0 +1,30 @@
1
+ class Mastodon
2
+ class Todo < Struct.new(:text, :contexts, :projects, :priority)
3
+ include Comparable
4
+
5
+ def to_s
6
+ pri = priority ? "(#{priority})" : ""
7
+ ctx = contexts.empty? ? "" : "@#{contexts.join(' @')}"
8
+ prj = projects.empty? ? "" : "+#{projects.join(' +')}"
9
+
10
+ "#{pri} #{text} #{ctx} #{prj}".strip
11
+ end
12
+
13
+ def inspect
14
+ "#<Mastodon::Todo \"#{to_s}\">"
15
+ end
16
+
17
+ # Comparison operator: Sort todos by their priority first, then sort
18
+ # them by the text.
19
+ def <=>(other_todo)
20
+ return -1 if (priority.nil? and !other_todo.priority.nil?)
21
+
22
+ pri = (priority <=> other_todo.priority)
23
+ if pri == 0
24
+ return text <=> other_todo.text
25
+ else
26
+ return pri
27
+ end
28
+ end
29
+ end
30
+ end
data/mastodon.gemspec ADDED
@@ -0,0 +1,52 @@
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{mastodon}
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 = ["Colin Shea"]
12
+ s.date = %q{2009-12-23}
13
+ s.description = %q{Mastodon: A ruby parser for todo.txt files.
14
+
15
+ And the mastodon, like plain text, isn't extinct! (Yet.)}
16
+ s.email = %q{colin@evaryont.me}
17
+ s.extra_rdoc_files = [
18
+ "README.mkd"
19
+ ]
20
+ s.files = [
21
+ "Rakefile",
22
+ "VERSION.yml",
23
+ "lib/mastodon.rb",
24
+ "lib/mastodon/todo.rb",
25
+ "lib/mastodon/version.rb",
26
+ "test/run_tests.rb",
27
+ "test/test_helper.rb",
28
+ "test/test_mastodon.rb",
29
+ "test/todo.txt"
30
+ ]
31
+ s.homepage = %q{http://github.com/evaryont/mastodon/}
32
+ s.rdoc_options = ["--charset=UTF-8"]
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = %q{1.3.5}
35
+ s.summary = %q{A ruby parser for todo.txt files}
36
+ s.test_files = [
37
+ "test/run_tests.rb",
38
+ "test/test_helper.rb",
39
+ "test/test_mastodon.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
47
+ else
48
+ end
49
+ else
50
+ end
51
+ end
52
+
@@ -0,0 +1,139 @@
1
+ require 'teststrap'
2
+
3
+ context "Mastodon" do
4
+ setup do
5
+ @todos = File.readlines(File.join(File.dirname(__FILE__), "todo.txt"))
6
+ Mastodon.new(@todos)
7
+ end
8
+
9
+ context "Projects" do
10
+ setup do
11
+ topic.projects
12
+ end
13
+
14
+ asserts_topic.equals ["proj", "proj2", "proj+phone", "proj/foo", "p_r_o_j", "p-r-o-j", "+proj", "@proj"]
15
+
16
+ asserts_topic.kind_of? Array
17
+ end
18
+
19
+ context "Contexts" do
20
+ setup do
21
+ topic.contexts
22
+ end
23
+
24
+ asserts_topic.equals ["con", "con2", "con@phone", "con/foo", "c_o_n", "c-o-n", "@con", "+con"]
25
+
26
+ asserts_topic.kind_of? Array
27
+ end
28
+
29
+ asserts "Non-existent contexts should return an empty array" do
30
+ topic.find_context("nosuchthing") == []
31
+ end
32
+ asserts "Non-existent projects should return an empty array" do
33
+ topic.find_project("thisprojectdoesntexist") == []
34
+ end
35
+
36
+ context "Context #2" do
37
+ setup do
38
+ topic.find_context("con2")
39
+ end
40
+ asserts "Context size should be greater than zero" do
41
+ topic.size > 0
42
+ end
43
+ asserts "First todo with the context 'con2' should be 'Multiple contexts'" do
44
+ topic.first.text == "Multiple contexts"
45
+ end
46
+ end
47
+
48
+ context "Project #2" do
49
+ setup do
50
+ topic.find_project("proj2")
51
+ end
52
+ should "greater than zero" do
53
+ topic.size > 0
54
+ end
55
+ asserts "First todo with the project 'proj2' should be 'Multiple projects'" do
56
+ topic.first.text == "Multiple projects"
57
+ end
58
+ end
59
+
60
+ context "Todo" do
61
+ #asserts(:size).equals @todos.size
62
+
63
+ asserts "all todos are of type Mastodon::Todo" do
64
+ !(topic.todos.map do |todo|
65
+ todo.is_a? Mastodon::Todo
66
+ end.index(false))
67
+ end
68
+
69
+ context "Lossless parsing: 1st Todo: Normal example" do
70
+ setup do
71
+ @todo = @todos[0].strip
72
+ topic[0]
73
+ end
74
+
75
+ should "be the same characters" do
76
+ topic.to_s.chars.to_a == @todo.chars.to_a
77
+ end
78
+ should "be the same length" do
79
+ topic.to_s.length == @todo.length
80
+ end
81
+ end
82
+
83
+ context "Lossless parsing: 8th Todo: Normal example, with priority" do
84
+ setup do
85
+ @todo = @todos[7].strip
86
+ topic[7]
87
+ end
88
+
89
+ should "be the same characters" do
90
+ topic.to_s.chars.to_a == @todo.chars.to_a
91
+ end
92
+ should "be the same length" do
93
+ topic.to_s.length == @todo.length
94
+ end
95
+ end
96
+
97
+ context "Lossless parsing: 17th Todo: Example without any metadata" do
98
+ setup do
99
+ @todo = @todos[16].strip
100
+ topic[16]
101
+ end
102
+
103
+ should "be the same characters" do
104
+ topic.to_s.chars.to_a == @todo.chars.to_a
105
+ end
106
+ should "be the same length" do
107
+ topic.to_s.length == @todo.length
108
+ end
109
+ end
110
+ end
111
+
112
+ asserts "13th todo should have the context 'con'" do
113
+ topic[13].contexts = ["con"]
114
+ end
115
+ asserts "14th todo should have the project 'proj'" do
116
+ topic[14].projects = ["proj"]
117
+ end
118
+
119
+ context "Priority" do
120
+ asserts "3rd todo should have no priority" do
121
+ topic[3].priority.nil?
122
+ end
123
+ asserts "4th todo should have no priority" do
124
+ topic[4].priority.nil?
125
+ end
126
+ asserts "5th todo should have priority A" do
127
+ topic[5].priority = "A"
128
+ end
129
+ asserts "6th todo should have priority Z" do
130
+ topic[6].priority = "Z"
131
+ end
132
+ asserts "7th todo should have priority Q" do
133
+ topic[7].priority = "Q"
134
+ end
135
+ asserts "8th todo should have no priority" do
136
+ topic[8].priority.nil?
137
+ end
138
+ end
139
+ end
data/test/teststrap.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'riot'
3
+ require 'mastodon'
4
+ require 'pp'
data/test/todo.txt ADDED
@@ -0,0 +1,17 @@
1
+ Todo @con +proj
2
+ left @ right @con
3
+ user@server email
4
+ Multiple projects +proj +proj2
5
+ Multiple contexts @con @con2
6
+ (A) Priority
7
+ (Z) All the way to Z
8
+ (Q) All mixed together @con +proj
9
+ Not a priority: (A)
10
+ Advanced contexts @con@phone @con/foo @c_o_n @c-o-n @@con
11
+ Advanced projects +proj+phone +proj/foo +p_r_o_j +p-r-o-j ++proj
12
+ Mixed symbols: +@proj @+con
13
+ @con Leading with a context
14
+ +proj Leading with a project
15
+ Google+Yahoo+Microsoft == monopoly
16
+ Google + Yahoo + Microsoft == monopoly
17
+ Ready to (ab)use
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mastodon2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1
5
+ platform: ruby
6
+ authors:
7
+ - Colin Shea
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-29 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: riot
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: yard
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: A Ruby parser for todo.txt files
36
+ email: colin@evaryont.me
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE.md
43
+ - README.md
44
+ files:
45
+ - .document
46
+ - .gitignore
47
+ - LICENSE.md
48
+ - README.md
49
+ - Rakefile
50
+ - VERSION.yml
51
+ - lib/core_ext/string/pull_regex.rb
52
+ - lib/mastodon.rb
53
+ - lib/mastodon/todo.rb
54
+ - mastodon.gemspec
55
+ - test/mastodon_test.rb
56
+ - test/teststrap.rb
57
+ - test/todo.txt
58
+ has_rdoc: true
59
+ homepage: http://evaryont.me
60
+ licenses: []
61
+
62
+ post_install_message:
63
+ rdoc_options:
64
+ - --charset=UTF-8
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ requirements: []
80
+
81
+ rubyforge_project:
82
+ rubygems_version: 1.3.5
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: A Ruby parser for todo.txt files
86
+ test_files:
87
+ - test/mastodon_test.rb
88
+ - test/teststrap.rb