@@ -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)
241242endfunction
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+
243303function ! s: CommandChatNew (range , args ) abort
244304 call augment#chat#Reset ()
245305endfunction
@@ -248,6 +308,97 @@ function! s:CommandChatToggle(range, args) abort
248308 call augment#chat#Toggle ()
249309endfunction
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
252403let 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
264417function ! 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
0 commit comments