mirror of
https://github.com/helix-editor/helix.git
synced 2025-04-06 20:37:44 +03:00
fix: use relative path when finding file style: cargo fmt _ chore: better error message refactor: rename to `blame_line` fix: use line of primary cursor for git blame feat: basic implementation of blocking Blame handler feat: implement basic virtual text (end of line blame) feat: figure out how to draw stuff at the end of lines feat: implement end of line virtual text for the current line feat: implement inline git blame chore: clean up chore: remove unused import _ chore: set `blame` to `false` by default docs: document `[editor.vcs.blame]` chore: add progress perf: use background task for worker _ chore: remove unnecessary panic!s chore: remove commented code refactor: remove some layers of abstraction refactor: remove nesting feat: [editor.vcs] -> [editor.version-control] fix: account for inserted and deleted lines _ refactor: extract into a `blame` module feat: allow using custom commit format feat: allow more customizability for inline blame test: add tests for custom inline commit parsser refactor: rename `blame` -> `blame_line` _ _ test: create helper macros for tests test: make test syntax more expressive. Allow specifying line numbers that just got added test: with interspersed lines feat: add `line_blame` static command _ test: add an extra test case test: add ability to have `delete`d lines test: fix on windows (?) test: `delete` test case test: add extra step to test case test: add documentation for macro refactor: use `hashmap!` macro refactor: collapse match arm fix: remove panic perf: update inline git blame every 150 milliseconds instead of on each command test: add attributes on blocks style: move function earlier in the file perf: cache blame results in a hashma chore: remove log statements chore: clean up. ALSO: removes checking for inline blame every N seconds. _ perf: use mspc instead of busy-wait docs: add information why we don't optimize the repo _ test: add back the commented out tests chore: comment out cfg(not(windows)) test: add extra history to blame test docs: remove incorrect static command _ test: disable test on windows feat: send inline blame event update when reloading or saving the document feat: rename `version-control` -> `inline-blame` feat: update theme key used for inline-blame chore: remove unused #![allow] chore: style: remove accidental formatting docs: remove incorrect key perf: Use a single `ThreadSafeRepository` instead of re-constructing it each time feat: add `inline_blame` static command bound to `space + B` style: revert formatting in keymap.md chore: do not compute blame for document when changing config option This isn't needed anymore because the inline-blame will be computed regardless if `inline_blame.enable` is set or not style: remove newline refactor: use `fold` instead of loop chore: clean up feat: log error forl line blame when it happens feat: improve message when we don't have the blame We know that we don't have it because we're still calculating it. feat: do not render inline blame for empty lines _ feat: do not show blame output when we are on a hunk that was added refactor: remove additional wrapper methods fix _ feat: more readable time for git blame chr feat: feat: improved error handling fix: path separator on Windows test: disable on windows refactor: move pretty date function formatter into `helix-stdx` perf: do not use a syscall on each render chore: add TODO comment to update gix version chore: use `gix::path` conversion from Path -> BString _ _ chore: do not update file blame on document save This is not needed because when we write the file, we don't make a new commit so the blame will not change. refactor: use statics to get time elapsed instead of editor state refactor: do not use custom event, use handler instead fix: do not spawn a new handler docs: correct examples for `editor.inline-blame.format` docs: correct static command name refactor: add comments, and improve variable names I didn't really understand this function when I made it. Was just copy-pasted from end of line diagnostics I wanted to know what this is actually doing, so I investigated and while doing this also added comments and improved names of variables so others can understand too fix: time in future is accounted for perf: inline some functions that are called in only 1 place, during a render loop perf: add option to disable requesting inline blame in the background fix: request blame again when document is reloaded chore: inline blame is disabled with request on demand feat: when requesting line blame with "blame on demand", show blame in status perf: use less allocations perf: less allocations in `format_relative_time` _ _ _ _ docs: correct name of command _ feat: improve error message _ feat: rename enum variants for inline blame behaviour docs: improve description of behaviour field
81 lines
2.7 KiB
Rust
81 lines
2.7 KiB
Rust
use std::time::{Instant, SystemTime};
|
|
|
|
use once_cell::sync::Lazy;
|
|
|
|
const SECOND: i64 = 1;
|
|
const MINUTE: i64 = 60 * SECOND;
|
|
const HOUR: i64 = 60 * MINUTE;
|
|
const DAY: i64 = 24 * HOUR;
|
|
const MONTH: i64 = 30 * DAY;
|
|
const YEAR: i64 = 365 * DAY;
|
|
|
|
/// Like `std::time::SystemTime::now()` but does not cause a syscall on every invocation.
|
|
///
|
|
/// There is just one syscall at the start of the program, subsequent invocations are
|
|
/// much cheaper and use the monotonic clock instead of trigerring a syscall.
|
|
#[inline]
|
|
fn now() -> SystemTime {
|
|
static START_INSTANT: Lazy<Instant> = Lazy::new(Instant::now);
|
|
static START_SYSTEM_TIME: Lazy<SystemTime> = Lazy::new(SystemTime::now);
|
|
|
|
*START_SYSTEM_TIME + START_INSTANT.elapsed()
|
|
}
|
|
|
|
/// Formats a timestamp into a human-readable relative time string.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `timestamp` - A point in history. Seconds since UNIX epoch (UTC)
|
|
/// * `timezone_offset` - Timezone offset in seconds
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// A String representing the relative time (e.g., "4 years ago", "11 months from now")
|
|
#[inline]
|
|
pub fn format_relative_time(timestamp: i64, timezone_offset: i32) -> String {
|
|
let timestamp = timestamp + timezone_offset as i64;
|
|
let now = now()
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
.unwrap_or_default()
|
|
.as_secs() as i64
|
|
+ timezone_offset as i64;
|
|
|
|
let time_passed = now - timestamp;
|
|
|
|
let time_difference = time_passed.abs();
|
|
|
|
let (value, unit) = if time_difference >= YEAR {
|
|
let years = time_difference / YEAR;
|
|
(years, if years == 1 { "year" } else { "years" })
|
|
} else if time_difference >= MONTH {
|
|
let months = time_difference / MONTH;
|
|
(months, if months == 1 { "month" } else { "months" })
|
|
} else if time_difference >= DAY {
|
|
let days = time_difference / DAY;
|
|
(days, if days == 1 { "day" } else { "days" })
|
|
} else if time_difference >= HOUR {
|
|
let hours = time_difference / HOUR;
|
|
(hours, if hours == 1 { "hour" } else { "hours" })
|
|
} else if time_difference >= MINUTE {
|
|
let minutes = time_difference / MINUTE;
|
|
(minutes, if minutes == 1 { "minute" } else { "minutes" })
|
|
} else {
|
|
let seconds = time_difference / SECOND;
|
|
(seconds, if seconds == 1 { "second" } else { "seconds" })
|
|
};
|
|
let value = value.to_string();
|
|
|
|
let label = if time_passed.is_positive() {
|
|
"ago"
|
|
} else {
|
|
"from now"
|
|
};
|
|
|
|
let mut relative_time = String::with_capacity(value.len() + 1 + unit.len() + 1 + label.len());
|
|
relative_time.push_str(&value);
|
|
relative_time.push(' ');
|
|
relative_time.push_str(unit);
|
|
relative_time.push(' ');
|
|
relative_time.push_str(label);
|
|
relative_time
|
|
}
|