Compare commits

...

2 commits

3 changed files with 119 additions and 32 deletions

View file

@ -4,8 +4,18 @@ mkdir -p "$(git rev-parse --git-dir)/fzf"
history="$(git rev-parse --git-dir)/fzf/history" history="$(git rev-parse --git-dir)/fzf/history"
null=$(printf "\0") null=$(printf "\0")
untracked='/^?? /d'
while test $# != 0
do
case "$1" in
(--untracked | -u) untracked="" ;;
esac
shift
done
IFS='' IFS=''
git status --porcelain | while read line git status --porcelain | sed "$untracked" | while read line
do do
path=$(echo $line | cut -b 4-) path=$(echo $line | cut -b 4-)
type=$(echo $line | cut -b -3) type=$(echo $line | cut -b -3)

View file

@ -3,65 +3,142 @@
local json = require "cjson" local json = require "cjson"
local arrr = require "arrr" local arrr = require "arrr"
local shapeshift = require "shapeshift" local shapeshift = require "shapeshift"
local lumber = require("lumber")
local log = lumber.new {
level = lumber.levels.WARN;
format = require "lumber.format.term";
filter = function(message)
if type(message) == "string" then
return message
else
return require("inspect")(message)
end
end
}
local default_config = {
{ notify = "zenity", minutes = 60 };
{ notify = "notify", minutes = 180 };
}
local function zulu_offset() local function zulu_offset()
local current = os.date("*t") local current = os.date("*t")
current.isdst = false current.isdst = false
local zulu = os.date("!*t") local zulu = os.date("!*t")
--- @cast zulu -string
--- @cast current -string
return os.difftime(os.time(current), os.time(zulu)) return os.difftime(os.time(current), os.time(zulu))
end end
local config_file do
local xdg_home = os.getenv("XDG_CONFIG_HOME")
local home = os.getenv("HOME")
if xdg_home then
config_file = xdg_home .. "/task/tasknotif.lua"
elseif home then
config_file = home .. "/.config/task/tasknotif.lua"
else
config_file = "tasknotif.lua"
end
end
local params do local params do
local parse = arrr { local parse = arrr {
{ "Time or something", "--minutes", "-m", "number" }; { "Configuration to use (default: "..config_file..")", "--config", "-c" };
{ "Use Zenity to display a window instead of sending a notification", "--zenity", "-z" } { "Sets the log level", "--log", nil, true };
{ "Ignore anything that's already due soon at program start", "--pre-check" };
} }
local validate = shapeshift.table { local validate = shapeshift.table {
__extra = "keep"; __extra = "keep";
minutes = shapeshift.default(30, shapeshift.is.number); precheck = shapeshift.default(false, shapeshift.is.boolean);
} }
params = select(2, validate(parse(arg))) params = select(2, validate(parse(arg)))
end end
if params.log then
log.level = lumber.levels[string.upper(params.log)]
end
log:debug("Params", params)
log:info "Starting taskwarrior notifier"
--- @type table
local config if params.config then
config = assert(loadfile(params.config))()
else
local chunk = loadfile(config_file)
config = chunk and chunk() or default_config
end
local done = {} local done = {}
for severity in ipairs(config) do
done[severity] = {}
end
while true do --- @param run boolean Whether there should be any notification at all
local data = json.decode(io.popen("task export"):read("*a")) local function check(run)
for _, task in ipairs(data) do -- Save handled tasks in the current loop so the same task doesn't get several notififations at once
if task.status == "pending" and task.due then local handled = {}
do if run == nil then run = true end
local d = {} for severity, condition in ipairs(config) do
d.year, d.month, d.day, d.hour, d.min, d.sec log:debug(condition)
= task.due:match("(%d%d%d%d)(%d%d)(%d%d)T(%d%d)(%d%d)(%d%d)Z") local data = json.decode(io.popen("task export"):read("*a"))
d.sec = d.sec + zulu_offset() for _, task in ipairs(data) do
task.due = os.time(d) if task.status == "pending" and task.due then
end do
local d = {}
-- If anything gets postponed outside of the warning time, d.year, d.month, d.day, d.hour, d.min, d.sec
-- remove it from the done list = task.due:match("(%d%d%d%d)(%d%d)(%d%d)T(%d%d)(%d%d)(%d%d)Z")
if done[task.uuid] then d.sec = d.sec + zulu_offset()
if os.difftime(task.due, os.time()) > 60*params.minutes then task.due = os.time(d)
done[task.uuid] = nil
end end
end
if os.difftime(task.due, os.time()) < 60*params.minutes then -- If anything gets postponed outside of the warning time,
if not done[task.uuid] then -- remove it from the done list
done[task.uuid] = task if done[severity][task.uuid] then
print("Notifying:", task.uuid, task.description) if os.difftime(task.due, os.time()) > 60 * condition.minutes then
if params.zenity then done[severity][task.uuid] = nil
os.execute(string.format("zenity --warning --title '%s' --text '%s'", "Task due soon", task.description)) end
else end
os.execute("notify-send 'Task due soon' '"..task.description:gsub([[']], [['"'"']]).."'")
if os.difftime(task.due, os.time()) < 60 * condition.minutes then
if handled[task.uuid] then
log:info("Skipping task "..task.uuid..": already handled in this loop")
end
if not done[severity][task.uuid] then
done[severity][task.uuid] = task
if run and not handled[task.uuid] then
log:info("Notifying:", task.uuid, task.description)
if condition.notify == "zenity" then
os.execute(string.format("zenity --warning --title '%s' --text '%s'", "Task due soon", task.description))
elseif condition.notify == "notify" then
os.execute("notify-send 'Task due soon' '"..task.description:gsub([[']], [['"'"']]).."'")
else
error("Unknown notification type: " .. tostring(condition.notify))
end
handled[task.uuid] = task
end
end end
end end
end end
end end
end end
end
if not os.execute("sleep 5") then if params.precheck then
log:info "Doing initial pre-scan"
check(false)
end
log:info "Starting scan loop"
while true do
check(true)
if not os.execute("sleep 30") then
log:info "Exiting taskwarrior notifier"
os.exit() os.exit()
end end
end end

View file

@ -22,7 +22,7 @@
dog = log --decorate --oneline --graph --date-order dog = log --decorate --oneline --graph --date-order
fadd = "! git pick | xargs --open-tty git add" fadd = "! git pick | xargs --open-tty git add"
fig = "! git pick | xargs -L1 git ignore" fig = "! git pick | xargs -L1 git ignore"
faddall = "! git status --porcelain | cut -b 4- | fzf --multi --layout=reverse-list | xargs --open-tty git add" faddall = "! git pick --untracked | xargs --open-tty git add"
fixup = "!git commit --patch --no-edit --amend $(git diff --name-only HEAD~1..HEAD)" fixup = "!git commit --patch --no-edit --amend $(git diff --name-only HEAD~1..HEAD)"
h = log -1 --format=%h h = log -1 --format=%h
hash = log -1 --format=%H hash = log -1 --format=%H