<commit_before>import vim

import os
import re
import subprocess
import xml.etree.ElementTree as ET
import signal

from collections import deque

import vimbufsync
vimbufsync.check_version("0.1.0", who="coquille")

#: Pipe used to discuss with coqtop
coqtop = None

#: See vimbufsync ( https://github.com/def-lkb/vimbufsync )
saved_sync = None

#: Keeps track of what have been checked by Coq, and what is waiting to be
#: checked.
encountered_dots = []
send_queue = deque([])

error_at = None

info_msg = None

###################
# synchronization #
###################

def sync():
    global saved_sync
    curr_sync = vimbufsync.sync()
    if not saved_sync or curr_sync.buf() != saved_sync.buf():
        _reset()
    else:
        (line, col) = saved_sync.pos()
        rewind_to(line - 1, col) # vim indexes from lines 1, coquille from 0
    saved_sync = curr_sync

def _reset():
    global saved_sync, encountered_dots, info_msg, error_at, send_queue
    encountered_dots = []
    send_queue = deque([])
    saved_sync = None
    error_at   = None
    info_msg   = None
    reset_color()

#####################
# exported commands #
#####################

def kill_coqtop():
    global coqtop
    if coqtop:
        try:
            coqtop.terminate()
            coqtop.communicate()
        except OSError:
            pass
        coqtop = None
    _reset()

def ignore_sigint():
    signal.signal(signal.SIGINT, signal.SIG_IGN)

def restart_coq(*args):
    global coqtop
    if coqtop: kill_coqtop()
    try:
        coqtop = subprocess.Popen(
                ["coqtop", "-ideslave"] + list(args),
                stdin = subprocess.PIPE,
                stdout = subprocess.PIPE,
                preexec_fn = ignore_sigint
                )
    except OSError:
        print("Error: couldn't launch coqtop")

def coq_rewind(steps=1):
    global encountered_dots, info_msg

    if steps < 1 or encountered_dots == []:
        return

    if coqtop is None:
        print("Error: Coqtop isn't running. Are you sure you called :CoqLaunch?")
        return

    request = ET.Element('call')
    request.set('val', 'rewind')
    request.set('steps', str(steps))

    send_cmd(request)

    response = get_answer()

    if response is None:
        vim.command("call coquille#KillSession()")
        print('ERROR: the Coq process died')
        return

    if response.get('val') == 'good':
        additional_steps = response.find('int') # should never be none
        nb_removed = steps + int(additional_steps.text)
        encountered_dots = encountered_dots[:len(encountered_dots) - nb_removed]
    else:
        info_msg = "[COQUILLE ERROR] Unexpected answer:\n\n%s" % ET.tostring(response)

    refresh()

def coq_to_cursor():
    if coqtop is None:
        print("Error: Coqtop isn't running. Are you sure you called :CoqLaunch?")
        return

    sync()

    (cline, ccol) = vim.current.window.cursor
    (line, col)  = encountered_dots[-1] if encountered_dots else (0,0)

    if cline < line or (cline == line and ccol < col):
        rewind_to(cline - 1, ccol)
    else:
        while True:
            r = _get_message_range((line, col))
            if r is not None and r['stop'] < (cline - 1, ccol):
                line = r['stop'][0]
                col  = r['stop'][1] + 1<commit_msg>better handling of limit case in CoqToCursor ( fix #14 )<commit_after>import vim

import os
import re
import subprocess
import xml.etree.ElementTree as ET
import signal

from collections import deque

import vimbufsync
vimbufsync.check_version("0.1.0", who="coquille")

#: Pipe used to discuss with coqtop
coqtop = None

#: See vimbufsync ( https://github.com/def-lkb/vimbufsync )
saved_sync = None

#: Keeps track of what have been checked by Coq, and what is waiting to be
#: checked.
encountered_dots = []
send_queue = deque([])

error_at = None

info_msg = None

###################
# synchronization #
###################

def sync():
    global saved_sync
    curr_sync = vimbufsync.sync()
    if not saved_sync or curr_sync.buf() != saved_sync.buf():
        _reset()
    else:
        (line, col) = saved_sync.pos()
        rewind_to(line - 1, col) # vim indexes from lines 1, coquille from 0
    saved_sync = curr_sync

def _reset():
    global saved_sync, encountered_dots, info_msg, error_at, send_queue
    encountered_dots = []
    send_queue = deque([])
    saved_sync = None
    error_at   = None
    info_msg   = None
    reset_color()

#####################
# exported commands #
#####################

def kill_coqtop():
    global coqtop
    if coqtop:
        try:
            coqtop.terminate()
            coqtop.communicate()
        except OSError:
            pass
        coqtop = None
    _reset()

def ignore_sigint():
    signal.signal(signal.SIGINT, signal.SIG_IGN)

def restart_coq(*args):
    global coqtop
    if coqtop: kill_coqtop()
    try:
        coqtop = subprocess.Popen(
                ["coqtop", "-ideslave"] + list(args),
                stdin = subprocess.PIPE,
                stdout = subprocess.PIPE,
                preexec_fn = ignore_sigint
                )
    except OSError:
        print("Error: couldn't launch coqtop")

def coq_rewind(steps=1):
    global encountered_dots, info_msg

    if steps < 1 or encountered_dots == []:
        return

    if coqtop is None:
        print("Error: Coqtop isn't running. Are you sure you called :CoqLaunch?")
        return

    request = ET.Element('call')
    request.set('val', 'rewind')
    request.set('steps', str(steps))

    send_cmd(request)

    response = get_answer()

    if response is None:
        vim.command("call coquille#KillSession()")
        print('ERROR: the Coq process died')
        return

    if response.get('val') == 'good':
        additional_steps = response.find('int') # should never be none
        nb_removed = steps + int(additional_steps.text)
        encountered_dots = encountered_dots[:len(encountered_dots) - nb_removed]
    else:
        info_msg = "[COQUILLE ERROR] Unexpected answer:\n\n%s" % ET.tostring(response)

    refresh()

def coq_to_cursor():
    if coqtop is None:
        print("Error: Coqtop isn't running. Are you sure you called :CoqLaunch?")
        return

    sync()

    (cline, ccol) = vim.current.window.cursor
    (line, col)  = encountered_dots[-1] if encountered_dots else (0,0)

    if cline < line or (cline == line and ccol < col):
        rewind_to(cline - 1, ccol)
    else:
        while True:
            r = _get_message_range((line, col))
            if r is not None and r['stop'] <= (cline - 1, ccol):
                line = r['stop'][0]
                col  = r['stop'][1] + 1
{'fraction_non_alphanumeric': 0.12931293129312932, 'fraction_numerical': 0.0051005100510051, 'mean_word_length': 2.570969469737547, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, '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': '4969755', 'n_tokens_mistral': 2215, 'n_tokens_neox': 2136, 'n_words': 576}