Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow loop cycling through Bullet items #53

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 19 additions & 12 deletions bullet/client.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import sys
from .charDef import *
from . import colors
from . import utils
from . import cursor
from . import keyhandler
import readline
import re

if sys.platform == 'win32':
from .winCharDef import *
else:
from .charDef import *

# Reusable private utility class
class myInput:
def __init__(self,
Expand Down Expand Up @@ -89,7 +92,7 @@ def input(self):
i == PG_DOWN_KEY or \
i == TAB_KEY or \
i == UNDEFINED_KEY:
return
return i
elif i == BACK_SPACE_KEY:
if self.moveCursor(self.pos - 1):
self.deleteChar()
Expand Down Expand Up @@ -171,27 +174,31 @@ def printBullet(self, idx):

@keyhandler.register(ARROW_UP_KEY)
def moveUp(self):
utils.clearLine()
old_pos = self.pos
if self.pos - 1 < 0:
return
self.pos = len(self.choices) - 1
self.printBullet(old_pos)
utils.moveCursorDown(len(self.choices) - 1)
else:
utils.clearLine()
old_pos = self.pos
self.pos -= 1
self.printBullet(old_pos)
utils.moveCursorUp(1)
self.printBullet(self.pos)
self.printBullet(self.pos)

@keyhandler.register(ARROW_DOWN_KEY)
def moveDown(self):
utils.clearLine()
old_pos = self.pos
if self.pos + 1 >= len(self.choices):
return
self.pos = 0
self.printBullet(old_pos)
utils.moveCursorUp(len(self.choices) - 1)
else:
utils.clearLine()
old_pos = self.pos
self.pos += 1
self.printBullet(old_pos)
utils.moveCursorDown(1)
self.printBullet(self.pos)
self.printBullet(self.pos)

@keyhandler.register(NEWLINE_KEY)
def accept(self):
Expand Down Expand Up @@ -438,7 +445,7 @@ def launch(self):
utils.forceWrite(' ' * len(result))
utils.forceWrite('\b' * len(result))
else:
break
return result
else:
while True:
result = sess.input()
Expand Down
168 changes: 111 additions & 57 deletions bullet/utils.py
Original file line number Diff line number Diff line change
@@ -1,112 +1,165 @@
import os
import sys
import tty, termios
import string
import shutil
from .charDef import *
import string
import sys

from . import colors

COLUMNS, _ = shutil.get_terminal_size() ## Size of console

def mygetc():
''' Get raw characters from input. '''
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch

def getchar():
''' Character input parser. '''
c = mygetc()
if ord(c) == LINE_BEGIN_KEY or \
ord(c) == LINE_END_KEY or \
ord(c) == TAB_KEY or \
ord(c) == INTERRUPT_KEY or \
ord(c) == NEWLINE_KEY:
return c

elif ord(c) == BACK_SPACE_KEY:
if sys.platform == 'win32':
import colorama
from .winCharDef import *
import msvcrt

colorama.init()


def mygetc():
'''Gets raw characters from input on Windows'''
c = msvcrt.getch()
c = c.decode('mbcs')

return c

elif ord(c) == ESC_KEY:
combo = mygetc()
if ord(combo) == MOD_KEY_INT:
key = mygetc()
if ord(key) >= MOD_KEY_BEGIN - MOD_KEY_FLAG and ord(key) <= MOD_KEY_END - MOD_KEY_FLAG:
if ord(mygetc()) == MOD_KEY_DUMMY:
return chr(ord(key) + MOD_KEY_FLAG)
else:
return UNDEFINED_KEY
elif ord(key) >= ARROW_KEY_BEGIN - ARROW_KEY_FLAG and ord(key) <= ARROW_KEY_END - ARROW_KEY_FLAG:
return chr(ord(key) + ARROW_KEY_FLAG)


def getchar():
'''Parses input on Windows'''
c = mygetc()
nonesc_characters = [LINE_BEGIN_KEY, LINE_END_KEY, TAB_KEY,
INTERRUPT_KEY, NEWLINE_KEY, BACK_SPACE_KEY]
if ord(c) in nonesc_characters:
return c

elif ord(c) == ESC_KEY:
combo = mygetc()
if ord(combo) in [
ARROW_UP_KEY,
ARROW_DOWN_KEY,
ARROW_LEFT_KEY,
ARROW_RIGHT_KEY,
]:
return combo
else:
if c in string.printable:
return c
else:
return UNDEFINED_KEY
else:
return getchar()

else:
if c in string.printable:
else:
import tty, termios
from .charDef import *


def mygetc():
''' Get raw characters from input. '''
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch


def getchar():
''' Character input parser. '''
c = mygetc()
if ord(c) == LINE_BEGIN_KEY or \
ord(c) == LINE_END_KEY or \
ord(c) == TAB_KEY or \
ord(c) == INTERRUPT_KEY or \
ord(c) == NEWLINE_KEY:
return c

elif ord(c) == BACK_SPACE_KEY:
return c

elif ord(c) == ESC_KEY:
combo = mygetc()
if ord(combo) == MOD_KEY_INT:
key = mygetc()
if ord(key) >= MOD_KEY_BEGIN - MOD_KEY_FLAG and ord(key) <= MOD_KEY_END - MOD_KEY_FLAG:
if ord(mygetc()) == MOD_KEY_DUMMY:
return chr(ord(key) + MOD_KEY_FLAG)
else:
return UNDEFINED_KEY
elif ord(key) >= ARROW_KEY_BEGIN - ARROW_KEY_FLAG and ord(key) <= ARROW_KEY_END - ARROW_KEY_FLAG:
return chr(ord(key) + ARROW_KEY_FLAG)
else:
return UNDEFINED_KEY
else:
return getchar()

else:
return UNDEFINED_KEY
if c in string.printable:
return c
else:
return UNDEFINED_KEY

return UNDEFINED_KEY

# Basic command line functions

def moveCursorLeft(n):
''' Move cursor left n columns. '''
forceWrite("\033[{}D".format(n))


def moveCursorRight(n):
''' Move cursor right n columns. '''
forceWrite("\033[{}C".format(n))



def moveCursorUp(n):
''' Move cursor up n rows. '''
forceWrite("\033[{}A".format(n))


def moveCursorDown(n):
''' Move cursor down n rows. '''
forceWrite("\033[{}B".format(n))


def moveCursorHead():
''' Move cursor to the start of line. '''
forceWrite("\r")
# if the line is full, \r on Windows moves cursor to
# the next line, so we print \b first
forceWrite("\b\r")


def clearLine():
''' Clear content of one line on the console. '''
forceWrite(" " * COLUMNS)
forceWrite(" " * COLUMNS + '\b')
moveCursorHead()



def clearConsoleUp(n):
''' Clear n console rows (bottom up). '''
''' Clear n console rows (bottom up). '''
for _ in range(n):
clearLine()
moveCursorUp(1)


def clearConsoleDown(n):
''' Clear n console rows (top down). '''
''' Clear n console rows (top down). '''
for _ in range(n):
clearLine()
moveCursorDown(1)
moveCursorUp(n)

def forceWrite(s, end = ''):

def forceWrite(s, end=''):
''' Dump everthing in the buffer to the console. '''
sys.stdout.write(s + end)
sys.stdout.flush()


def cprint(
s: str,
color: str = colors.foreground["default"],
on: str = colors.background["default"],
s: str,
color: str = colors.foreground["default"],
on: str = colors.background["default"],
end: str = '\n'
):
):
''' Colored print function.
Args:
s: The string to be printed.
Expand All @@ -116,4 +169,5 @@ def cprint(
Returns:
None
'''
forceWrite(on + color + s + colors.RESET, end = end)

forceWrite(on + color + s + colors.RESET, end=end)
25 changes: 25 additions & 0 deletions bullet/winCharDef.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import sys

# Keyboard mapping macros
LINE_BEGIN_KEY = 1
LINE_END_KEY = 5
TAB_KEY = 9
NEWLINE_KEY = 13
ESC_KEY = 224 # 27?
BACK_SPACE_KEY = 8

ARROW_UP_KEY = 72
ARROW_DOWN_KEY = 80
ARROW_LEFT_KEY = 75
ARROW_RIGHT_KEY = 77
HOME_KEY = 71
END_KEY = 79
PG_UP_KEY = 73
PG_DOWN_KEY = 81
DELETE_KEY = 83

UNDEFINED_KEY = sys.maxsize
BEEP_CHAR = 7
BACK_SPACE_CHAR = 8
SPACE_CHAR = 32
INTERRUPT_KEY = 3
7 changes: 6 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@
author='Mckinsey666',
license='MIT',
packages=find_packages(),
)
extras_require={
":sys_platform=='win32'": [
'colorama>=0.4.0, <=0.4.1'
]
}
)