Skip to content

Commit

Permalink
feat: display timestamp in Telescope results
Browse files Browse the repository at this point in the history
Annotate each session with a timestamp from stat(2) and use it when
displaying Telescope results.

Also, move the timestamp cache from local table in `sort_by` to session
object.
  • Loading branch information
gzbd committed Aug 7, 2024
1 parent b0a2b4c commit 6cc0264
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 16 deletions.
49 changes: 34 additions & 15 deletions lua/possession/query.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,33 @@ function M.filter_by(sessions, opts)
end, sessions)
end

--- Gets file timestmap
---@param file string a file path
---@param key possession.QuerySortKey key to sort by: name, stat(2) timestamps
local get_time = function(file, key)
local stat = vim.loop.fs_stat(file)
if not stat then
return 0
end
local t = stat[key]
-- use millis to fit in Lua's max float "integer precision" of 53 bits
return math.floor(t.sec * 1000 + t.nsec / 1000000)
end

--- Annotates each session object in list with timestamp
---@param sessions table[] list of sessions from `as_list`
---@param key possession.QuerySortKey key to sort by: name, stat(2) timestamps
function M.annotate_with_timestamp(sessions, key)
if not vim.tbl_contains({ 'atime', 'mtime', 'ctime' }, key) then
return
end

for _, s in ipairs(sessions) do
local ts = get_time(s.file, key)
s[key] = ts
end
end

---@alias possession.QuerySortKey 'name'|'atime'|'mtime'|'ctime'

--- Sort a list of sessions in-place
Expand All @@ -44,25 +71,17 @@ function M.sort_by(sessions, key, descending)
return s.name
end
elseif vim.tbl_contains({ 'atime', 'mtime', 'ctime' }, key) then
local get_time = function(file)
local stat = vim.loop.fs_stat(file)
if not stat then
return 0
end
local t = stat[key]
-- use millis to fit in Lua's max float "integer precision" of 53 bits
return math.floor(t.sec * 1000 + t.nsec / 1000000)
end
-- cache filesystem access
local times = {}
get_key = function(s)
if not s.file then
return 0
elseif times[s.file] then
return times[s.file]
elseif s[key] then
-- If session is annotated with timestamp use it
return s[key]
end
local t = get_time(s.file)
times[s.file] = t

local t = get_time(s.file, key)
-- Cache timestamp in session object
s[key] = t
return t
end
end
Expand Down
41 changes: 40 additions & 1 deletion lua/possession/telescope.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ local finders = require('telescope.finders')
local pickers = require('telescope.pickers')
local previewers = require('telescope.previewers')
local transform_mod = require('telescope.actions.mt').transform_mod
local entry_display = require('telescope.pickers.entry_display')

local config = require('possession.config')
local session = require('possession.session')
local display = require('possession.display')
local query = require('possession.query')
local utils = require('possession.utils')

local CURRENT_YEAR = os.date('%Y')

local function session_previewer(opts)
return previewers.new_buffer_previewer {
title = 'Session Preview',
Expand Down Expand Up @@ -64,6 +67,7 @@ local session_actions = {
---@field default_action? 'load'|'save'|'delete'
---@field sessions? table[] list of sessions like returned by query.as_list
---@field sort? boolean|possession.QuerySortKey sort the initial sessions list, `true` means 'mtime'
---@field ts_annotation? possession.QuerySortKey annotate telescope results with timestamp
---@field only_cwd? boolean only display sessions for the cwd

---@param opts possession.TelescopeListOpts
Expand All @@ -72,6 +76,7 @@ function M.list(opts)
default_action = 'load',
sessions = nil,
sort = 'mtime',
ts_annotation = 'mtime',
only_cwd = false,
}, opts or {})

Expand All @@ -86,17 +91,51 @@ function M.list(opts)
sessions = query.filter_by(sessions, { cwd = vim.fn.getcwd() })
end

if opts.ts_annotation then
query.annotate_with_timestamp(sessions, opts.ts_annotation)
end

if opts.sort then
local key = opts.sort == true and 'name' or opts.sort
local descending = key ~= 'name'
query.sort_by(sessions, key, descending)
end

return finders.new_table {
results = sessions,
entry_maker = function(entry)
local make_display = entry.name

if opts.ts_annotation then
local displayer = entry_display.create {
separator = ' ',
items = {
{ width = nil },
{ remaining = true },
},
}

make_display = function(e)
local ts_sec = e.value[opts.ts_annotation] / 1000
local format
if CURRENT_YEAR ~= os.date('%Y', ts_sec) then
format = '%b %d %Y'
else
format = '%b %d %H:%M'
end

local mtime_part = os.date(format, ts_sec)

return displayer {
{ mtime_part, 'TelescopeResultsField' },
e.value.name,
}
end
end

return {
value = entry,
display = entry.name,
display = make_display,
ordinal = entry.name,
}
end,
Expand Down

0 comments on commit 6cc0264

Please sign in to comment.