Skip to content

Commit 67f6a0e

Browse files
Augment Vim v0.48.0
1 parent faee8f7 commit 67f6a0e

7 files changed

Lines changed: 331 additions & 12 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ This file documents the notable changes for each stable version of the Augment
44
Vim plugin. The following list is not necessarily comprehensive, but should
55
include any changes that may impact the user experience.
66

7+
## Unreleased
8+
9+
- Add the `:Augment chat-input` command, which opens a floating window for
10+
composing a chat message before sending it (Neovim only). It is range-aware
11+
like `:Augment chat`, and falls back to the standard `input()` prompt on Vim.
12+
- Add the `:Augment help [command]` command, which lists the available commands
13+
or shows more detailed help for a specific command.
14+
- Fix Neovim API deprecation warnings: migrate from `vim.lsp.start_client` to
15+
`vim.lsp.start` (with `attach = false` to preserve the plugin's explicit
16+
buffer-attach logic) and use the colon-method syntax for `client:notify` and
17+
`client:request` on Neovim 0.11+, with a compatibility fallback for 0.10.
18+
719
## 0.25.1
820

921
- Deprecate the `Enable` and `Disable` commands in favor of the

‎README.md‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,10 @@ The following commands are provided:
7979
:Augment signout " Sign out of Augment
8080
:Augment log " View the plugin log
8181
:Augment chat " Send a chat message to Augment AI
82+
:Augment chat-input " Compose a chat message in a floating window (Neovim only)
8283
:Augment chat-new " Start a new chat conversation
8384
:Augment chat-toggle " Toggle the chat panel visibility
85+
:Augment help " List the available commands, or `:Augment help <command>` for details
8486
```
8587
8688
## Workspace Folders
@@ -145,6 +147,33 @@ You can interact with chat in two ways:
145147
146148
The response will appear in a separate chat buffer with markdown formatting.
147149
150+
### Floating chat input (Neovim only)
151+
152+
The `:Augment chat-input` command opens a centered floating window with a
153+
markdown scratch buffer where you can compose a chat message before sending it.
154+
This is handy for writing longer, multi-line prompts. The window opens in insert
155+
mode, and its title shows the available keys:
156+
157+
- `<C-s>` (insert or normal mode) or `<CR>` (normal mode) submits the message
158+
- `<Esc>` (normal mode) or `<C-c>` (insert or normal mode) cancels
159+
160+
Like `:Augment chat`, it is range-aware: invoking it from visual mode (or with a
161+
range) includes the selected text in the chat request once you submit.
162+
163+
If an input window is already open, running the command again refocuses it
164+
rather than opening a new one, so you won't lose what you've typed if focus
165+
moves away.
166+
167+
This command requires Neovim's floating window support. In Vim it falls back to
168+
the standard `input()` prompt used by `:Augment chat`, with no change to
169+
existing behavior. The plugin does not define a default mapping for it, so map
170+
it yourself if you'd like a shortcut, for example:
171+
172+
```vim
173+
nnoremap <leader>ai :Augment chat-input<CR>
174+
vnoremap <leader>ai :Augment chat-input<CR>
175+
```
176+
148177
To start a new conversation, use the `:Augment chat-new` command. This will
149178
clear the chat history from your context.
150179

‎autoload/augment.vim‎

Lines changed: 159 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,9 @@ function! s:CommandChat(range, args) abort
201201
" prompt the user for a message
202202
let message = empty(a:args) ? input('Message: ') : a:args
203203

204-
" Handle cancellation or empty input
205-
if message ==# '' || message =~# '^\s*$'
204+
" Handle cancellation or empty input. \_s matches whitespace including
205+
" newlines, so a message that is only blank lines is treated as cancel.
206+
if message ==# '' || message =~# '^\_s*$'
206207
redraw
207208
echo 'Chat cancelled'
208209
return
@@ -240,6 +241,65 @@ function! s:CommandChat(range, args) abort
240241
call augment#client#Client().Request('augment/chat', params)
241242
endfunction
242243

244+
" Open a floating window to compose a chat message before sending it. The
245+
" floating input is Neovim-only; in Vim (and when a message is supplied
246+
" directly) this falls back to the standard chat command, which prompts for a
247+
" message via input() when none is given.
248+
function! s:CommandChatInput(range, args) abort
249+
if !s:IsRunning()
250+
echohl WarningMsg
251+
echo s:NOT_RUNNING_MSG
252+
echohl None
253+
return
254+
endif
255+
256+
" Determine whether a selection range is active. Leave visual mode so the
257+
" '< and '> marks are set for the chat flow to pick up on submit.
258+
let was_visual = index(['v', 'V', "\<C-v>"], mode()) >= 0
259+
if was_visual
260+
execute "normal! \<Esc>"
261+
endif
262+
let ranged = a:range == 2 || was_visual
263+
264+
" A message passed directly on the command line skips the floating input.
265+
" Vim has no editable floating window, so it falls back to the input()
266+
" prompt provided by the standard chat command.
267+
if !empty(a:args) || !has('nvim')
268+
call s:CommandChat(ranged ? 2 : 0, a:args)
269+
return
270+
endif
271+
272+
let source_win = win_getid()
273+
let Callback = function('s:ChatInputSubmit', [source_win, ranged])
274+
call augment#chat#OpenInputWindow(Callback)
275+
endfunction
276+
277+
" Handle a message submitted from the floating chat input
278+
function! s:ChatInputSubmit(source_win, ranged, message) abort
279+
" \_s matches whitespace including newlines, so a buffer of only blank
280+
" lines is treated as cancel rather than sending an empty message.
281+
if a:message ==# '' || a:message =~# '^\_s*$'
282+
redraw
283+
echo 'Chat cancelled'
284+
return
285+
endif
286+
287+
" Restore focus to the window the input was opened from
288+
if win_id2win(a:source_win) != 0
289+
call win_gotoid(a:source_win)
290+
endif
291+
292+
" Re-select the original range so it is passed through to the chat request,
293+
" mirroring the behavior of `:Augment chat` in visual mode. The '< and '>
294+
" marks were set when the command left visual mode, so `gv` works whether
295+
" invoked from visual mode or via an explicit `:'<,'>` range.
296+
if a:ranged
297+
normal! gv
298+
endif
299+
300+
call s:CommandChat(a:ranged ? 2 : 0, a:message)
301+
endfunction
302+
243303
function! s:CommandChatNew(range, args) abort
244304
call augment#chat#Reset()
245305
endfunction
@@ -248,6 +308,97 @@ function! s:CommandChatToggle(range, args) abort
248308
call augment#chat#Toggle()
249309
endfunction
250310

311+
" Help text for the available commands. The order of this list determines the
312+
" order shown by `:Augment help`. Each entry has a usage string (shown in the
313+
" detail header), a one-line summary (shown in the command list), and a list of
314+
" detail lines (shown by `:Augment help <command>`).
315+
let s:command_help = [
316+
\ {'name': 'status', 'usage': 'status', 'summary': 'View the current status of the plugin.', 'detail': [
317+
\ 'View the current status of the plugin, including whether you are',
318+
\ 'signed in and the syncing progress of any configured workspace folders.',
319+
\ ]},
320+
\ {'name': 'signin', 'usage': 'signin', 'summary': 'Sign in to Augment.', 'detail': [
321+
\ 'Authenticate with the Augment service using OAuth. This is required',
322+
\ 'before using the plugin for the first time.',
323+
\ ]},
324+
\ {'name': 'signout', 'usage': 'signout', 'summary': 'Sign out of Augment.', 'detail': [
325+
\ 'Sign out of Augment.',
326+
\ ]},
327+
\ {'name': 'log', 'usage': 'log', 'summary': 'View the plugin log.', 'detail': [
328+
\ 'View the plugin log. This is useful for debugging.',
329+
\ ]},
330+
\ {'name': 'chat', 'usage': 'chat [message]', 'summary': 'Send a chat message to Augment AI.', 'detail': [
331+
\ 'Start a chat with Augment AI. In visual mode, the selected text will',
332+
\ 'be included in the chat request. If no message is provided, you will',
333+
\ 'be prompted to enter one.',
334+
\ ]},
335+
\ {'name': 'chat-input', 'usage': 'chat-input', 'summary': 'Compose a chat message in a floating window (Neovim only).', 'detail': [
336+
\ 'Open a centered floating window with a markdown scratch buffer for',
337+
\ 'composing a chat message before sending it. Submit with <C-s> or, in',
338+
\ 'normal mode, <CR>; cancel with <Esc> or <C-c>. Like ":Augment chat" it',
339+
\ 'is range-aware. Requires Neovim; in Vim it falls back to the input()',
340+
\ 'prompt used by ":Augment chat".',
341+
\ ]},
342+
\ {'name': 'chat-new', 'usage': 'chat-new', 'summary': 'Start a new chat conversation.', 'detail': [
343+
\ 'Start a new chat conversation with Augment AI, clearing the history',
344+
\ 'from your context.',
345+
\ ]},
346+
\ {'name': 'chat-toggle', 'usage': 'chat-toggle', 'summary': 'Toggle the chat panel visibility.', 'detail': [
347+
\ 'Open or close the chat conversation window. The conversation is',
348+
\ 'preserved while the window is closed and can be reopened with the',
349+
\ 'same command.',
350+
\ ]},
351+
\ {'name': 'help', 'usage': 'help [command]', 'summary': 'Show help for Augment commands.', 'detail': [
352+
\ 'Show help for Augment commands. With no argument, list all available',
353+
\ 'commands with a short description. With a command name, show detailed',
354+
\ 'help for that command.',
355+
\ ]},
356+
\ {'name': 'enable', 'usage': 'enable', 'summary': '(deprecated) See g:augment_disable_completions.', 'detail': [
357+
\ 'Deprecated. Use the g:augment_disable_completions option instead,',
358+
\ 'which disables inline completions without affecting chat. See',
359+
\ '":help g:augment_disable_completions" for more details.',
360+
\ ]},
361+
\ {'name': 'disable', 'usage': 'disable', 'summary': '(deprecated) See g:augment_disable_completions.', 'detail': [
362+
\ 'Deprecated. Use the g:augment_disable_completions option instead,',
363+
\ 'which disables inline completions without affecting chat. See',
364+
\ '":help g:augment_disable_completions" for more details.',
365+
\ ]},
366+
\ ]
367+
368+
" Show help for the available commands. With no argument, list all commands;
369+
" with a command name, show detailed help for that command.
370+
function! s:CommandHelp(range, args) abort
371+
let topic = empty(a:args) ? '' : split(a:args)[0]
372+
373+
if empty(topic)
374+
echohl Title
375+
echo 'Augment commands'
376+
echohl None
377+
for entry in s:command_help
378+
echo printf(' :Augment %-12s %s', entry.name, entry.summary)
379+
endfor
380+
echo 'Run ":Augment help <command>" for more details about a command.'
381+
return
382+
endif
383+
384+
for entry in s:command_help
385+
" Note that ==? is case-insensitive comparison
386+
if topic ==? entry.name
387+
echohl Title
388+
echo ':Augment ' . entry.usage
389+
echohl None
390+
for line in entry.detail
391+
echo ' ' . line
392+
endfor
393+
return
394+
endif
395+
endfor
396+
397+
echohl WarningMsg
398+
echo 'Augment: Unknown command: "' . topic . '". Run ":Augment help" to list available commands.'
399+
echohl None
400+
endfunction
401+
251402
" Handle user commands
252403
let s:command_handlers = {
253404
\ 'log': function('s:CommandLog'),
@@ -257,8 +408,10 @@ let s:command_handlers = {
257408
\ 'disable': function('s:CommandDisable'),
258409
\ 'status': function('s:CommandStatus'),
259410
\ 'chat': function('s:CommandChat'),
411+
\ 'chat-input': function('s:CommandChatInput'),
260412
\ 'chat-new': function('s:CommandChatNew'),
261413
\ 'chat-toggle': function('s:CommandChatToggle'),
414+
\ 'help': function('s:CommandHelp'),
262415
\ }
263416

264417
function! augment#Command(range, args) abort range
@@ -267,11 +420,12 @@ function! augment#Command(range, args) abort range
267420
return
268421
endif
269422

270-
" If the plugin failed to initialize, only allow status and log commands
423+
" If the plugin failed to initialize, only allow status, log, and help
424+
" commands
271425
let command = split(a:args)[0]
272426
if (!exists('g:augment_initialized') || !g:augment_initialized)
273-
\ && command !=# 'status' && command !=# 'log'
274-
call augment#DisplayError('The Augment plugin failed to initialize. Only `:Augment status` and `:Augment log` commands are available.')
427+
\ && command !=# 'status' && command !=# 'log' && command !=# 'help'
428+
call augment#DisplayError('The Augment plugin failed to initialize. Only `:Augment status`, `:Augment log`, and `:Augment help` commands are available.')
275429
return
276430
endif
277431

‎autoload/augment/chat.vim‎

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ function! augment#chat#OpenChatPanel() abort
5555
if exists('&winfixbuf')
5656
setlocal winfixbuf " Keep buffer in window when splitting
5757
endif
58+
setlocal winfixwidth " Never change the window's width
5859
setlocal bufhidden=hide " When buffer is abandoned, hide it
5960
setlocal nobuflisted " Hide from :ls
6061
setlocal wrap " Wrap long lines
@@ -78,6 +79,97 @@ function! augment#chat#OpenChatPanel() abort
7879
call win_gotoid(current_win)
7980
endfunction
8081

82+
" Open a centered floating window with a scratch markdown buffer for composing
83+
" a chat message. a:OnSubmit is a Funcref invoked with the composed message
84+
" when the user submits. This relies on Neovim's floating window API and should
85+
" only be called when running under Neovim.
86+
function! augment#chat#OpenInputWindow(OnSubmit) abort
87+
" If an input window is already open, refocus it instead of opening a new
88+
" one. This avoids orphaning the existing float (and losing any typed
89+
" content) when the command is invoked again after focus moved away.
90+
if exists('s:input_win') && s:input_win != -1 && nvim_win_is_valid(s:input_win)
91+
call nvim_set_current_win(s:input_win)
92+
startinsert
93+
return
94+
endif
95+
96+
let s:input_on_submit = a:OnSubmit
97+
98+
" Create an unlisted scratch buffer (buftype=nofile, noswapfile)
99+
let buf = nvim_create_buf(v:false, v:true)
100+
101+
" Center the window, sizing it relative to the editor dimensions
102+
let width = float2nr(&columns * 0.6)
103+
let width = max([40, min([width, &columns - 4])])
104+
let height = max([5, min([10, &lines - 4])])
105+
let row = (&lines - height) / 2
106+
let col = (&columns - width) / 2
107+
108+
let opts = {
109+
\ 'relative': 'editor',
110+
\ 'width': width,
111+
\ 'height': height,
112+
\ 'row': row,
113+
\ 'col': col,
114+
\ 'style': 'minimal',
115+
\ 'border': 'rounded',
116+
\ 'title': ' Augment Chat (<C-s>/<CR> submit, <Esc> cancel) ',
117+
\ 'title_pos': 'center',
118+
\ }
119+
120+
let s:input_win = nvim_open_win(buf, v:true, opts)
121+
let s:input_buf = buf
122+
123+
setlocal filetype=markdown " Use markdown syntax highlighting
124+
setlocal bufhidden=wipe " Discard the buffer when the window closes
125+
setlocal wrap " Wrap long lines
126+
setlocal linebreak " Wrap at word boundaries
127+
128+
" Submit with <C-s> (insert and normal) or <CR> (normal)
129+
inoremap <buffer> <silent> <C-s> <Esc><Cmd>call <SID>InputSubmit()<CR>
130+
nnoremap <buffer> <silent> <C-s> <Cmd>call <SID>InputSubmit()<CR>
131+
nnoremap <buffer> <silent> <CR> <Cmd>call <SID>InputSubmit()<CR>
132+
" Cancel with <Esc> (normal) or <C-c> (insert and normal)
133+
nnoremap <buffer> <silent> <Esc> <Cmd>call <SID>InputCancel()<CR>
134+
inoremap <buffer> <silent> <C-c> <Esc><Cmd>call <SID>InputCancel()<CR>
135+
nnoremap <buffer> <silent> <C-c> <Cmd>call <SID>InputCancel()<CR>
136+
137+
" Start in insert mode so the user can type immediately
138+
startinsert
139+
endfunction
140+
141+
function! s:CloseInputWindow() abort
142+
if exists('s:input_win') && s:input_win != -1 && nvim_win_is_valid(s:input_win)
143+
call nvim_win_close(s:input_win, v:true)
144+
endif
145+
let s:input_win = -1
146+
endfunction
147+
148+
" Join the buffer contents into a message, close the window, and invoke the
149+
" stored submit callback with the message.
150+
function! s:InputSubmit() abort
151+
if !exists('s:input_buf') || !nvim_buf_is_valid(s:input_buf)
152+
call s:CloseInputWindow()
153+
return
154+
endif
155+
156+
let lines = nvim_buf_get_lines(s:input_buf, 0, -1, v:false)
157+
let message = join(lines, "\n")
158+
let Callback = s:input_on_submit
159+
160+
call s:CloseInputWindow()
161+
162+
if type(Callback) == v:t_func
163+
call Callback(message)
164+
endif
165+
endfunction
166+
167+
function! s:InputCancel() abort
168+
call s:CloseInputWindow()
169+
redraw
170+
echo 'Chat cancelled'
171+
endfunction
172+
81173
function! augment#chat#Reset() abort
82174
call s:ResetChatContents()
83175
call s:ResetHistory()

‎autoload/augment/version.vim‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
" MIT License - See LICENSE.md for full terms
33

44
function! augment#version#Version() abort
5-
return '0.47.0'
5+
return '0.48.0'
66
endfunction

0 commit comments

Comments
 (0)