Open zachriggle opened 2 years ago
Just to check, are you aware of https://github.com/dandavison/delta, which is similar to bat
but has much deeper git diff
integration ? :) or is the idea that given a line number, you want to see the enclosing scope context, and git
is just an example, such that bat
still feels like a better fit?
delta
doesn't actually have integration for this -- it's still parsing a standard git diff
and all the magic is in git
.
I'd like to see the feature in bat
❤️
Understood, thanks for the clarification. If/when we decide to do this, it will require a fair amount of work - currently, bat
doesn't know anything about the text it colors - it simply passes the line of text, a "context" (i.e. "this line is inside a block comment started previously") and a color scheme to a highlighter function and gets a series of string slices with color details. To implement this, bat
would need to receive and keep track of tokens and their "scopes" and remember positions of indexed symbols etc to know which is the closest prior function / class definition etc.
Edit to add: this would then match how Sublime Merge does it.
--line-range
was brought up in initial message, I would like add observation here. I am missing a context input for bat
that relates to highlight or line range inputs, like -C
in grep
.
With current implementation of --line-range
, it's like: we have lines before, we have lines after... but no way to select before/after simultaneously without additional calculations.
bat -H 123 --line-range 123:+10
worksbat -H 123 --line-range 123:-10
worksbat -H 123 --line-range -10:123:+10
nopebat -H 123 --line-range 123:+-10
nopeno way to select before/after simultaneously without additional calculations.
That doesn't seem like too much added headache over what bat
already suppports:
bat -H 123 --line-range $(( 123 - 10 )):$(( 123 + 10 ))
Or save the "anchor line" and optionally a context window as variables and then just reference them:
function bat_highlight_context() {
local file="${1:?}"
local line="${2:?}"
local context_size="${3:-10}"
local line_range="$(( $line - $context_size )):$(( $line + $context_size ))"
bat $file -H $line --line-range $line_range
}
bat_highlight_context foo.sh 123
Bat is great! Hopefully my sponsorship helps pay for 🍺 money!
Background
When using
bat
in many of my workflows, I make use of the--highlight-line
flag to highlight specific lines.Currently, I rely on
git
to display--function-context
to get the bounds of the enclosing scope. This works well, but relies on very fragile and error-prone regular expressions.For example, try
git grep -b -W memcpy
orgit log -b -p -W memcpy
inside a random C\C++ project. Neat output, but no syntax highlighting!I have some plumbing that parses Git's output and passes it to e.g.
bat -H 123 -r 100:150
flags on the command line -- but this is hacky, error-prone, displays too much information due to Git's implementation. (from matching line, search backward for a function/class signature, then search forward for the next one -- and display all lines). All of this plumbing is written in Zsh and it's a hack that I don't feel comfortable sharing.Feature
It would be nice if
bat
had similar functionality to show the enclosing scope (ObjC block, ObjC selector, function, method, class, namespace) based on where the highlighted line(s) are.Since
bat
pardoes syntax highlighting, I expect there is some way to get the enclosing scope in a much more reliable fashion.This would also remove the need to pass
-r
inbat -H 123 -r 100:150
-- with this feature you might instead passbat -W 123
orbat --function-context 123
.Implementation Suggestions
Since scopes may be nested (namespace → class / implementation → selector → block → block → block → conditional → loop) it may not be easy to discern how many scopes to go outward. I suggest having the containing function / method / selector implementation as the default. If the highlighted line is an e.g. struct or interface / declaration / definition / implementation, the entire struct or class definition should be shown.
If the highlighted line is a global or otherwise only contained by a namespace (global or named), only that line should be shown -- though perhaps there should be an option to toggle this (to show the whole file for globals, or the whole namespace if enclosed).
For additional scopes that are not displayed (e.g. if we are showing a line inside a method, but the method is declared within a class definition, which is itself inside a named scope) it might be useful to show the lines which constitute the namespace / class / struct name.
The way that
git
handles--function-context
with global variables is just to show everything before the line until a function signature is found, and everything after until a function signature is found. This results in way too much being displayed, and in many cases the entire file is shown.