Skip to content

Instantly share code, notes, and snippets.

@FingerLiu
Created June 4, 2017 04:17
Show Gist options
  • Save FingerLiu/771296462761b16ee6d685dc725eb0b4 to your computer and use it in GitHub Desktop.
Save FingerLiu/771296462761b16ee6d685dc725eb0b4 to your computer and use it in GitHub Desktop.
curses 实现命令行聊天界面
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import curses, traceback, string
#-- Define the appearance of some interface elements
hotkey_attr = curses.A_BOLD | curses.A_UNDERLINE
menu_attr = curses.A_NORMAL
#-- Define additional constants
EXIT = 0
CONTINUE = 1
#-- Give screen module scope
screen = None
#-- Create the topbar menu
def topbar_menu(menus):
left = 2
for menu in menus:
menu_name = menu[0]
menu_hotkey = menu_name[0]
menu_no_hot = menu_name[1:]
screen.addstr(1, left, menu_hotkey, hotkey_attr)
screen.addstr(1, left+1, menu_no_hot, menu_attr)
left = left + len(menu_name) + 3
# Add key handlers for this hotkey
topbar_key_handler((string.upper(menu_hotkey), menu[1]))
topbar_key_handler((string.lower(menu_hotkey), menu[1]))
# Little aesthetic thing to display application title
screen.addstr(1, left+30,
" OC Curses Interface",
curses.A_STANDOUT)
screen.refresh()
#-- Magic key handler both loads and processes keys strokes
def topbar_key_handler(key_assign=None, key_dict={}):
if key_assign:
key_dict[ord(key_assign[0])] = key_assign[1]
else:
c = screen.getch()
if c in (curses.KEY_END, ord('!')):
return 0
elif c not in key_dict.keys():
curses.beep()
return 1
else:
return eval(key_dict[c])
def friends_view():
s = curses.newwin(38, 30, 2, 1)
s.box()
s.addstr(1, 2, 'Friends', curses.A_BOLD)
s.addstr(3, 2, 'Jone Snow', curses.A_STANDOUT)
s.addstr(4, 2, 'Sansa', curses.A_NORMAL)
s.addstr(5, 2, 'Little Finger', curses.A_NORMAL)
s.addstr(6, 2, 'Lady Gaga', curses.A_NORMAL)
s.addstr(7, 2, 'Big Brother', curses.A_NORMAL)
s.refresh()
def message_view():
s = curses.newwin(25, 89, 2, 31)
s.box()
s.addstr(1, 2, 'Message -- Jone Snow', curses.A_BOLD)
s.addstr(3, 2, 'I am the fire that burns against the cold, the light that', curses.A_NORMAL)
s.addstr(4, 2, 'brings the dawn, the horn that wakes the sleepers, the', curses.A_NORMAL)
s.addstr(5, 2, 'shield that guards the realms of men.', curses.A_NORMAL)
s.addstr(6, 2, 'I pledge my life and honor to the Night\'s Watch,', curses.A_NORMAL)
s.addstr(7, 2, 'for this night and all the nights to come.', curses.A_NORMAL)
s.refresh()
def input_view():
s = curses.newwin(13, 89, 27, 31)
s.box()
s.addstr(1, 2, 'Type your message here...', curses.A_BOLD)
s.refresh()
# s.getch()
def oc_func():
s = curses.newwin(6, 20, 2, 1)
s.box()
s.addstr(1, 2, "A", hotkey_attr)
s.addstr(1, 3, "bout OC", menu_attr)
s.addstr(2, 2, "P", hotkey_attr)
s.addstr(2, 3, "reference", menu_attr)
s.addstr(3, 2, "C", hotkey_attr)
s.addstr(3, 3, "hange account", menu_attr)
s.addstr(4, 2, "L", hotkey_attr)
s.addstr(4, 3, "og out", menu_attr)
s.refresh()
c = s.getch()
if c:
s.erase()
return CONTINUE
def edit_func():
s = curses.newwin(6, 20, 2, 7)
s.box()
s.addstr(1, 2, "C", hotkey_attr)
s.addstr(1, 4, " Cut", menu_attr)
s.addstr(2, 2, "X", hotkey_attr)
s.addstr(2, 4, " Copy", menu_attr)
s.addstr(3, 2, "V", hotkey_attr)
s.addstr(3, 4, " Paste", menu_attr)
s.addstr(4, 2, "A", hotkey_attr)
s.addstr(4, 4, " Select All", menu_attr)
s.refresh()
c = s.getch()
if c:
s.erase()
return CONTINUE
def status_func():
s = curses.newwin(6, 12, 2, 22)
s.box()
s.addstr(1, 2, "O", hotkey_attr)
s.addstr(1, 3, "line", menu_attr)
s.addstr(2, 2, "L", hotkey_attr)
s.addstr(2, 3, "eave", menu_attr)
s.addstr(3, 2, "I", hotkey_attr)
s.addstr(3, 3, "nvisible", menu_attr)
s.addstr(4, 2, "o", hotkey_attr)
s.addstr(4, 3, "ffline", menu_attr)
s.refresh()
c = s.getch()
if c:
s.erase()
return CONTINUE
def app_func():
s = curses.newwin(6, 22, 2, 31)
s.box()
s.addstr(1, 2, "S", hotkey_attr)
s.addstr(1, 3, "creen Shot", menu_attr)
s.addstr(2, 2, "E", hotkey_attr)
s.addstr(2, 3, "moji Management", menu_attr)
s.addstr(3, 2, "M", hotkey_attr)
s.addstr(3, 3, "essage Management", menu_attr)
s.refresh()
c = s.getch()
if c:
s.erase()
return CONTINUE
def help_func():
s = curses.newwin(30, 60, 5, 31)
s.box()
s.addstr(1, 16, "OC Client in Terminal V0.1", curses.A_UNDERLINE)
s.addstr(12, 10, "OC Client implemented in pure python.", menu_attr)
s.addstr(16, 10, "Use keyboard to navigate and chat!", menu_attr)
s.addstr(26, 26, "Copyright © Cloudist 2017", menu_attr | curses.A_RIGHT)
s.refresh()
c = s.getch()
if c:
s.erase()
return CONTINUE
def main(stdscr):
global screen
screen = stdscr.subwin(41, 121, 0, 0)
screen.box()
screen.hline(2, 1, curses.ACS_HLINE, 77)
screen.refresh()
# Define the topbar menus
oc_menu = ("OC", "oc_func()")
edit_menu = ("Content Edit", "edit_func()")
status_menu = ("Status", "status_func()")
app_menu = ("Application", "app_func()")
help_menu = ("Help", "help_func()")
exit_menu = ("Exit", "EXIT")
# Add the topbar menus to screen object
topbar_menu((
oc_menu, edit_menu, status_menu,
app_menu, help_menu, exit_menu
))
friends_view()
message_view()
input_view()
while topbar_key_handler():
friends_view()
message_view()
input_view()
if __name__ == '__main__':
try:
# Initialize curses
stdscr = curses.initscr()
#curses.start_color()
# Turn off echoing of keys, and enter cbreak mode,
# where no buffering is performed on keyboard input
curses.noecho()
curses.cbreak()
# In keypad mode, escape sequences for special keys
# (like the cursor keys) will be interpreted and
# a special value like curses.KEY_LEFT will be returned
stdscr.keypad(1)
main(stdscr) # Enter the main loop
# Set everything back to normal
stdscr.keypad(0)
curses.echo()
curses.nocbreak()
curses.endwin() # Terminate curses
except:
# In the event of an error, restore the terminal
# to a sane state.
stdscr.keypad(0)
curses.echo()
curses.nocbreak()
curses.endwin()
traceback.print_exc() # Print the exception
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment