nin 0.0.0 → 0.7.0

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