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