do_stuff 0.0.1 → 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.
- data/bin/do_stuff +1 -56
- data/lib/do_stuff/runner.rb +88 -0
- data/lib/do_stuff/standalone.rb +58 -0
- data/lib/do_stuff/todolist.rb +55 -53
- data/lib/do_stuff.rb +2 -0
- metadata +4 -2
data/bin/do_stuff
CHANGED
@@ -1,59 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
require 'rubygems'
|
3
|
-
require 'fileutils'
|
4
|
-
require 'optparse'
|
5
2
|
require 'do_stuff'
|
6
3
|
|
7
|
-
|
8
|
-
abort "Error: Couldn't find #{DO_STUFFRC}.\nPlease create it and put the " +
|
9
|
-
"path to your todo.txt file in it." unless File.exists?(DO_STUFFRC)
|
10
|
-
|
11
|
-
TODO_FILE = File.expand_path(File.read(DO_STUFFRC).chomp)
|
12
|
-
FileUtils.mkdir_p(File.dirname(TODO_FILE))
|
13
|
-
FileUtils.touch(TODO_FILE)
|
14
|
-
|
15
|
-
program = File.basename($0)
|
16
|
-
USAGE = <<EOS
|
17
|
-
usage: #{program} list unfinished tasks
|
18
|
-
#{program} <task desc> add a new task
|
19
|
-
#{program} <task num> erase task
|
20
|
-
#{program} -e[task num] edit task file and jump to given task
|
21
|
-
#{program} -h show this message
|
22
|
-
EOS
|
23
|
-
|
24
|
-
OptionParser.new do |opts|
|
25
|
-
opts.on('-e [TASK NUM]') do |task_num|
|
26
|
-
TodoList.edit(TODO_FILE)
|
27
|
-
exit
|
28
|
-
end
|
29
|
-
|
30
|
-
opts.on('-h', '--help') do
|
31
|
-
puts USAGE
|
32
|
-
exit
|
33
|
-
end
|
34
|
-
end.parse!
|
35
|
-
|
36
|
-
begin
|
37
|
-
todolist = TodoList.new(TODO_FILE)
|
38
|
-
rescue TodoList::ParseError => e
|
39
|
-
abort "Error parsing #{e.file}: #{e.message}"
|
40
|
-
end
|
41
|
-
|
42
|
-
if ARGV.length == 0
|
43
|
-
todolist.tasks.each do |num, task|
|
44
|
-
puts "#{num}. #{task}"
|
45
|
-
end
|
46
|
-
elsif ARGV.length == 1 && ARGV[0] =~ /^\d+$/
|
47
|
-
task_num = ARGV[0].to_i
|
48
|
-
task = todolist.get(task_num)
|
49
|
-
abort "There is no task ##{task_num}." unless task
|
50
|
-
todolist.erase(task_num)
|
51
|
-
todolist.write!
|
52
|
-
puts "Erased ##{task_num}: #{task}"
|
53
|
-
else
|
54
|
-
# If nothing else matches, treat the arguments as a task description.
|
55
|
-
task = ARGV.join(' ')
|
56
|
-
task_num = todolist.add(task)
|
57
|
-
todolist.write!
|
58
|
-
puts "Added ##{task_num}: #{task}"
|
59
|
-
end
|
4
|
+
DoStuff::Runner.execute(*ARGV)
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
module DoStuff
|
5
|
+
module Runner
|
6
|
+
def self.execute(*argv)
|
7
|
+
dostuffrc = ENV['HOME'] + '/.do_stuffrc'
|
8
|
+
abort "Error: Couldn't find #{dostuffrc}.\nPlease create it and put " +
|
9
|
+
"the path to your todo.txt file in it." unless File.exists?(dostuffrc)
|
10
|
+
|
11
|
+
todofile = File.expand_path(File.read(dostuffrc).chomp)
|
12
|
+
FileUtils.mkdir_p(File.dirname(todofile))
|
13
|
+
FileUtils.touch(todofile)
|
14
|
+
|
15
|
+
|
16
|
+
opts = OptionParser.new do |opts|
|
17
|
+
opts.on('-e [TASK NUM]') do |task_num|
|
18
|
+
TodoList.edit(todofile)
|
19
|
+
exit
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on('--standalone FILE') do |file|
|
23
|
+
if defined?(::DoStuff::Standalone)
|
24
|
+
Standalone.save(file)
|
25
|
+
puts "#{file} generated successfully! Have fun doing stuff."
|
26
|
+
exit
|
27
|
+
else
|
28
|
+
abort "You're already using a standalone do_stuff script."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on('-h', '--help') do
|
33
|
+
usage
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
begin
|
39
|
+
opts.parse!(argv)
|
40
|
+
rescue OptionParser::ParseError => e
|
41
|
+
abort e.message
|
42
|
+
end
|
43
|
+
|
44
|
+
begin
|
45
|
+
todolist = TodoList.new(todofile)
|
46
|
+
rescue TodoList::ParseError => e
|
47
|
+
abort "Error parsing #{e.file}: #{e.message}"
|
48
|
+
end
|
49
|
+
|
50
|
+
if argv.length == 0
|
51
|
+
todolist.tasks.each do |num, task|
|
52
|
+
puts "#{num}. #{task}"
|
53
|
+
end
|
54
|
+
elsif argv.length == 1 && argv[0] =~ /^\d+$/
|
55
|
+
task_num = argv[0].to_i
|
56
|
+
task = todolist.get(task_num)
|
57
|
+
abort "There is no task ##{task_num}." unless task
|
58
|
+
todolist.erase(task_num)
|
59
|
+
todolist.write!
|
60
|
+
puts "Erased ##{task_num}: #{task}"
|
61
|
+
else
|
62
|
+
# If nothing else matches, treat the arguments as a task description.
|
63
|
+
task = argv.join(' ')
|
64
|
+
task_num = todolist.add(task)
|
65
|
+
todolist.write!
|
66
|
+
puts "Added ##{task_num}: #{task}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.usage
|
71
|
+
program = File.basename($0)
|
72
|
+
|
73
|
+
print <<-EOS
|
74
|
+
usage: #{program} list unfinished tasks
|
75
|
+
#{program} <task desc> add a new task
|
76
|
+
#{program} <task num> erase task
|
77
|
+
#{program} -e[task num] edit task file and jump to given task
|
78
|
+
#{program} -h, --help show this message
|
79
|
+
EOS
|
80
|
+
|
81
|
+
if defined?(::DoStuff::Standalone)
|
82
|
+
print <<-EOS
|
83
|
+
#{program} --standalone FILE generate a standalone version of do_stuff
|
84
|
+
EOS
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# This standalone script generator was shamelessly stolen from defunkt's "hub"
|
2
|
+
# script at https://github.com/defunkt/hub. Thanks!
|
3
|
+
|
4
|
+
module DoStuff
|
5
|
+
module Standalone
|
6
|
+
extend self
|
7
|
+
|
8
|
+
RUBY_BIN = if File.executable? '/usr/bin/ruby'
|
9
|
+
'/usr/bin/ruby'
|
10
|
+
else
|
11
|
+
require 'rbconfig'
|
12
|
+
File.join RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name']
|
13
|
+
end
|
14
|
+
|
15
|
+
PREAMBLE = <<-preamble
|
16
|
+
#!#{RUBY_BIN}
|
17
|
+
#
|
18
|
+
# This file is generated code.
|
19
|
+
# Please DO NOT EDIT or send patches for it.
|
20
|
+
#
|
21
|
+
# Please take a look at the source from
|
22
|
+
# https://github.com/tsion/do_stuff
|
23
|
+
# and submit patches against the individual files
|
24
|
+
# that build do_stuff.
|
25
|
+
#
|
26
|
+
|
27
|
+
preamble
|
28
|
+
|
29
|
+
POSTAMBLE = "DoStuff::Runner.execute(*ARGV)\n"
|
30
|
+
__DIR__ = File.dirname(__FILE__)
|
31
|
+
|
32
|
+
def save(filename)
|
33
|
+
target = File.expand_path(filename)
|
34
|
+
File.open(target, 'w') do |f|
|
35
|
+
f.puts build
|
36
|
+
f.chmod 0755
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def build
|
41
|
+
root = File.dirname(__FILE__)
|
42
|
+
|
43
|
+
standalone = ''
|
44
|
+
standalone << PREAMBLE
|
45
|
+
|
46
|
+
files = Dir["#{root}/*.rb"].sort - [__FILE__]
|
47
|
+
|
48
|
+
files.each do |file|
|
49
|
+
File.readlines(file).each do |line|
|
50
|
+
standalone << line
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
standalone << POSTAMBLE
|
55
|
+
standalone
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/do_stuff/todolist.rb
CHANGED
@@ -1,71 +1,73 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
module DoStuff
|
2
|
+
class TodoList
|
3
|
+
def initialize(file)
|
4
|
+
@file = file
|
5
|
+
parse
|
6
|
+
end
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
def add(task)
|
9
|
+
# Try to fill a hole in the task list, otherwise append to the end.
|
10
|
+
i = @tasks.find_index(nil)
|
11
|
+
i ||= @tasks.length
|
11
12
|
|
12
|
-
|
13
|
+
@tasks[i] = task
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
# Return the task number
|
16
|
+
i + 1
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
def erase(task_num)
|
20
|
+
raise "No such task ##{task_num}." unless @tasks[task_num - 1]
|
21
|
+
@tasks[task_num - 1] = nil
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
def get(task_num)
|
25
|
+
@tasks[task_num - 1]
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
def tasks
|
29
|
+
# Group each task with its number and remove all nils
|
30
|
+
@tasks.map.with_index{|task, i| [i + 1, task] if task }.compact
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
def write!
|
34
|
+
File.open(@file, 'w') do |f|
|
35
|
+
tasks.each{|num, task| f.puts("#{num}. #{task}") }
|
36
|
+
end
|
35
37
|
end
|
36
|
-
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
def self.edit(file)
|
40
|
+
# TODO: Use task_num to jump to a line
|
41
|
+
system(ENV['EDITOR'], file)
|
42
|
+
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
class ParseError < StandardError
|
45
|
+
attr_accessor :file
|
46
|
+
def initialize(file, msg)
|
47
|
+
@file = file
|
48
|
+
super(msg)
|
49
|
+
end
|
48
50
|
end
|
49
|
-
end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
52
|
+
private
|
53
|
+
def parse
|
54
|
+
@tasks = []
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
File.read(@file).each_line do |line|
|
57
|
+
line.chomp!
|
58
|
+
if line =~ /^(\d+)\.\s+(.+)$/
|
59
|
+
task_num, task = $1.to_i, $2
|
60
|
+
i = task_num - 1
|
60
61
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
if @tasks[i]
|
63
|
+
raise ParseError.new(@file, "Two definitions for task " +
|
64
|
+
"#{task_num}:\n\t#{task_num}. #{@tasks[i]}\n\t#{line}")
|
65
|
+
end
|
65
66
|
|
66
|
-
|
67
|
-
|
68
|
-
|
67
|
+
@tasks[i] = task
|
68
|
+
else
|
69
|
+
raise ParseError.new(@file, "Ill-formed line encountered:\n\t#{line}")
|
70
|
+
end
|
69
71
|
end
|
70
72
|
end
|
71
73
|
end
|
data/lib/do_stuff.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: do_stuff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-23 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A minimalistic command-line todo list
|
15
15
|
email: scott@scott-olson.org
|
@@ -18,6 +18,8 @@ executables:
|
|
18
18
|
extensions: []
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
|
+
- lib/do_stuff/standalone.rb
|
22
|
+
- lib/do_stuff/runner.rb
|
21
23
|
- lib/do_stuff/todolist.rb
|
22
24
|
- lib/do_stuff.rb
|
23
25
|
- bin/do_stuff
|