1
0
Fork 0
mirror of synced 2024-06-25 18:21:11 -04:00
ultimate-vim/sources_non_forked/coc.nvim/src/core/ui.ts
2022-07-20 13:20:15 +08:00

105 lines
3.6 KiB
TypeScript

'use strict'
import { Neovim } from '@chemzqm/neovim'
import { Position, Range } from 'vscode-languageserver-protocol'
import { ScreenPosition } from '../types'
import { byteLength } from '../util/string'
const isVim = process.env.VIM_NODE_RPC == '1'
export async function getCursorPosition(nvim: Neovim): Promise<Position> {
// vim can't count utf16
let [line, content] = await nvim.eval(`[line('.')-1, strpart(getline('.'), 0, col('.') - 1)]`) as [number, string]
return Position.create(line, content.length)
}
/**
* Prompt user for confirm, a float/popup window would be used when possible,
* use vim's |confirm()| function as callback.
*
* @param title The prompt text.
* @returns Result of confirm.
*/
export async function showPrompt(nvim: Neovim, title: string): Promise<boolean> {
let res = await nvim.callAsync('coc#dialog#prompt_confirm', [title])
return res == 1
}
/**
* Move cursor to position.
*
* @param position LSP position.
*/
export async function moveTo(nvim: Neovim, position: Position, redraw: boolean): Promise<void> {
await nvim.call('coc#cursor#move_to', [position.line, position.character])
if (redraw) nvim.command('redraw', true)
}
/**
* Get current cursor character offset in document,
* length of line break would always be 1.
*
* @returns Character offset.
*/
export async function getOffset(nvim: Neovim): Promise<number> {
return await nvim.call('coc#cursor#char_offset') as number
}
/**
* Get screen position of current cursor(relative to editor),
* both `row` and `col` are 0 based.
*
* @returns Cursor screen position.
*/
export async function getCursorScreenPosition(nvim: Neovim): Promise<ScreenPosition> {
let [row, col] = await nvim.call('coc#cursor#screen_pos') as [number, number]
return { row, col }
}
/**
* Reveal message with highlight.
*/
export function showMessage(nvim: Neovim, msg: string, hl: 'MoreMsg' | 'Error' | 'ErrorMsg' | 'WarningMsg' = 'MoreMsg', forceTimer = false): void {
let method = forceTimer || isVim ? 'callTimer' : 'call'
nvim[method]('coc#ui#echo_messages', [hl, ('[coc.nvim] ' + msg).split('\n')], true)
}
/**
* Mode could be 'char', 'line', 'cursor', 'v', 'V', '\x16'
*/
export async function getSelection(nvim: Neovim, mode: string): Promise<Range | null> {
if (mode === 'line') {
let line = await nvim.call('line', ['.'])
return Range.create(line - 1, 0, line, 0)
}
if (mode === 'cursor') {
let [line, character] = await nvim.eval("coc#cursor#position()") as [number, number]
return Range.create(line, character, line, character)
}
let res = await nvim.call('coc#cursor#get_selection', [mode === 'char' ? 1 : 0])
if (!res) return null
return Range.create(res[0], res[1], res[2], res[3])
}
export async function selectRange(nvim: Neovim, range: Range, redraw: boolean): Promise<void> {
let { start, end } = range
let [line, endLine] = await nvim.eval(`[getline(${start.line + 1}),getline(${end.line + 1})]`) as [string, string]
let col = line.length > 0 ? byteLength(line.slice(0, start.character)) : 0
let endCol: number
let endLnum: number
let toEnd = end.character == 0
if (toEnd) {
endLnum = end.line == 0 ? 0 : end.line - 1
let pre = await nvim.call('getline', [endLnum + 1]) as string
endCol = byteLength(pre)
} else {
endLnum = end.line
endCol = endLine.length > 0 ? byteLength(endLine.slice(0, end.character)) : 0
}
nvim.pauseNotification()
nvim.command(`noa call cursor(${start.line + 1},${col + 1})`, true)
nvim.command('normal! v', true)
nvim.command(`noa call cursor(${endLnum + 1},${endCol})`, true)
if (toEnd) nvim.command('normal! $', true)
await nvim.resumeNotification(redraw)
}