1
0
Fork 0
mirror of synced 2024-06-26 02:31:09 -04:00
ultimate-vim/sources_non_forked/coc.nvim/src/model/input.ts
2022-07-20 13:20:15 +08:00

143 lines
4.2 KiB
TypeScript

'use strict'
import { Neovim } from '@chemzqm/neovim'
import { Disposable, Emitter, Event } from 'vscode-languageserver-protocol'
import events from '../events'
import { disposeAll } from '../util'
const logger = require('../util/logger')('model-input')
export interface InputPreference {
position?: 'cursor' | 'center'
marginTop?: number
border?: [0 | 1, 0 | 1, 0 | 1, 0 | 1]
rounded?: boolean
minWidth?: number
maxWidth?: number
highlight?: string
borderhighlight?: string
/**
* map list key-mappings
*/
list?: boolean
}
export interface Dimension {
width: number
height: number
row: number
col: number
}
export type InputOptions = Pick<InputPreference, 'borderhighlight' | 'position' | 'marginTop'>
type RequestResult = [number, number, [number, number, number, number]]
export default class InputBox implements Disposable {
private disposables: Disposable[] = []
private _winid: number | undefined
private _bufnr: number | undefined
private _input: string
private accepted = false
public title: string
public loading: boolean
public borderhighlight: string
// width, height, row, col
private _dimension: [number, number, number, number] = [0, 0, 0, 0]
private readonly _onDidFinish = new Emitter<string>()
private readonly _onDidChange = new Emitter<string>()
public readonly onDidFinish: Event<string | null> = this._onDidFinish.event
public readonly onDidChange: Event<string> = this._onDidChange.event
constructor(private nvim: Neovim, defaultValue: string) {
this._input = defaultValue
this.disposables.push(this._onDidFinish)
this.disposables.push(this._onDidChange)
let _title: string | undefined
Object.defineProperty(this, 'title', {
set: (newTitle: string) => {
_title = newTitle
if (this._winid) nvim.call('coc#dialog#change_title', [this._winid, newTitle], true)
},
get: () => {
return _title
}
})
let _loading = false
Object.defineProperty(this, 'loading', {
set: (loading: boolean) => {
_loading = loading
if (this._winid) nvim.call('coc#dialog#change_loading', [this._winid, loading], true)
},
get: () => {
return _loading
}
})
let _borderhighlight: string
Object.defineProperty(this, 'borderhighlight', {
set: (borderhighlight: string) => {
_borderhighlight = borderhighlight
if (this._winid) nvim.call('coc#dialog#change_border_hl', [this._winid, borderhighlight], true)
},
get: () => {
return _borderhighlight
}
})
events.on('BufWinLeave', bufnr => {
if (bufnr == this._bufnr) {
this._winid = undefined
this.dispose()
}
}, null, this.disposables)
events.on('PromptInsert', (value, bufnr) => {
if (bufnr == this._bufnr) {
this._input = value
this.accepted = true
this.dispose()
}
}, null, this.disposables)
events.on('TextChangedI', (bufnr, info) => {
if (bufnr == this._bufnr) {
this._input = info.line
this._onDidChange.fire(info.line)
}
}, null, this.disposables)
}
public get dimension(): Dimension | undefined {
let { _dimension } = this
return { width: _dimension[0], height: _dimension[1], row: _dimension[2], col: _dimension[3] }
}
public get bufnr(): number | undefined {
return this._bufnr
}
public get winid(): number | undefined {
return this._winid
}
public get value(): string {
return this._input
}
public async show(title: string, preferences: InputPreference): Promise<boolean> {
this.title = title
this.borderhighlight = preferences.borderhighlight ?? 'CocFloating'
this.loading = false
let res = await this.nvim.call('coc#dialog#create_prompt_win', [title, this._input, preferences]) as RequestResult
if (!res) throw new Error('Unable to open input window')
this._bufnr = res[0]
this._winid = res[1]
this._dimension = res[2]
return true
}
public dispose(): void {
this._onDidFinish.fire(this.accepted ? this._input : null)
if (this._winid) {
this.nvim.call('coc#float#close', [this._winid], true)
}
this._winid = undefined
this._bufnr = undefined
disposeAll(this.disposables)
}
}