<commit_before>import Omni = require('../../../omni-sharp-server/omni')

import _ = require('lodash')
import rx = require('rx')
var filter = require('fuzzaldrin').filter;

export interface RequestOptions {
    editor: Atom.TextEditor;
    bufferPosition: TextBuffer.Point; // the position of the cursor
    prefix: string;
    scopeDescriptor: { scopes: string[] };
}

export interface Suggestion {
    //Either text or snippet is required
    text?: string;
    snippet?: string;
    displayText?: string;
    replacementPrefix?: string;
    type: string;
    leftLabel?: string;
    leftLabelHTML?: string;
    rightLabel?: string;
    rightLabelHTML?: string;
    iconHTML?: string;
    description?: string;
    descriptionMoreURL?: string;
    className?: string;
}

// Hide all the private code, so it doesn't bleed into the rest
// Make another file at somepoint?
var dataSource = (function() {
    var currentOptions: RequestOptions;

    function getResults(options: RequestOptions) {
        return Omni.client.autocomplete(Omni.makeDataRequest<OmniSharp.Models.AutoCompleteRequest>({
            WordToComplete: '',
            WantDocumentationForEveryCompletionResult: false,
            WantKind: true,
            WantSnippet: true,
            WantReturnType: true
        }))
            .map(completions => {
            if (completions == null) {
                completions = [];
            }
            return completions;
        });
    };

    function justResults(options: RequestOptions) {
        getSuggestionsSubject.onNext(getResults(options).toPromise())
    }

    function nextResults(value) {
        getSuggestionsSubject.onNext(getLatestValueObservable.take(1).toPromise());
    }

    var requestSubject = new rx.Subject<RequestOptions>();
    var clearCacheSubject = new rx.Subject<boolean>();
    var getLatestValueObservable = requestSubject.flatMap(getResults);
    var getSuggestionsSubject = new rx.BehaviorSubject<rx.IPromise<OmniSharp.Models.AutoCompleteResponse[]>>(getLatestValueObservable.take(1).toPromise());

    // Clear when auto-complete is opening.
    // TODO: Update atom typings
    atom.commands.onWillDispatch(function(event: Event) {
        if (event.type === "autocomplete-plus:activate" || event.type === "autocomplete-plus:confirm" || event.type === "autocomplete-plus:cancel") {
            clearCachedValue();
        }

        if (event.type === "autocomplete-plus:activate" && currentOptions) {
            requestSubject.onNext(currentOptions);
        }
    });

    // Always reset if the value is a dot
    var clearCacheWithDotPrefixObservable = requestSubject
        .where(z => z.prefix === "." || (z.prefix && !_.trim(z.prefix)) || !z.prefix)
        .subscribe(justResults);

    rx.Observable.merge(clearCacheSubject).subscribe(nextResults);

    function clearCachedValue() {
        clearCacheSubject.onNext(true);
    }

    return {
        onNext(options: RequestOptions) {
            currentOptions = options;<commit_msg>Brought back buffer movement check, if the user tries to be like @nosami and break things. ;)<commit_after>import Omni = require('../../../omni-sharp-server/omni')

import _ = require('lodash')
import rx = require('rx')
var filter = require('fuzzaldrin').filter;

export interface RequestOptions {
    editor: Atom.TextEditor;
    bufferPosition: TextBuffer.Point; // the position of the cursor
    prefix: string;
    scopeDescriptor: { scopes: string[] };
}

export interface Suggestion {
    //Either text or snippet is required
    text?: string;
    snippet?: string;
    displayText?: string;
    replacementPrefix?: string;
    type: string;
    leftLabel?: string;
    leftLabelHTML?: string;
    rightLabel?: string;
    rightLabelHTML?: string;
    iconHTML?: string;
    description?: string;
    descriptionMoreURL?: string;
    className?: string;
}

// Hide all the private code, so it doesn't bleed into the rest
// Make another file at somepoint?
var dataSource = (function() {
    var currentOptions: RequestOptions;

    function getResults(options: RequestOptions) {
        return Omni.client.autocomplete(Omni.makeDataRequest<OmniSharp.Models.AutoCompleteRequest>({
            WordToComplete: '',
            WantDocumentationForEveryCompletionResult: false,
            WantKind: true,
            WantSnippet: true,
            WantReturnType: true
        }))
            .map(completions => {
            if (completions == null) {
                completions = [];
            }
            return completions;
        });
    };

    function justResults(options: RequestOptions) {
        getSuggestionsSubject.onNext(getResults(options).toPromise())
    }

    function nextResults(value) {
        getSuggestionsSubject.onNext(getLatestValueObservable.take(1).toPromise());
    }

    var requestSubject = new rx.Subject<RequestOptions>();
    var clearCacheSubject = new rx.Subject<boolean>();
    var getLatestValueObservable = requestSubject.flatMap(getResults);
    var getSuggestionsSubject = new rx.BehaviorSubject<rx.IPromise<OmniSharp.Models.AutoCompleteResponse[]>>(getLatestValueObservable.take(1).toPromise());

    // Detect when the cursor has moved a good distance
    var bufferMovement = rx.Observable.zip(requestSubject, requestSubject.skip(1), (previous, current) => {
        // If the row changes we moved lines, we should refetch the completions
        // (Is it possible it will be the same set?)
        var row = Math.abs(current.bufferPosition.row - previous.bufferPosition.row) > 1;
        // If the column jumped, lets get them again to be safe.
        var column = Math.abs(current.bufferPosition.column - previous.bufferPosition.column) > 4;

        return { reset: row || column || false, previous: previous, current: current };
    }).where(z => z.reset).select(x => x.current);

    // Clear when auto-complete is opening.
    // TODO: Update atom typings
    atom.commands.onWillDispatch(function(event: Event) {
        if (event.type === "autocomplete-plus:activate" || event.type === "autocomplete-plus:confirm" || event.type === "autocomplete-plus:cancel") {
            clearCachedValue();
        }

        if (event.type === "autocomplete-plus:activate" && currentOptions) {
            requestSubject.onNext(currentOptions);
        }
    });

    // Always reset if the value is a dot
    var clearCacheWithDotPrefixObservable = requestSubject
        .where(z => z.prefix === "." || (z.prefix && !_.trim(z.prefix)) || !z.prefix);

    rx.Observable.merge(bufferMovement, clearCacheWithDotPrefixObservable).subscribe(justResults);
    rx.Observable.merge(clearCacheSubject).subscribe(nextResults);

    function clearCachedValue() {
        clearCacheSubject.onNext(true);
    }

    return {
        onNext(options: RequestOptions) {
            currentOptions = options;
{'fraction_non_alphanumeric': 0.1164553272117767, 'fraction_numerical': 0.001020259437399796, 'mean_word_length': 3.048377581120944, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7316695', 'n_tokens_mistral': 1901, 'n_tokens_neox': 1834, 'n_words': 443}