nin 0.0.0 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc5037bc8929225d80c4ffda217726c83a054c9a0c2d7c40d18b95b749248044
4
- data.tar.gz: 1a85efacd7a65c1df2d3da69faa058a430d898d6c30e7b0c401473a1d6a0cba8
3
+ metadata.gz: e69e3a795983376ba5be5fd6bd9b639dcb8856cf11585e52cb2493b701e98ab4
4
+ data.tar.gz: 4e3662bb0d5e87243eb78d20619e5a33904c586e158a3e4fa067ebd098e6e0d1
5
5
  SHA512:
6
- metadata.gz: 8cd7d778fd4a06352be726ad2b2dae3b032d76d4c33db113d23f5d8e5f7527aca9e4e552d9f3200655839739064bade40dcfbc7fb0325abae69ebf00e6b846ce
7
- data.tar.gz: 60196625b942e4034c304aae5ee6856f36dcad94aff28ccb6153baf4beba30095f393fcf1800eb78dfd42da3545c1a62ae7a12fe85787666d25b9af1db3e1cc4
6
+ metadata.gz: 72afcf6252cd03732ebd9b1e03d9eb0fc209aaf22edc1de4760be1a0d5e89ee2cf01210dd915cd0cb01d3d23700552e45e7de9738ebcd76b86b196d432a416e7
7
+ data.tar.gz: f6850697bc332effae708dcee96ef0b1f0812e8e254c8a9f7ad5bb3da57f35db6188c0d739dfb386be4dc03e1529d5ff7538051f69044210f9bf09cf0f311c8a
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ .byebug_history
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ gemspec
@@ -0,0 +1,29 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ nin (0.6.0)
5
+ chronic
6
+ colored2
7
+ toml-rb
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ byebug (10.0.2)
13
+ chronic (0.10.2)
14
+ citrus (3.0.2)
15
+ colored2 (3.1.2)
16
+ minitest (5.11.3)
17
+ toml-rb (1.1.2)
18
+ citrus (~> 3.0, > 3.0)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ byebug
25
+ minitest
26
+ nin!
27
+
28
+ BUNDLED WITH
29
+ 1.17.1
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Ahmed Saleh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,67 @@
1
+ nin
2
+ ---
3
+
4
+ A simple, full-featured command line todo app
5
+
6
+ ![nin demo GIF](/demo.gif)
7
+
8
+ ## Features
9
+
10
+ - Simple, easy-to-use CLI
11
+ - Currently supports: listing, adding, editing, deleting, completing,
12
+ archiving, and deleting archived todo items
13
+ - Smart colored output
14
+ - Modular code covered by unit tests
15
+ - Uses YAML for storage by default
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ gem install nin
21
+ ```
22
+
23
+ To run the tests:
24
+
25
+ ```console
26
+ rake
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ```console
32
+ NAME:
33
+ nin - a simple, full-featured command line todo app
34
+
35
+ USAGE:
36
+ nin COMMAND [arguments...]
37
+
38
+ COMMANDS:
39
+ l [a] List all unarchived todos. Pass optional argument `a` to list all todos
40
+ a desc Add a todo. Prepend due date by an @. Prepend tag by a \#
41
+ e id desc Edit a todo. Prepend due date by an @. Prepend tag by a \#
42
+ c id(s) Un/complete todo(s)
43
+ ac id(s) Un/archive todo(s)
44
+ d id(s) Delete todo(s)
45
+ gc Delete all archived todos. Resets item ids as a side effect
46
+ o Open todo file in $EDITOR
47
+ ```
48
+
49
+ ## Why
50
+
51
+ Why write another todo app? I like to use the terminal for everything and I've
52
+ been using a markdown file to manage my todo list. I looked for something
53
+ simple and I found [Todo.rb](https://gist.github.com/mattsears/1259080) which
54
+ `nin` started as a spinoff from. However, I needed to add some more features. I
55
+ then found [Todolist](http://todolist.site/) which I took some inspiration from
56
+ but kept the CLI as simple as it is in Todo.rb. I also didn't like that
57
+ todolist uses JSON to store the todo items because I wanted to view the file on
58
+ my phone and I needed something more readable.
59
+
60
+ ## Contribution
61
+
62
+ Contributions are welcome. If you found a bug or want to add a new feature,
63
+ open an issue or send a pull request.
64
+
65
+ ## License
66
+
67
+ See [LICENSE](https://github.com/aonemd/nin/blob/master/LICENSE).
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.test_files = FileList['test/**/*_test.rb']
7
+ end
8
+
9
+ task :default => :test
data/bin/nin ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/nin'
4
+
5
+ begin
6
+ Nin::Command.new(ARGV[0], ARGV[1..-1]).call
7
+ rescue Nin::ItemNotFoundError
8
+ puts "Todo item does not exist"
9
+ rescue Nin::EmptyCommandArgumentError
10
+ puts "Command argument cannot be empty\nRun nin to view the USAGE message"
11
+ end
Binary file
data/lib/nin.rb CHANGED
@@ -1,59 +1,16 @@
1
- module Nin
2
- class Item
3
- attr_accessor :body
4
-
5
- def initialize(desc)
6
- @desc = desc
7
- end
8
-
9
- def to_s
10
- "#{@desc}"
11
- end
12
- end
13
-
14
- class Todo
15
- attr_accessor :items
16
-
17
- def initialize()
18
- @items = load_items
19
- end
20
-
21
- def list
22
- end
23
-
24
- def add(todo)
25
- end
26
-
27
- def edit(id)
28
- end
29
-
30
- def delete(id)
31
- end
32
-
33
- private
34
-
35
- def load_items
36
- []
37
- end
38
- end
39
- end
40
-
41
- if __FILE__ == $0
42
- case ARGV[0]
43
- when 'l'
44
- Nin::Todo.new.list
45
- when 'a'
46
- Nin::Todo.new.add(ARGV[1])
47
- when 'e'
48
- Nin::Todo.new.edit(ARGV[1])
49
- when 'd'
50
- Nin::Todo.new.delete(ARGV[1])
51
- else
52
- puts "\nUSAGE: nin COMMAND [arguments...]\n\n"
53
- puts "COMMANDS:"
54
- puts " l List all todos"
55
- puts " a desc Add a todo"
56
- puts " e id Edit a todo"
57
- puts " d id Remove a todo"
58
- end
59
- end
1
+ require 'psych'
2
+ require 'toml-rb'
3
+ require 'chronic'
4
+ require 'colored2'
5
+ require 'date'
6
+ require 'readline'
7
+
8
+ require_relative 'nin/version'
9
+ require_relative 'nin/error'
10
+ require_relative 'nin/yaml_store'
11
+ require_relative 'nin/toml_store'
12
+ require_relative 'nin/parser'
13
+ require_relative 'nin/item_presenter'
14
+ require_relative 'nin/item'
15
+ require_relative 'nin/todo'
16
+ require_relative 'nin/command'
@@ -0,0 +1,76 @@
1
+ module Nin
2
+ class Command
3
+ COMMANDS_WITH_ARGS = %w(a e c ac d)
4
+
5
+ def initialize(command, args)
6
+ @command = command
7
+ @args = args
8
+ @todo = Todo.new(YamlStore.new, collect_options)
9
+
10
+ validate_args
11
+ end
12
+
13
+ def call
14
+ case @command
15
+ when 'l'
16
+ @todo.list
17
+ when 'a'
18
+ desc, date, tags = Parser.new(@args.join(' ')).call
19
+ @todo.add(desc, date, tags)
20
+ when 'e'
21
+ desc, date, tags = Parser.new(@args[1..-1].join(' ')).call
22
+ @todo.edit(@args[0].to_i, desc, date, tags)
23
+ when 'c'
24
+ @todo.complete(*@args)
25
+ when 'ac'
26
+ @todo.archive(*@args)
27
+ when 'd'
28
+ @todo.delete(*@args)
29
+ when 'gc'
30
+ @todo.delete_archived
31
+ when 'o'
32
+ system("`echo $EDITOR` #{@todo.store.file}")
33
+ when 'i'
34
+ run_interactive_mode
35
+ else
36
+ puts "NAME:\n\tnin - a simple, full-featured command line todo app"
37
+ puts "\nUSAGE:\n\tnin COMMAND [arguments...]"
38
+ puts "\nCOMMANDS:"
39
+ puts "\tl [a] List all unarchived todos. Pass optional argument `a` to list all todos"
40
+ puts "\ta desc Add a todo. Prepend due date by a @. Prepend each tag by a \\#"
41
+ puts "\te id desc Edit a todo. Prepend due date by a @. Prepend each tag by a \\#"
42
+ puts "\tc id(s) Un/complete todo(s)"
43
+ puts "\tac id(s) Un/archive todo(s)"
44
+ puts "\td id(s) Delete todo(s)"
45
+ puts "\tgc Delete all archived todos. Resets item ids as a side effect"
46
+ puts "\to Open todo file in $EDITOR"
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def collect_options
53
+ options = { archived: false }
54
+
55
+ if @command == 'l' && @args[0] == 'a'
56
+ options[:archived] = true
57
+ end
58
+
59
+ options
60
+ end
61
+
62
+ def validate_args
63
+ COMMANDS_WITH_ARGS.each do |command|
64
+ raise EmptyCommandArgumentError if @command == command && @args.empty?
65
+ end
66
+ end
67
+
68
+ def run_interactive_mode
69
+ while line = Readline.readline("nin> ", true)
70
+ line = line.split(' ')
71
+
72
+ Command.new(line[0], line[1..-1]).call
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,4 @@
1
+ module Nin
2
+ class ItemNotFoundError < StandardError; end
3
+ class EmptyCommandArgumentError < StandardError; end
4
+ end
@@ -0,0 +1,60 @@
1
+ module Nin
2
+ class Item
3
+ attr_accessor :id, :desc, :date, :tags, :completed, :archived
4
+
5
+ def initialize(id,
6
+ desc,
7
+ date = nil,
8
+ tags = [],
9
+ completed = false,
10
+ archived = false,
11
+ formatter = ItemPresenter)
12
+
13
+ @id = id
14
+ @desc = desc
15
+ self.date = date # this looks ugly
16
+ @tags = tags
17
+ @completed = completed
18
+ @archived = archived
19
+ @formatter = formatter.new(self)
20
+ end
21
+
22
+ def date=(date = nil)
23
+ @date = date || Date.today.to_s
24
+ end
25
+
26
+ def toggle_completed!
27
+ @completed = !@completed
28
+ end
29
+
30
+ def toggle_archived!
31
+ @archived = !@archived
32
+ end
33
+
34
+ def to_s
35
+ @formatter.call
36
+ end
37
+
38
+ def to_h
39
+ {
40
+ 'id' => id,
41
+ 'desc' => desc,
42
+ 'tags' => tags,
43
+ 'completed' => completed,
44
+ 'archived' => archived
45
+ }
46
+ end
47
+
48
+ def completed?
49
+ @completed
50
+ end
51
+
52
+ def archived?
53
+ @archived
54
+ end
55
+
56
+ def due?
57
+ @date < Date.today.to_s
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,49 @@
1
+ module Nin
2
+ class ItemPresenter < SimpleDelegator
3
+ def call
4
+ sprintf("%d\t%s\t%s \t%s %s",
5
+ id, completed, date, desc, tags).gsub(' ', ' ')
6
+ end
7
+
8
+ private
9
+
10
+ def desc
11
+ if self.archived?
12
+ self.desc.yellow
13
+ elsif self.completed?
14
+ self.desc.white
15
+ else
16
+ self.desc
17
+ end
18
+ end
19
+
20
+ def completed
21
+ if self.completed?
22
+ '[x]'.green
23
+ else
24
+ '[ ]'
25
+ end
26
+ end
27
+
28
+ def date
29
+ case self.date
30
+ when Date.today.to_s
31
+ '@today'.bold
32
+ when Date.today.succ.to_s
33
+ '@tomorrow'
34
+ when Date.today.prev_day.to_s
35
+ '@yesterday'.magenta
36
+ else
37
+ if self.due?
38
+ ('@' << self.date).magenta
39
+ else
40
+ '@' << self.date
41
+ end
42
+ end.cyan
43
+ end
44
+
45
+ def tags
46
+ self.tags.map { |tag| tag.dup.prepend('#') }.join(' ').blue
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,41 @@
1
+ module Nin
2
+ class Parser
3
+ def initialize(desc)
4
+ @desc = desc
5
+ @date = extract_date
6
+ @tags = extract_tags
7
+ end
8
+
9
+ def call
10
+ [@desc, @date, @tags]
11
+ end
12
+
13
+ private
14
+
15
+ def extract_date
16
+ date_pattern = /@[A-Z0-9.,-]+/i
17
+ date = @desc.scan(date_pattern).last
18
+
19
+ return nil if date.nil?
20
+
21
+ date.gsub!('@', '')
22
+ strip_tags(date_pattern)
23
+
24
+ Chronic.parse(date).strftime('%Y-%m-%d')
25
+ end
26
+
27
+ def extract_tags
28
+ tag_pattern = /#[A-Z0-9_]+/i
29
+ tags = @desc.scan(tag_pattern).map { |tag| tag.gsub!('#', '') }
30
+
31
+ strip_tags(tag_pattern)
32
+
33
+ tags
34
+ end
35
+
36
+ def strip_tags(pattern)
37
+ @desc.gsub!(pattern, '')
38
+ @desc.strip!
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,130 @@
1
+ module Nin
2
+ class Todo
3
+ attr_accessor :items
4
+ attr_reader :store
5
+
6
+ def initialize(store = YamlStore.new, options = {})
7
+ @store = store
8
+ @options = options
9
+ @items = load_items.sort_by(&:date)
10
+ end
11
+
12
+ def list
13
+ if @options[:archived]
14
+ @items
15
+ else
16
+ unarchived_items
17
+ end.each do |item|
18
+ puts item
19
+ end
20
+ end
21
+
22
+ def add(desc, date, tags)
23
+ @items << Item.new(next_id, desc, date, tags)
24
+ @store.write(to_hash)
25
+ end
26
+
27
+ def edit(id, desc, date, tags)
28
+ item = find_by_id(id)
29
+ item.desc = desc
30
+ item.date = date
31
+ item.tags = tags
32
+ @store.write(to_hash)
33
+ end
34
+
35
+ def complete(*ids)
36
+ ids.each do |id|
37
+ item = find_by_id(id.to_i)
38
+ item.toggle_completed!
39
+ end
40
+
41
+ @store.write(to_hash)
42
+ end
43
+
44
+ def archive(*ids)
45
+ ids.each do |id|
46
+ item = find_by_id(id.to_i)
47
+ item.toggle_archived!
48
+ end
49
+
50
+ @store.write(to_hash)
51
+ end
52
+
53
+ def delete_archived
54
+ delete(*archived_items.map(&:id))
55
+ reset_item_indices!
56
+ end
57
+
58
+ def delete(*ids)
59
+ ids.each do |id|
60
+ item = find_by_id(id.to_i)
61
+ @items.delete(item)
62
+ end
63
+
64
+ reset_item_indices!
65
+ end
66
+
67
+ private
68
+
69
+ def load_items
70
+ items = []
71
+ @store.read.map do |key, values|
72
+ date = key.dup
73
+ values.map do |item|
74
+ items << Item.new(item.fetch('id').to_i,
75
+ item.fetch('desc'),
76
+ date,
77
+ item.fetch('tags'),
78
+ item.fetch('completed'),
79
+ item.fetch('archived')
80
+ )
81
+ end
82
+ end
83
+
84
+ items
85
+ end
86
+
87
+ def to_hash
88
+ @items.group_by(&:date).reduce({}) do |hash, (key, values)|
89
+ hash[key] = values.map(&:to_h)
90
+ hash
91
+ end
92
+ end
93
+
94
+ def next_id
95
+ last_id + 1
96
+ end
97
+
98
+ def last_id
99
+ begin
100
+ @items.sort_by(&:id).last.id
101
+ rescue NoMethodError
102
+ 0
103
+ end
104
+ end
105
+
106
+ def find_by_id(id)
107
+ found_item = @items.find { |item| item.id == id }
108
+
109
+ raise ItemNotFoundError unless found_item
110
+
111
+ found_item
112
+ end
113
+
114
+ def archived_items
115
+ @items.select { |item| item.archived? }
116
+ end
117
+
118
+ def unarchived_items
119
+ @items.select { |item| !item.archived? }
120
+ end
121
+
122
+ def reset_item_indices!
123
+ @items.each.with_index(1) do |item, index|
124
+ item.id = index
125
+ end
126
+
127
+ @store.write(to_hash)
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,31 @@
1
+ module Nin
2
+ class TomlStore
3
+ DEFAULT_FILE = "#{ENV['HOME']}/.todos.toml"
4
+
5
+ attr_reader :file
6
+
7
+ def initialize(file = DEFAULT_FILE)
8
+ @file = file
9
+
10
+ init_store
11
+ end
12
+
13
+ def read
14
+ TomlRB.load_file(@file)
15
+ end
16
+
17
+ def write(hash)
18
+ File.open(@file, 'w') do |file|
19
+ file.write(TomlRB.dump(hash))
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def init_store
26
+ return if File.exist?(@file)
27
+
28
+ File.open(@file, "w")
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Nin
2
+ VERSION='0.7.0'
3
+ end
@@ -0,0 +1,31 @@
1
+ module Nin
2
+ class YamlStore
3
+ DEFAULT_FILE = "#{ENV['HOME']}/.todos.yaml"
4
+
5
+ attr_reader :file
6
+
7
+ def initialize(file = DEFAULT_FILE)
8
+ @file = file
9
+
10
+ init_store
11
+ end
12
+
13
+ def read
14
+ Psych.load_file(@file) || {} # Psych returns false if the file is empty
15
+ end
16
+
17
+ def write(hash)
18
+ File.open(@file, 'w') do |file|
19
+ file.write(Psych.dump(hash))
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def init_store
26
+ return if File.exist?(@file)
27
+
28
+ File.open(@file, "w")
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ require File.expand_path('../lib/nin/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Ahmed Saleh"]
6
+ gem.email = 'aonemdsaleh@gmail.com'
7
+ gem.description = "A simple, full-featured command line todo app"
8
+ gem.summary = "A command line todo app that provides an easy to use CLI for everyday todo management"
9
+ gem.homepage = 'https://github.com/aonemd/nin'
10
+
11
+ gem.files = `git ls-files`.split($\).reject do |f|
12
+ f.match(%r{^(test|spec|features)/})
13
+ end
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.executables = ["nin"]
16
+
17
+ gem.name = 'nin'
18
+ gem.version = Nin::VERSION
19
+ gem.license = 'MIT'
20
+
21
+ gem.add_dependency 'toml-rb'
22
+ gem.add_dependency 'chronic'
23
+ gem.add_dependency 'colored2'
24
+
25
+ gem.add_development_dependency 'byebug'
26
+ gem.add_development_dependency 'minitest'
27
+ end
metadata CHANGED
@@ -1,23 +1,112 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ahmed Saleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-07 00:00:00.000000000 Z
12
- dependencies: []
13
- description: Under construction
11
+ date: 2018-12-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: toml-rb
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: chronic
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: colored2
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: A simple, full-featured command line todo app
14
84
  email: aonemdsaleh@gmail.com
15
- executables: []
85
+ executables:
86
+ - nin
16
87
  extensions: []
17
88
  extra_rdoc_files: []
18
89
  files:
90
+ - ".gitignore"
91
+ - Gemfile
92
+ - Gemfile.lock
93
+ - LICENSE
94
+ - README.md
95
+ - Rakefile
96
+ - bin/nin
97
+ - demo.gif
19
98
  - lib/nin.rb
20
- homepage: https://github.com/gems/nin
99
+ - lib/nin/command.rb
100
+ - lib/nin/error.rb
101
+ - lib/nin/item.rb
102
+ - lib/nin/item_presenter.rb
103
+ - lib/nin/parser.rb
104
+ - lib/nin/todo.rb
105
+ - lib/nin/toml_store.rb
106
+ - lib/nin/version.rb
107
+ - lib/nin/yaml_store.rb
108
+ - nin.gemspec
109
+ homepage: https://github.com/aonemd/nin
21
110
  licenses:
22
111
  - MIT
23
112
  metadata: {}
@@ -40,5 +129,6 @@ rubyforge_project:
40
129
  rubygems_version: 2.7.6
41
130
  signing_key:
42
131
  specification_version: 4
43
- summary: Under construction
132
+ summary: A command line todo app that provides an easy to use CLI for everyday todo
133
+ management
44
134
  test_files: []