[nylug-workshop] Input strategies
Not Peter
spacey at lenin.net
Fri Dec 8 01:19:57 EST 2006
(Mailman ate this, so I'm reposting it for Peter. If you posted
something that didn't come through, please repost now.
- Ron)
-------- Original Message --------
OK, here's a rough explanation of what we spent some time looking at
on tuesday:
The input method is dodgy because of how curses works with chars. The
summary of how curses (and ncurses when using the curses interface)
deals with terminal input:
a) If the terminal isn't capable of passing 8-bit characters cleanly*,
there is a mode enabled by running the screen's method
keypad(False). This tells curses that the terminal will send
special things like arrows, function keys, ctrl-<key> combinations,
etc. as sequences of two, three, four, or five 7-bit characters.
* It's worth noting that there's little or nothing that available
today that isn't 8-bit. 7-bit serial lines are rare artifacts of
the past - or toys bought by belligerant collectors who don't
have anything better to do than subject themselves to the misery
of debugging serial connections that people pretty much hated
when they were new.
b) When using 7-bit input mode, there's a huge variability in what'll
come through. As far as the documentation I've seen goes, there is
no "end-of-character" signaling, so you essentially have to get a
bunch of characters and then look for a pause. This *may* happen by
some convention with slower serial terminals, but on something like
an xterm or a linux console, you can key-mash and the input
functions don't seem to offer a way, in this mode, of
distinguishing 5 events in a row from 5 keys being hit at the same
time. The attached updated cursesdemo.py shows you this behavior
when you use app_seq1(). Unfortunately it's display is confusing
because I haven't found a good way to clear the terminal so once
you have something that's got 5 characters, you'll display 5 lines.
c) When using 8-bit mode, the python developers cheated in our
favor. They didn't bother limiting themselves to 8 bits, I think
they just figure out what's right and return the integer associated
with a character regardless of the size of the integer. This
doesn't need to rely on grabbing multiple chracters and it will
always return the correct character on modern, local devices
(xterms, linux consoles, vty's under screen, etc). Use app_seq2()
to see how this behaves.
So I've hacked dtk on my system here to change the input method to use
a more straightforward dictionary for this. The old way is still
included and would probably be useful for use over an old serial link
by a masochistic unix geezer (and I mean geezer independant of anyones
age). It's probably something to be enabled via a keyword argument -
perhaps in the future terminal capabilities would be detected and set
the proper input mode if a 7-bit terminal came up and bit someone.
Also, I've started adding logging. The kind of logging I'm doing
should probably become more centralized, but it's something like this
(from CursesEngine.py's __init__()):
if wantslog == True:
self.logger = logging.getLogger('dtk.CursesEngine')
self.hndlr = logging.FileHandler('dtk.CursesEngine.log')
self.hndlr.setFormatter(logging.Formatter('%(asctime)s
%(levelname)s %(message)s'))
self.logger.addHandler(self.hndlr)
try:
if kwargs['loglevel']:
self.logger.setLevel(kwargs['loglevel'])
except KeyError: # Not defined
self.logger.setLevel(logging.WARNING)
In principle this should create a logger local to the module that,
when it's asked to, will create a file called "dtk.CursesEngine.log"
that will contain log messages from the curses engine when it's
initialized with a keyword argument of "wantslog" set to True. This is
not necessarily the right way to do this because it means having to
change the invocation of CursesEngine(), which is bad, but I think
that a DtkLogging class to wrap the logging functionality that could
be called on by all the dtk modules could be an easy way to globally
define logging, and it could add granular configuration
(eg. it could have declarations like
DtkLogging.CursesEngineLogging = True
DtkLogging.CursesEngineLoglevel = logging.DEBUG
and when CursesEngine runs
import DtkLogging
it can check to see if its supposed to log, supposed to log to a
separate file, what log level should be invoked, etc. I've attached a
diff to CursesEngine.py to this message. Dan maybe you could let me
know what you think. I know you said you were working on the logging,
but I'm not brave enough to see how to keep account of rows etc. in
the TextEditor yet (it doesn't seem to scroll when typing past the
last line in the window), and to approach that I need more logging.
Happy holidays! I think I may be out of town for the next meeting, but
I'm hoping that other people can look at the attached and let me know
if I missed anything regarding the differences in key input methods.
-Peter
--
The 5 year plan: In five years we'll make up another plan.
Or just re-use this one.
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: CursesEngine20061207.diff
Url: http://nylug.org/pipermail/nylug-workshop/attachments/20061208/d08e0311/attachment.diff
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cursesdemo.py
Type: text/x-python
Size: 2610 bytes
Desc: not available
Url : http://nylug.org/pipermail/nylug-workshop/attachments/20061208/d08e0311/attachment.py
More information about the nylug-workshop
mailing list