Skip to content

Commit

Permalink
add ability to show/hide notifiers dynamically (#5)
Browse files Browse the repository at this point in the history
* add ability to show/hide notifiers dynamically

* clean up
  • Loading branch information
epwalsh authored Dec 1, 2023
1 parent dde2cbd commit 3b7721c
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 23 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

- Added `pomo.get_all_timers()` function.
- Added `sticky` option to "Default" notifier.
- Added ability to show/hide a timer's notifiers, if they support that, via the commands and functions:
- `:TimerShow` / `pomo.show_timer()`
- `:TimerHide` / `pomo.hide_timer()`
- Made the "Default" timer hide-able, which has the same affect as the `sticky` option.

### Changed

- `pomo.start_timer(...)` now returns a `pomo.Timer` instead of an integer timer ID.
- `pomo.stop_timer(...)` now takes a `pomo.Timer` or an integer timer ID.

## [v0.3.0](https://github.com/epwalsh/pomo.nvim/releases/tag/v0.3.0) - 2023-11-30

Expand Down
61 changes: 46 additions & 15 deletions lua/pomo/commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,36 @@ local util = require "pomo.util"

local M = {}

---@param arg string
---@return pomo.Timer|?
local function get_timer_from_arg(arg)
---@type pomo.Timer|?
local timer
if string.len(arg) > 0 then
local timer_id = tonumber(arg)
if timer_id == nil then
log.error("invalid timer ID: '%s'", arg)
return
end

timer = pomo.get_timer(timer_id)
if not timer then
log.error("timer #%d is not active", timer_id)
return
else
return timer
end
else
timer = pomo.get_latest()
if not timer then
log.error "there are no active timers"
return
else
return timer
end
end
end

M.register_commands = function()
vim.api.nvim_create_user_command("TimerStart", function(data)
if data.fargs == nil or #data.fargs == 0 or #data.fargs > 2 then
Expand All @@ -21,21 +51,8 @@ M.register_commands = function()
end, { nargs = "+" })

vim.api.nvim_create_user_command("TimerStop", function(data)
---@type integer|?
local timer_id
if string.len(data.args) > 0 then
timer_id = tonumber(data.args)

if timer_id == nil then
return log.error("invalid timer ID: '%s'", data.args)
elseif not pomo.get_timer(timer_id) then
return log.error("timer #%d is not active", timer_id)
end
elseif pomo.num_active_timers() == 0 then
return log.error "there are no active timers"
end

if not pomo.stop_timer(timer_id) then
local timer = get_timer_from_arg(data.args)
if timer and not pomo.stop_timer(timer) then
return log.error "failed to stop timer"
end
end, { nargs = "?" })
Expand All @@ -59,6 +76,20 @@ M.register_commands = function()

pomo.start_timer(time_limit, name, repititions)
end, { nargs = "+" })

vim.api.nvim_create_user_command("TimerHide", function(data)
local timer = get_timer_from_arg(data.args)
if timer then
pomo.hide_timer(timer)
end
end, { nargs = "?" })

vim.api.nvim_create_user_command("TimerShow", function(data)
local timer = get_timer_from_arg(data.args)
if timer then
pomo.show_timer(timer)
end
end, { nargs = "?" })
end

return M
56 changes: 49 additions & 7 deletions lua/pomo/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ end
---@param name string|? A name for the timer. Does not have to be unique.
---@param repeat_n integer|? The number of the times to repeat the timer.
---@param cfg pomo.Config|? Override the config.
---@return integer timer_id The ID of the timer created.
---@return pomo.Timer timer
M.start_timer = function(time_limit, name, repeat_n, cfg)
cfg = cfg and cfg or M.get_config()
local timer_id = timers:first_available_id()
Expand All @@ -30,19 +30,61 @@ M.start_timer = function(time_limit, name, repeat_n, cfg)
timers:remove(t)
end)

return timer_id
return timer
end

---Stop a timer. If no ID is given, the latest timer is stopped.
---@param timer_id integer|?
---Stop a timer. If no timer or ID is given, the latest timer is stopped.
---@param timer integer|pomo.Timer|?
---@return boolean success If the timer was stopped.
M.stop_timer = function(timer_id)
local timer = timers:pop(timer_id)
if timer ~= nil then
M.stop_timer = function(timer)
if type(timer) ~= "table" then
timer = timers:pop(timer) ---@diagnostic disable-line: param-type-mismatch
end
if not timer then
return false
else
timer:stop()
return true
end
end

---@param timer integer|pomo.Timer|?
---@return pomo.Timer|?
local function get_or_latest(timer)
if timer == nil then
return M.get_latest()
elseif type(timer) == "number" then
return M.get(timer)
elseif type(timer) == "table" then
return timer
else
error("unexpected type for 'timer' parameter '" .. type(timer) .. "'")
end
end

---Hide a timer's notifiers (if they support that). If no timer ID is given, the latest timer is used.
---@param timer integer|pomo.Timer|?
---@return boolean success
M.hide_timer = function(timer)
timer = get_or_latest(timer)
if not timer then
return false
else
timer:hide()
return true
end
end

---Show a timer's notifiers (if they support that). If no timer or ID is given, the latest timer is used.
---@param timer integer|pomo.Timer?
---@return boolean success
M.show_timer = function(timer)
timer = get_or_latest(timer)
if not timer then
return false
else
timer:show()
return true
end
end

Expand Down
34 changes: 33 additions & 1 deletion lua/pomo/notifier.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ M.NotifierType = NotifierType

---The abstract base class for notifiers. At a minimum each concrete implementation needs to provide
---the methods `self:tick()`, `self:start()`, `self:done()`, and `self:stop()`.
---Optionally they can also provide `self:hide()` and `self:show()` methods.
---See `pomo.DefaultNotifier` for an example.
---@class pomo.Notifier
local Notifier = {}
Expand All @@ -38,6 +39,12 @@ Notifier.stop = function(self) ---@diagnostic disable-line: unused-local
error "not implemented"
end

---Called to hide the timer's progress. Should have the opposite affect as `show()`.
Notifier.hide = function(self) end ---@diagnostic disable-line: unused-local

---Called to show the timer's progress. Should have the opposite affect as `hide()`.
Notifier.show = function(self) end ---@diagnostic disable-line: unused-local

---The default implementation of `pomo.Notifier`, uses `vim.notify` to display the timer.
---@class pomo.DefaultNotifier : pomo.Notifier
---@field timer pomo.Timer
Expand All @@ -46,6 +53,7 @@ end
---@field title_icon string
---@field text_icon string
---@field sticky boolean
---@field _last_text string|?
local DefaultNotifier = {}
M.DefaultNotifier = DefaultNotifier

Expand All @@ -60,10 +68,11 @@ DefaultNotifier.new = function(timer, opts)
self.title_icon = self.opts.title_icon and self.opts.title_icon or "󱎫"
self.text_icon = self.opts.text_icon and self.opts.text_icon or "󰄉"
self.sticky = self.opts.sticky ~= false
self._last_text = nil
return self
end

---@param text string
---@param text string|?
---@param level string|integer
---@param timeout boolean|integer
DefaultNotifier._update = function(self, text, level, timeout)
Expand All @@ -86,6 +95,16 @@ DefaultNotifier._update = function(self, text, level, timeout)
title = string.format("Timer #%d, %s%s", self.timer.id, util.format_time(self.timer.time_limit), repetitions_str)
end

if text ~= nil then
self._last_text = text
elseif not self._last_text then
return
else
text = self._last_text
end

assert(text)

self.notification = vim.notify(text, level, {
icon = self.title_icon,
title = title,
Expand Down Expand Up @@ -119,6 +138,19 @@ DefaultNotifier.stop = function(self)
self:_update(string.format(" %s stopping...", self.text_icon), "info", 1000)
end

DefaultNotifier.hide = function(self)
self:_update(nil, "info", 100)
self.sticky = false
end

DefaultNotifier.show = function(self)
self.sticky = true
local time_left = self.timer:time_remaining()
if time_left ~= nil and time_left > 0 then
self:tick(time_left)
end
end

---A `pomo.Notifier` that sends a system notification when the timer is finished.
---@class pomo.SystemNotifier : pomo.Notifier
---@field timer pomo.Timer
Expand Down
18 changes: 18 additions & 0 deletions lua/pomo/timer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,24 @@ Timer.stop = function(self)
end
end

---Hide the timer's notifiers, if they support that.
Timer.hide = function(self)
for _, noti in ipairs(self.notifiers) do
if noti.hide ~= nil then
noti:hide()
end
end
end

---Show the timer's notifiers, if they support that.
Timer.show = function(self)
for _, noti in ipairs(self.notifiers) do
if noti.show ~= nil then
noti:show()
end
end
end

---This is a class definition for the timer in `vim.loop` to help my language server.
---@class uv_timer_t
---@field start function
Expand Down

0 comments on commit 3b7721c

Please sign in to comment.