-
-
Notifications
You must be signed in to change notification settings - Fork 6.3k
[RFC] Add a way to color command-line #6364
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
PR commits start with “ex_getln: Clean up draw_cmdline a bit”. |
Example code which will highlight using pygments: # color_cmdline.py
def color_cmdline_setup():
import vim
from pygments import lex, format
from pygments.lexers import get_lexer_by_name
from pygments.formatter import Formatter
from pygments.token import Token
try:
from __builtin__ import unicode
except ImportError:
unicode = str
COLORS = {
Token: 'Normal',
Token.Comment: 'Comment',
Token.Comment.Preproc: 'PreProc',
Token.Keyword: 'Keyword',
Token.Keyword.Type: 'Type',
Token.Operator: 'Operator',
Token.Name: 'Identifier',
Token.Name.Builtin: 'Statement',
Token.Name.Function: 'Function',
Token.Name.Constant: 'Number',
Token.String: 'String',
Token.Number: 'Number',
Token.Punctuation: 'Operator',
Token.Error: 'Error',
}
class NvimFormatter(Formatter):
def __init__(self, **kwargs):
super(NvimFormatter, self).__init__(**kwargs)
self.offset = 0
self.colorscheme = kwargs.get('colorscheme', None) or COLORS
def format_unencoded(self, tokensource, outfile):
for ttype, value in tokensource:
ttype_str = str(ttype).replace(' ', '_')
value = value.rstrip('\n')
color = self.colorscheme.get(ttype)
while color is None:
ttype = ttype[:-1]
color = self.colorscheme.get(ttype)
if isinstance(value, unicode):
vlen = len(value.encode('utf-8'))
else:
vlen = len(value)
if vlen:
outfile.write('{} {} {} {}\n'.format(
self.offset, self.offset + vlen, color, ttype_str))
self.offset += vlen
def setup():
global color_cmdline_highlight
lexer = get_lexer_by_name('vim')
def color_cmdline_highlight():
cmdline = vim.eval('a:cmdline')
add_tt = False
if bool(int(vim.eval('get(a:000, 0)'))):
add_tt = True
tokens = lex(cmdline, lexer)
fmt = format(tokens, NvimFormatter(bg=vim.options['background']))
return [
((lambda s, e, g, tt: (
(int(s), int(e), g)
+ ((tt,) if add_tt else ())
))(*line.split()))
for line in fmt.split('\n')[:-1]
]
setup()
color_cmdline_setup() pyfile <sfile>:h/color_cmdline.py
function PygmentsFormat(cmdline, ...)
return pyeval('color_cmdline_highlight()')
endfunction
let g:Nvim_color_cmdline = 'PygmentsFormat' |
it might be worthwhile to think of how this will interact with #6162 later. I guess GUIs can recieve a list of pairs |
:echo "«^ | | ||
]]) | ||
end) | ||
it('does the right thing when errorring', function() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: errorring -> erroring
8798c20
to
4c841ca
Compare
Actually it appears that |
I would guess the purpose is to nudge plugin authors to consider adding a prompt (instead of just calling Also, having user commands and |
@bfredl One of the points of the coloring is “better have no colors then make user problems”. People using that for other purposes should be prepared that Neovim may reject calling their callback if it causes troubles: shows errors, takes too long to finish, alters some state, explicitly disabled by the user, etc. In the PR I am only going to disable it for errors, arabic shaping (not sure how to implement and how to test) and probably for some option set, but that may be extended depending on the problems I spot. If you know an existing facility to automatically interrupt after some time passed I would implement “too long to finish” as well. |
This would be fine for other use cases as long as one still can
I don't know if |
Should speed up execution without arabic characters a bit, slowing down with arabic characters. More necessary, this allows coloring prompt without caring about arabic shaping at the first iteration.
Reason: should actually switch to using input() coloring because other coloring variants are eventually going away.
There are still some issues: specifically, new “pending” test hangs busted.
(Without the merge clint fails locally.) |
AppVeyor failure looks unrelated:
Travis hanged in oldtests, test49:
Restarting. |
My tentative observation is that the test49 hang seems to persist if travis cache is not cleared. |
@justinmk This is planned to be merged after dealing with more urgent issues for the next (0.2.1) release? |
@ZyX-I If you think it's ready, I think we should include it in 0.2.1 |
@@ -265,6 +273,8 @@ Lua interface (|if_lua.txt|): | |||
on cancel and completion respectively) via dictionary argument (replaces all | |||
other arguments if used). | |||
|
|||
|input()| and |inputdialog()| now support user-defined cmdline highlighting. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is only highlighting mentioned, in all of these docs? This is a handler that is called on each input character, correct? That's useful for much more than highlighting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bfredl asked this somewhere above: it is not guaranteed to be called, if real hooks cause any problems then I would rather add code which detects those problems and stops using hook then do anything. Currently this includes stopping calling the hook in case of arabic characters present. And handler is not called on each input character, it is called on redraw, minus cases when hook output can be taken from cache. I don’t have any information regarding what caused redraw, so one will have to compute a diff: hook always receives the whole drawn command-line. And whatever other uses you have in mind, note that hook is not supposed to edit input, :echo
anything or issue any errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though no, arabic characters fall under different category: “hard to implement, unlikely to happen and should really be solved on the different layer and not with some hacks in ex_getln.c and screen.c (it contains another incarnation of arabic shaping code)”. What falls into “causes problems” category now are hooks which throw errors.
@@ -4703,6 +4703,7 @@ input({opts}) | |||
cancelreturn "" Same as {cancelreturn} from | |||
|inputdialog()|. Also works with | |||
input(). | |||
highlight nothing Highlight handler: |Funcref|. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How often is the handler called? Should mention this somewhere.
Typically we prefix VimL handlers with on_
(Vim does _cb
suffix). Maybe this should be called on_input
. But this is not a passive event, it's more of a hook. So maybe it should be called hl_hook
(emacs has a similar foo-hook
convention).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on_input
is not right, it is currently called on redraw. And I do not like the hook or event view of the function, in my view it is more like a syntax definition, in a form of the VimL code: this allows things like caching in case of double highlight I implemented, additionally I don’t know command-line redrawing system enough to answer questions like “how many times and for which states highlight will be called when triggering a
mapping defined like cnoremap a bcd<C-\>e"efg"<CR>
” without experiments.
UI now supports command-line coloring. Officially only |input()| and | ||
|inputdialog()| may be colored, temporary for testing purposes expressions | ||
(e.g. |i_CTRL-R_=|) and regular command-line (|:|) are colored by callbacks | ||
defined in `g:Nvim_color_expr` and `g:Nvim_color_cmdline` respectively. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
g:Nvim_
might not be a good convention because sessionoptions+=globals
will try to store such variables if they are string/num types (doesn't apply here, but as a general convention ...).
Since these are temporary and deprecated, perhaps underscore prefix would make sense. g:_nvim_foo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@justinmk I can’t have leading underscores, funcref variable names must start with a capital. Underscore is not one.
|
||
local screen | ||
|
||
-- Bug in input() handling: {REDRAW} will erase the whole prompt up until |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should say :redraw!
instead of {REDRAW}
in this context.
src/nvim/ex_getln.c
Outdated
} else if (colored_ccline->cmdfirstc == ':') { | ||
try_enter(&tstate); | ||
err_errmsg = N_( | ||
"E5408: Unable to get Nvim_color_cmdline callback from g:: %s"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
g::
looks awkward. Suggestion:
"E5408: Unable to get g:Nvim_color_cmdline callback: %s"
There's a non-trivial amount of logic (and documentation) involving |
Insert-mode highlighting is done in C code. I am running VimL and expect it to be slow in cases like somebody trying to implement pygments in pure VimL. And I do not see too non-trivial amount: for |
Or, the other way around:
|
CI succeeded, only left running is gcov “flaky” build which will not possibly affect green status. |
All “flaky” appeared to be green as well, it is uncommon. |
FEATURES: 0e873a3 Lua(Jit) built-in neovim#4411 5b32bce Windows: `:terminal` neovim#7007 7b0ceb3 UI/API: externalize cmdline neovim#7173 b67f58b UI/API: externalize wildmenu neovim#7454 b23aa1c UI: 'winhighlight' neovim#6597 17531ed UI: command-line coloring (`:help input()-highlight`) neovim#6364 244a1f9 API: execute lua directly from the remote api neovim#6704 45626de API: `get_keymap()` neovim#6236 db99982 API: `nvim_get_hl_by_name()`, `nvim_get_hl_by_id()` neovim#7082 dc68538 menu_get() function neovim#6322 9db42d4 :cquit : take an error code argument neovim#7336 9cc185d job-control: serverstart(): support ipv6 neovim#6680 1b7a9bf job-control: sockopen() neovim#6594 6efe84a clipboard: fallback to tmux clipboard neovim#6894 6016ac2 clipboard: customize clipboard with `g:clipboard` neovim#6030 3a86dd5 ruby: override ruby host via `g:ruby_host_prog` neovim#6841 16cce1a debug: $NVIM_LOG_FILE neovim#6827 0cba3da `:checkhealth` built-in, validates $VIMRUNTIME neovim#7399 FIXES: 105d680 TUI: more terminals, improve scroll/resize neovim#6816 cb912a3 :terminal : handle F1-F12, other keys neovim#7241 619838f inccommand: improve performance neovim#6949 04b3c32 inccommand: Fix matches for zero-width neovim#7487 60b1e8a inccommand: multiline, other fixes neovim#7315 f1f7f3b inccommand: Ignore leading modifiers in the command neovim#6967 1551f71 inccommand: fix 'gdefault' lockup neovim#7262 6338199 API: bufhl: support creating new groups neovim#7414 541dde3 API: allow K_EVENT during operator-pending 8c732f7 terminal: adjust for 'number' neovim#7440 5bec946 UI: preserve wildmenu during jobs/events neovim#7110 c349083 UI: disable 'lazyredraw' during ui_refresh. neovim#6259 51808a2 send FocusGained/FocusLost event instead of pseudokey neovim#7221 133f8bc shada: preserve unnamed register on restart neovim#4700 1b70a1d shada: avoid assertion on corrupt shada file neovim#6958 9f534f3 mksession: Restore tab-local working directory neovim#6859 de1084f fix buf_write() crash neovim#7140 7f76986 syntax: register 'Normal' highlight group neovim#6973 6e7a8c3 RPC: close channel if stream was closed neovim#7081 85f3084 clipboard: disallow recursion; show hint only once neovim#7203 8d1ccb6 clipboard: performance, avoid weird edge-cases neovim#7193 01487d4 'titleold' neovim#7358 01e53a5 Windows: better path-handling, separator (slash) hygiene neovim#7349 0f2873c Windows: multibyte startup arguments neovim#7060 CHANGES: 9ff0cc7 :terminal : start in normal-mode neovim#6808 032b088 lower priority of 'cursorcolumn', 'colorcolumn' neovim#7364 2a3bcd1 RPC: Don't delay notifications when request is pending neovim#6544 023f67c :terminal : Do not change 'number', 'relativenumber' neovim#6796 1ef2d76 socket.c: Disable Nagle's algorithm on TCP sockets neovim#6915 6720fe2 help: `K` tries Vim help instead of manpage neovim#3104 7068370 help, man.vim: change "outline" map to `gO` neovim#7405
Based on #5119 as I do not want merge conflicts.
The idea is that we can color Neovim command-line. Ultimate goal is
:
/command prompts).=
/expr prompts).This is logical to split that into the following PRs:
src/nvim/eval
and split it from execution, make it produce coloring information. Obsoletes or reuses expression parser from VimL (Vimscript) to Lua translator #243. Reuses tests from VimL (Vimscript) to Lua translator #243. Resulting code is going to be rather unoptimal: expressions are going to be reparsed each time.:command -color=funcname
for coloring user commands.Proposed API for input():
input(prompt :: String[, text :: String[, completion :: String]])
: no additions.input(prompt :: String, options :: Dictionary)
,options
allow keys text, completion and highlight. No third argument allowed.