Skip to content

Commit

Permalink
feat(completion): add coc.preferences.minTriggerInputLength
Browse files Browse the repository at this point in the history
  • Loading branch information
chemzqm committed Oct 21, 2018
1 parent 88334cb commit 0920d9e
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 55 deletions.
6 changes: 3 additions & 3 deletions autoload/coc/snippet.vim
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ let s:is_vim = !has('nvim')
" make a range to select mode
function! coc#snippet#range_select(lnum, col, len) abort
let m = mode()
noa set virtualedit=onemore
if a:len == 0 && m !=# 'i'
startinsert
endif
if a:len > 0 && m ==# 'i'
stopinsert
endif
call timer_start(10, { -> s:start_select(a:lnum, a:col, a:len)})
call timer_start(20, { -> s:start_select(a:lnum, a:col, a:len)})
endfunction

function! s:start_select(lnum, col, len)
noa set virtualedit=onemore
call cursor(a:lnum, a:col)
if a:len > 0
let m = a:len == 1 ? '' : (a:len - 1).'l'
execute 'normal! v'.m. "\<C-g>"
execute 'noa set virtualedit='.s:virtualedit
endif
execute 'noa set virtualedit='.s:virtualedit
endfunction

function! coc#snippet#show_choices(lnum, col, len, values) abort
Expand Down
9 changes: 7 additions & 2 deletions data/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@
},
"coc.preferences.languageSourcePriority": {
"type": "number",
"default": 9,
"default": 99,
"description": "Priority of language sources."
},
"coc.preferences.rootPath": {
Expand All @@ -266,10 +266,15 @@
"default": 500,
"description": "Timeout for completion, in miliseconds."
},
"coc.preferences.minTriggerInputLength": {
"type": "number",
"default": 1,
"description": "Mininal input length for trigger completion, default 1"
},
"coc.preferences.triggerCompletionWait": {
"type": "integer",
"default": 60,
"description": "Wait time between trigger characer type and completion start."
"description": "Wait time between trigger characer type and completion start, for sync content to the server"
},
"coc.preferences.noselect": {
"type": "boolean",
Expand Down
1 change: 1 addition & 0 deletions settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"coc.preferences.snippets.enable": true,
// only used when autoTrigger is always
"coc.preferences.triggerAfterInsertEnter": false,
"coc.preferences.minTriggerInputLength": 1,
"coc.preferences.customSources": ["word", "emoji", "include"],
"coc.preferences.timeout": 500,
"coc.preferences.noselect": true,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/completion/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('completion', () => {
await helper.wait(100)
items = await helper.getItems()
words = items.map(o => o.word)
expect(words).toEqual(['format', 'fallback', 'forceDocumentSync'])
expect(words).toEqual([])
})

it('should not trigger on insert enter', async () => {
Expand Down
74 changes: 39 additions & 35 deletions src/completion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { isCocItem } from './util/complete'
import { fuzzyMatch, getCharCodes } from './util/fuzzy'
import { byteSlice } from './util/string'
import workspace from './workspace'
import Document from './model/document'
const logger = require('./util/logger')('completion')

export interface LastInsert {
Expand All @@ -18,6 +19,8 @@ export interface LastInsert {
}

export class Completion implements Disposable {
// current input string
private input: string
private increment: Increment
private lastInsert?: LastInsert
private lastChangedI: number
Expand Down Expand Up @@ -67,32 +70,37 @@ export class Completion implements Disposable {
}
}

private get document(): Document {
let { option } = this
if (!option) return null
return workspace.getDocument(option.bufnr)
}

private async getResumeInput(): Promise<string> {
let { option, increment } = this
let [, lnum, col] = await this.nvim.call('getcurpos')
if (lnum != option.linenr || col <= option.col) {
increment.stop()
return null
}
let line = option.document.getline(lnum - 1)
let line = this.document.getline(lnum - 1)
return byteSlice(line, option.col, col - 1)
}

private get isTriggered(): boolean {
let { option } = this
let { document, triggerCharacter } = option
return triggerCharacter && !document.isWord(triggerCharacter)
let { triggerCharacter } = this.option
return triggerCharacter && !this.document.isWord(triggerCharacter)
}

private get bufnr(): number {
let { option } = this
return option ? option.bufnr : null
}

private get input(): string {
let { option } = this
return option ? option.input : null
}
// private get input(): string {
// let { option } = this
// return option ? option.input : null
// }

public init(nvim: Neovim): void {
this.nvim = nvim
Expand All @@ -111,12 +119,10 @@ export class Completion implements Disposable {
// stop change emit on completion
increment.on('start', () => {
this.completeItems = []
let { document } = this.option
document.paused = true
this.document.paused = true
})
increment.on('stop', () => {
let { document } = this.option
document.paused = false
this.document.paused = false
this.option = null
})
}
Expand All @@ -139,11 +145,9 @@ export class Completion implements Disposable {
}

public startCompletion(option: CompleteOption): void {
Object.defineProperty(option, 'document', {
value: workspace.getDocument(option.bufnr),
enumerable: false
})
if (option.document == null || this.completing) return
this.option = option
this.input = option.input
if (this.document == null || this.completing) return
this.completing = true
this._doComplete(option).then(() => {
this.completing = false
Expand All @@ -157,7 +161,7 @@ export class Completion implements Disposable {
private async resumeCompletion(resumeInput: string, isChangedP = false): Promise<void> {
let { nvim, increment, option, complete, insertMode } = this
if (!complete || !complete.results) return
option.input = resumeInput
this.input = resumeInput
let items = complete.filterResults(resumeInput)
if (!insertMode || !items || items.length === 0) {
this.nvim.call('coc#_hide', [], true)
Expand All @@ -184,9 +188,8 @@ export class Completion implements Disposable {
}

private async _doComplete(option: CompleteOption): Promise<void> {
let { document, linenr, line } = option
let { nvim, increment } = this
this.option = option
let { linenr, line } = option
let { nvim, increment, document } = this
increment.start()
logger.trace(`options: ${JSON.stringify(option)}`)
let arr = sources.getCompleteSources(option)
Expand Down Expand Up @@ -229,27 +232,25 @@ export class Completion implements Disposable {
private async onTextChangedI(bufnr: number): Promise<void> {
this.lastChangedI = Date.now()
if (this.completing) return
let { nvim, increment, input } = this
let { latestInsertChar } = this
let { nvim, increment, input, latestInsertChar } = this
if (increment.isActivted) {
if (bufnr !== this.bufnr) return
let search = await this.getResumeInput()
if (search == null || search == input) return
if (!increment.isActivted) return
let { document } = this.option
let len = input.length
if (!this.isTriggered && len == 0 && document.isWord(search[0])) {
if (search.length < this.option.input.length) {
increment.stop()
} else {
return await this.resumeCompletion(search)
return
}
return await this.resumeCompletion(search)
}
if (!latestInsertChar) return
// check trigger
let shouldTrigger = await this.shouldTrigger(latestInsertChar)
if (!shouldTrigger) return
let option: CompleteOption = await nvim.call('coc#util#get_complete_option')
if (latestInsertChar) option.triggerCharacter = latestInsertChar
Object.freeze(option)
logger.trace('trigger completion with', option)
this.startCompletion(option)
}
Expand All @@ -274,11 +275,11 @@ export class Completion implements Disposable {

private async onInsertEnter(): Promise<void> {
this.insertMode = true
let autoTrigger = this.preferences.get<string>('autoTrigger', 'always')
if (autoTrigger !== 'always') return
let trigger = this.preferences.get<boolean>('triggerAfterInsertEnter', false)
if (trigger && !this.completing) {
let option = await this.nvim.call('coc#util#get_complete_option')
if (!trigger || this.completing) return
let minLength = this.preferences.get<number>('minTriggerInputLength', 1)
let option = await this.nvim.call('coc#util#get_complete_option')
if (option.input.length >= minLength) {
this.startCompletion(option)
}
}
Expand Down Expand Up @@ -319,10 +320,13 @@ export class Completion implements Disposable {
let autoTrigger = this.preferences.get<string>('autoTrigger', 'always')
if (autoTrigger == 'none') return false
let doc = await workspace.document
// let [, lnum, col] = await this.nvim.call('getcurpos')
// let line = doc.getline(lnum - 1)
if (sources.shouldTrigger(character, doc.filetype)) return true
if (doc.isWord(character)) return autoTrigger == 'always'
if (autoTrigger !== 'always') return false
if (doc.isWord(character)) {
let minLength = this.preferences.get<number>('minTriggerInputLength', 1)
let input = await this.nvim.call('coc#util#get_input') as string
return input.length >= minLength
}
return false
}

Expand Down
26 changes: 16 additions & 10 deletions src/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,25 +529,31 @@ class Languages {
let { nvim } = this
let { textEdit } = item
if (!textEdit) return null
let { line, bufnr, linenr } = option
let { range, newText } = textEdit
let isSnippet = item.insertTextFormat === InsertTextFormat.Snippet
let document = workspace.getDocument(option.bufnr)
if (!document) return null
let line = document.getline(option.linenr - 1)
let deleteCount = range.end.character - option.colnr + 1
let character = range.start.character
// replace inserted word
let start = line.substr(0, character)
let label = complete.getWord(item)
let end = line.substr(option.col + label.length + deleteCount)
let end = line.substr(range.end.character)
if (isSnippet) {
await nvim.call('coc#util#setline', [option.linenr, `${start}${end}`])
await nvim.call('cursor', [option.linenr, byteLength(start) + 1])
await nvim.call('cursor', [linenr, byteLength(start) + 1])
return newText
}
let newLine = `${start}${newText}${end}`
if (newLine != line) {
await nvim.call('setline', [option.linenr, newLine])
let newLines = `${start}${newText}${end}`.split('\n')
if (newLines.length == 1) {
await nvim.call('coc#util#setline', [linenr, newLines[0]])
await nvim.call('cursor', [linenr, byteLength(start + newText) + 1])
} else {
let document = workspace.getDocument(bufnr)
if (document) {
await document.buffer.setLines(newLines, {
start: linenr - 1,
end: linenr,
strictIndexing: false
})
}
}
return null
}
Expand Down
1 change: 0 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ export interface CompleteOption {
linenr: number
custom: boolean
synname: string
document: Document
}

export interface VimCompleteItem {
Expand Down
6 changes: 3 additions & 3 deletions src/util/complete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ export function isCocItem(item: any): boolean {
}

export function getPosition(opt: CompleteOption): Position {
let { line, linenr, col, colnr } = opt
let part = byteSlice(line, 0, col - 1)
let { line, linenr, colnr } = opt
let part = byteSlice(line, 0, colnr - 1)
return {
line: linenr - 1,
character: part.length + 1 + (colnr - col > 1 ? 1 : 0)
character: part.length
}
}

Expand Down

0 comments on commit 0920d9e

Please sign in to comment.