2015-05-15 19 views
10

Quindi sto scrivendo un progetto in cui eseguo un programma che riceve/invia costantemente messaggi ad altri computer che eseguono lo stesso programma.Mantieni stdin line nella parte superiore o inferiore della schermata del terminale

Il destinatario/mittente di dati è in esecuzione su un thread e stampa su stdout. Ottengo cose come questa:

[INFO] User 'blah' wants to send message to you. 
[INFO] some other info 
[MSG REC] Message 'hello' received from blah. 

Ora il problema è che a volte vorrei inserire i comandi nel terminale, il problema è quando provo ad inserire un comando e un nuovo messaggio informazioni o MSG REC viene stampato su stdout . Ho comandi come quit e status ecc.

>> indica la riga di input.

Qualcosa di simile può accadere:

[INFO] User 'blah' wants to send message to you. 
[INFO] some other info 
[MSG REC] Message 'hello' received from blah. 
>> stat[MSG REC] Message 'sup' received from Bob. 
us 

Poi vorrei premere invio e il comando viene eseguito status ma sembra così povero nel terminale. Un messaggio appare ogni 2-4 secondi, quindi questo è un problema. C'è un buon modo per risolvere questo? Ho provato a usare i cursori ANSI per provare a inserire una nuova riga prima dell'ultima riga in modo che l'ultima riga rimanga sempre come linea di input e potrei digitare "stat", attendere un po 'e terminarla con "us" senza problemi.

Ho anche visto la gente consigliare curses ma tentare di integrarlo con il mio programma ha completamente incasinato la formattazione del mio output tra le altre cose (e penso che forse il suo eccessivo).

Quindi non v'è un modo semplice per rendere il filo inserire nuova MSG REC linee 1 riga sopra l'ultima riga in modo da l'ultima riga sarebbe sempre rimanere come la linea di ingresso con >> e qualsiasi altra cosa che ho digitato.

Utilizzando Python2.7 su Linux.

MODIFICA: modifica apportata a James Mills risposta: Ho dovuto utilizzarlo ogni volta che il mio thread stava stampando una nuova riga.

myY, myX = stdscr.getyx();   
str = "blah blah"; #my message I want to print 
stdscr.addstr(len(lines), 0, str) 
lines.append(str) 
stdscr.move(myY, myX) #move cursor back to proper position 

risposta

7

Ecco un esempio di base:

Codice:

#!/usr/bin/env python 

from string import printable 
from curses import erasechar, wrapper 

PRINTABLE = map(ord, printable) 

def input(stdscr): 
    ERASE = input.ERASE = getattr(input, "ERASE", ord(erasechar())) 
    Y, X = stdscr.getyx() 
    s = [] 

    while True: 
     c = stdscr.getch() 

     if c in (13, 10): 
      break 
     elif c == ERASE: 
      y, x = stdscr.getyx() 
      if x > X: 
       del s[-1] 
       stdscr.move(y, (x - 1)) 
       stdscr.clrtoeol() 
       stdscr.refresh() 
     elif c in PRINTABLE: 
      s.append(chr(c)) 
      stdscr.addch(c) 

    return "".join(s) 

def prompt(stdscr, y, x, prompt=">>> "): 
    stdscr.move(y, x) 
    stdscr.clrtoeol() 
    stdscr.addstr(y, x, prompt) 
    return input(stdscr) 

def main(stdscr): 
    Y, X = stdscr.getmaxyx() 

    lines = [] 
    max_lines = (Y - 3) 

    stdscr.clear() 

    while True: 
     s = prompt(stdscr, (Y - 1), 0) # noqa 
     if s == ":q": 
      break 

     # scroll 
     if len(lines) > max_lines: 
      lines = lines[1:] 
      stdscr.clear() 
      for i, line in enumerate(lines): 
       stdscr.addstr(i, 0, line) 

     stdscr.addstr(len(lines), 0, s) 
     lines.append(s) 

     stdscr.refresh() 

wrapper(main) 

Questo imposta fondamentalmente una demo maledice un'applicazione che richiede all'utente per l'input e visualizza il prompt a (24, 0) . La demo termina con l'utente che entra in :q. Per ogni altro input, aggiunge l'input alla parte superiore dello schermo. Godere! (<BACKSAPCE> funziona anche!) :)

Vedere: curses; tutta l'API che ho usato in questo esempio è direttamente da questa libreria standard. Sebbene l'uso di curses possa o meno essere un "overkill" IHMO, consiglierei l'uso di urwid, specialmente se la complessità della tua applicazione inizia a superare le normali "maledizioni".

+0

Ho dovuto aggiungere 'curses.KEY_BACKSPACE' per correggere i backspaces sul mio computer. Anche questo non funziona come voglio, mentre il mio thread sta stampando nuove linee ogni secondo (l'ho passato 'stdscr' come argomento e reso le linee globali), sposta il cursore alla fine della linea stampata Sto digitando è alla fine dell'ultima riga stampata e non nella parte inferiore vicino a '>>>' – Mohammad

+1

Okay è riuscito a risolverlo e ora funziona come voglio! Ho appena dovuto cambiare il modo in cui il mio thread stava stampando nuove righe, in modo da spostare il cursore nella posizione corretta dopo averlo stampato. Ho aggiunto la modifica al post originale. – Mohammad

+0

Sono contento che questo ti abbia aiutato a risolvere i tuoi problemi! L'uso di '' curses.KEY_BACKSPACE'' non funziona sul mio sistema :) –

Problemi correlati