<commit_before>


import os
import sys
import fcntl
import termios
import select
import errno

STDIN = sys.stdin.fileno()

ANSI_SEQUENCES = dict(
    up = '\x1b[A',
    down = '\x1b[B',
    right = '\x1b[C',
    left = '\x1b[D',
    home = '\x1bOH',
    end = '\x1bOF',
    insert = '\x1b[2~',
    delete = '\x1b[3~',
    pageUp = '\x1b[5~',
    pageDown = '\x1b[6~',
    ctrlLeft = '\x1b[1;5C',
    ctrlRight = '\x1b[1;5D',
    F1 = '\x1bOP',
    F2 = '\x1bOQ',
    F3 = '\x1bOR',
    F4 = '\x1bOS',
    F5 = '\x1b[15~',
    F6 = '\x1b[17~',
    F7 = '\x1b[18~',
    F8 = '\x1b[19~',
    F9 = '\x1b[20~',
    F10 = '\x1b[21~',
    F11 = '\x1b[23~',
    F12 = '\x1b[24~',
)

KEY_NAMES = dict((v,k) for k,v in list(ANSI_SEQUENCES.items()))
KEY_NAMES.update({
    '\x1b' : 'esc',
    '\n' : 'enter',
    ' ' : 'space',
    '\x7f' : 'backspace',
})


class RawTerminal(object):
    def __init__(self, blocking=True):
        self._blocking = blocking

    def open(self):
        # Set raw mode
        self._oldterm = termios.tcgetattr(STDIN)
        newattr = termios.tcgetattr(STDIN)
        newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
        termios.tcsetattr(STDIN, termios.TCSANOW, newattr)

        # Set non-blocking IO on stdin
        self._old = fcntl.fcntl(STDIN, fcntl.F_GETFL)
        if not self._blocking:
            fcntl.fcntl(STDIN, fcntl.F_SETFL, self._old | os.O_NONBLOCK)

    def close(self):
        # Restore previous terminal mode
        termios.tcsetattr(STDIN, termios.TCSAFLUSH, self._oldterm)
        fcntl.fcntl(STDIN, fcntl.F_SETFL, self._old)

    def get(self):
        ret = sys.stdin.read(1)
        if not ret:
            raise EOFError()
        return ret

    def wait(self):
        select.select([STDIN], [], [])

    def __enter__(self):
        self.open()
        return self

    def __exit__(self, *args):
        self.close()


def keyboard_listener(heartbeat=None):
    with RawTerminal(blocking=False) as terminal:
        # return keys
        sequence = ""
        while True:
            # wait for keys to become available
            ret, _, __ = select.select([STDIN], [], [], heartbeat)
            if not ret:
                yield "heartbeat"
                continue

            # read all available keys
            while True:
                try:
                    sequence += terminal.get()
                except EOFError:
                    break
                except IOError as e:
                    if e.errno == errno.EAGAIN:
                        break

            # handle ANSI key sequences
            while sequence:
                for seq in list(ANSI_SEQUENCES.values()):
                    if sequence[:len(seq)] == seq:
                        yield KEY_NAMES[seq]
                        sequence = sequence[len(seq):]
                        break
                # handle normal keys
                else:
                    for key in sequence:
                        yield KEY_NAMES.get(key, key)
                    sequence = ""


if __name__ == "__main__":
    for key in keyboard_listener(0.5):
        print(key)<commit_msg>keyboard - catch ctrl-a,b,d,e...<commit_after>
import os
import sys
import fcntl
import termios
import select
import errno
import string

STDIN = sys.stdin.fileno()

ANSI_SEQUENCES = dict(
    up = '\x1b[A',
    down = '\x1b[B',
    right = '\x1b[C',
    left = '\x1b[D',
    home = '\x1bOH',
    end = '\x1bOF',
    insert = '\x1b[2~',
    delete = '\x1b[3~',
    pageUp = '\x1b[5~',
    pageDown = '\x1b[6~',
    ctrlLeft = '\x1b[1;5C',
    ctrlRight = '\x1b[1;5D',
    F1 = '\x1bOP',
    F2 = '\x1bOQ',
    F3 = '\x1bOR',
    F4 = '\x1bOS',
    F5 = '\x1b[15~',
    F6 = '\x1b[17~',
    F7 = '\x1b[18~',
    F8 = '\x1b[19~',
    F9 = '\x1b[20~',
    F10 = '\x1b[21~',
    F11 = '\x1b[23~',
    F12 = '\x1b[24~',
)

for c in string.ascii_lowercase:
    ANSI_SEQUENCES['ctrl_%s' % c] = chr(ord(c) - ord('a')+1)

KEY_NAMES = dict((v,k) for k,v in list(ANSI_SEQUENCES.items()))
KEY_NAMES.update({
    '\x1b' : 'esc',
    '\n' : 'enter',
    ' ' : 'space',
    '\x7f' : 'backspace',
})


class RawTerminal(object):
    def __init__(self, blocking=True):
        self._blocking = blocking

    def open(self):
        # Set raw mode
        self._oldterm = termios.tcgetattr(STDIN)
        newattr = termios.tcgetattr(STDIN)
        newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
        termios.tcsetattr(STDIN, termios.TCSANOW, newattr)

        # Set non-blocking IO on stdin
        self._old = fcntl.fcntl(STDIN, fcntl.F_GETFL)
        if not self._blocking:
            fcntl.fcntl(STDIN, fcntl.F_SETFL, self._old | os.O_NONBLOCK)

    def close(self):
        # Restore previous terminal mode
        termios.tcsetattr(STDIN, termios.TCSAFLUSH, self._oldterm)
        fcntl.fcntl(STDIN, fcntl.F_SETFL, self._old)

    def get(self):
        ret = sys.stdin.read(1)
        if not ret:
            raise EOFError()
        return ret

    def wait(self):
        select.select([STDIN], [], [])

    def __enter__(self):
        self.open()
        return self

    def __exit__(self, *args):
        self.close()


def keyboard_listener(heartbeat=None):
    with RawTerminal(blocking=False) as terminal:
        # return keys
        sequence = ""
        while True:
            # wait for keys to become available
            ret, _, __ = select.select([STDIN], [], [], heartbeat)
            if not ret:
                yield "heartbeat"
                continue

            # read all available keys
            while True:
                try:
                    sequence += terminal.get()
                except EOFError:
                    break
                except IOError as e:
                    if e.errno == errno.EAGAIN:
                        break

            # handle ANSI key sequences
            while sequence:
                for seq in list(ANSI_SEQUENCES.values()):
                    if sequence[:len(seq)] == seq:
                        yield KEY_NAMES[seq]
                        sequence = sequence[len(seq):]
                        break
                # handle normal keys
                else:
                    for key in sequence:
                        yield KEY_NAMES.get(key, key)
                    sequence = ""


if __name__ == "__main__":
    for key in keyboard_listener(0.5):
        print(repr(key))
{'fraction_non_alphanumeric': 0.1342376052385407, 'fraction_numerical': 0.021983161833489244, 'mean_word_length': 1.6497315159025197, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, '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': '191965', 'n_tokens_mistral': 2311, 'n_tokens_neox': 2183, 'n_words': 483}