Compare commits

...

13 Commits

8 changed files with 70 additions and 31 deletions

View File

@ -11,12 +11,14 @@ release:
test:
crystal spec
deps:
crystal deps install
shards install
deps_update:
crystal deps update
shards update
deps_opt:
@[ -d lib/ ] || make deps
doc:
crystal docs
clean:
rm $(NAME)
.PHONY: all run build release test deps deps_update doc
.PHONY: all run build release test deps deps_update clean doc

View File

@ -1,3 +1,5 @@
**Migrated to <https://git.sceptique.eu/Sceptique/todo>**
# todo
track your todo lists in your terminal
@ -6,7 +8,7 @@ track your todo lists in your terminal
### Requirements
- crystal (see the shards.yml file)
- crystal (see the shards.yml file) (tested with v0.27.0)
- shards
### Build
@ -41,7 +43,9 @@ There are several type of date format which are parsed automatically:
## Configuration
### Hooks
You can set some hooks, which will be executed. Write a yaml file ~/.config/todorc with the following structure:
I you want someting to get executed right after or before an operation,
you can setup some hooks.
Write a yaml file `~/.config/todorc` with the following structure:
```yaml
hooks:
@ -65,6 +69,17 @@ hooks:
after_save:
```
Each hooks can take several parameters:
- `mode`: current operation
- `date`: date of the task
- `id`: id of the task
- `list_name`: name of the list of task
- `dir_name`: directory where the task is registered
- `msg`: body on the task
- `sort`: type of sort (date, id, ...)
## Development
TODO: Write development instructions here

View File

@ -1,5 +1,5 @@
name: todo
version: 0.2.1
version: 1.0.1
authors:
- Arthur Poulet <arthur.poulet@mailoo.org>
@ -8,6 +8,6 @@ targets:
todo:
main: src/todo.cr
crystal: 0.20.5
crystal: 0.24.2
license: GPL-3.0

View File

@ -24,6 +24,7 @@ parsed = OptionParser.parse! do |p|
p.on("-s", "--sort", "Sort by date (by default)") { sort = :date }
p.on("-i", "--sort-id", "Sort by id") { sort = :id }
p.on("-v", "--version", "Show version") { puts "Todo v#{Todo::VERSION}"; exit }
p.on("-h", "--help", "Show this help") { puts p; exit }
end
Dir.mkdir_p(dir_name)

View File

@ -1,5 +1,4 @@
require "yaml"
require "yaml"
class Todo::Config
FILE_PATH = File.expand_path ".config/todorc", ENV["HOME"]
@ -17,13 +16,19 @@ class Todo::Config
Config.from_yaml("{}")
end
def exec(hook_name : String)
def exec(hook_name : String, *args)
hooks = self.hooks
unless hooks.nil?
current = hooks[hook_name]?
unless current.nil?
current.each { |hook| d = `#{hook}`.strip; puts d unless d.empty? }
end
current = (hooks[hook_name]?)
exec_hooks(current, *args) unless (current.nil?)
end
end
private def exec_hooks(hooks : Array(String), *args)
hooks.each do |hook|
args_str = args.map { |e| "#{e.to_s.inspect}" }.join(" ")
d = `#{hook} #{args_str}`.strip
puts d unless d.empty?
end
end
end

View File

@ -1,35 +1,49 @@
require "colorize"
require "./todo"
require "./task"
require "./list"
require "./config"
module Todo::Exec
extend self
private def copy_task(task, list_to, dir_name)
list = List.load(list_to, dir_name)
list << task
list.save(list_to, dir_name)
end
# :nodoc:
# calls config.exec with the arguments
private macro config_exec(config_to_exec)
config.exec {{config_to_exec}}, mode, date, id, list_name, dir_name, msg, sort
end
def run(mode, date, id, list_name, dir_name, msg, sort)
config = Config.new
# new list
config.exec "before_load"
# Prepare the list
config_exec "before_load"
list = List.load(list_name, dir_name)
config.exec "after_load"
config_exec "after_load"
config.exec "before_#{mode}"
# effect
config_exec "before_#{mode}"
# Execute the operation
case mode
when :add
todo = ::Todo::Todo.new(msg, date)
todo = ::Todo::Task.new(msg, date)
list << todo
puts "ADD [#{list.size - 1}] #{todo.date} #{todo.msg}"
when :list
display = [] of Array(String)
list.each_with_index { |todo, idx| display << [todo.date, "#{idx.to_s.rjust(4, ' ').colorize.yellow} | #{todo.date.rjust(12, ' ').colorize.white.mode(:dim).to_s} | #{todo.msg}"] }
list.each_with_index do |todo, idx|
p_id = idx.to_s.rjust(4, ' ').colorize.yellow
p_date_time = Time.parse_local(todo.date, ::Todo::Task::DATE_FORMAT) rescue nil
p_date_red = p_date_time && p_date_time < Time.now
p_date = todo.date.rjust(12, ' ').colorize.fore(p_date_red ? :red : :white).mode(p_date_red ? :bright : :dim).to_s
display << [todo.date, "#{p_id} | #{p_date} | #{todo.msg}"]
end
display.sort_by! { |e| e[0] } if sort == :date
max_msg_len = list.reduce(7) { |l, r| [l, r.msg.size].max }
max_msg_len = [list.reduce(7) { |l, r| [l, r.msg.size].max }, 58].min
puts " id | date | message"
puts "---- | ------------ | #{"-" * max_msg_len} "
puts display.map { |e| e[1] }.join("\n")
@ -52,10 +66,11 @@ module Todo::Exec
else
puts "Error"
end
config.exec "after_#{mode}"
config_exec "after_#{mode}"
config.exec "before_save"
# Save the operation
config_exec "before_save"
list.save(list_name, dir_name)
config.exec "after_save"
config_exec "after_save"
end
end

View File

@ -1,5 +1,5 @@
require "yaml"
require "./todo"
require "./task"
class Todo::List
def self.load(path : String)
@ -14,7 +14,7 @@ class Todo::List
property name
YAML.mapping(
todos: {type: Array(Todo), setter: false, nilable: false},
todos: {type: Array(Todo::Task), setter: false, nilable: false},
)
def save(list_name : String, dir_name : String)
@ -26,7 +26,7 @@ class Todo::List
self
end
def <<(todo : Todo)
def <<(todo : Todo::Task)
self.todos << todo
end

View File

@ -1,12 +1,13 @@
require "yaml"
class Todo::Todo
class Todo::Task
YAML.mapping(
msg: {type: String},
date: {type: String, setter: false},
)
DATE_SEP = "(?:[/\-])"
DATE_FORMAT = "%y/%m/%d"
DATE_SEP = "(?:[/\-])"
# DATE_MATCH_1 = Regex.new "(?:(\d+)#{DATE_SEP})?(?:(\d+)#{DATE_SEP})(?:(\d+))"
DATE_MATCH_1 = /^(?:(\d+)#{DATE_SEP})?(\d+)#{DATE_SEP}(\d+)$/
DATE_MATCH_2 = /^d\+(\d+)$/i
@ -18,7 +19,7 @@ class Todo::Todo
year = (m[1]? || Time.now.year - 2000).to_i
"#{year}/#{m[2]}/#{m[3]}"
elsif m = value.match DATE_MATCH_2
(Time.now + m[1].to_i.days).to_s("%y/%m/%d")
(Time.now + m[1].to_i.days).to_s(DATE_FORMAT)
else
STDERR.puts "[WARN] \"#{value}\" is not a valid date"
value