Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /jana2/src/python/plugins/janapy/ijana.py was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 
0002 # Copyright 2020, Jefferson Science Associates, LLC.
0003 # Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 import sys
0006 import time
0007 import tty
0008 import termios
0009 import select
0010 import fcntl
0011 import struct
0012 import jana
0013 
0014 #------------------ ANSI Escape sequences ------------------
0015 
0016 RESET   = u'\u001b[0m'
0017 BLACK   = u'\u001b[30m'
0018 RED     = u'\u001b[31m'
0019 GREEN   = u'\u001b[32m'
0020 YELLOW  = u'\u001b[33m'
0021 BLUE    = u'\u001b[34m'
0022 MAGENTA = u'\u001b[35m'
0023 CYAN    = u'\u001b[36m'
0024 WHITE   = u'\u001b[37m'
0025 
0026 BRIGHT_BLACK   = u'\u001b[90m'
0027 BRIGHT_RED     = u'\u001b[91m'
0028 BRIGHT_GREEN   = u'\u001b[92m'
0029 BRIGHT_YELLOW  = u'\u001b[93m'
0030 BRIGHT_BLUE    = u'\u001b[94m'
0031 BRIGHT_MAGENTA = u'\u001b[95m'
0032 BRIGHT_CYAN    = u'\u001b[96m'
0033 BRIGHT_WHITE   = u'\u001b[97m'
0034 
0035 BACKGROUND_BLACK   = u'\u001b[40m'
0036 BACKGROUND_RED     = u'\u001b[41m'
0037 BACKGROUND_GREEN   = u'\u001b[42m'
0038 BACKGROUND_YELLOW  = u'\u001b[43m'
0039 BACKGROUND_BLUE    = u'\u001b[44m'
0040 BACKGROUND_MAGENTA = u'\u001b[45m'
0041 BACKGROUND_CYAN    = u'\u001b[46m'
0042 BACKGROUND_WHITE   = u'\u001b[47m'
0043 
0044 BOLD      = u'\u001b[1m'
0045 UNDERLINE = u'\u001b[4m'
0046 REVERESED = u'\u001b[7m'
0047 
0048 def UP(n)              : sys.stdout.write( u'\u001b['+str(n)+'A' )
0049 def DOWN(n)            : sys.stdout.write( u'\u001b['+str(n)+'B' )
0050 def RIGHT(n)           : sys.stdout.write( u'\u001b['+str(n)+'C' )
0051 def LEFT(n)            : sys.stdout.write( u'\u001b['+str(n)+'D' )
0052 def CLEAR()            : sys.stdout.write( u'\u001b[2J' )
0053 def CLEARLINE()        : sys.stdout.write( u'\u001b[0K' )
0054 def HOME()             : sys.stdout.write( u'\u001b[;H' )
0055 def MOVETO(X,Y)        : sys.stdout.write( u'\u001b[%d;%dH' % (int(Y), int(X)) )
0056 def PRINTAT(X,Y,S)     : MOVETO(X,Y) ; sys.stdout.write( S )
0057 def PRINTCENTERED(Y,S) : MOVETO( (NCOLS-len(S))/2 , Y ) ; sys.stdout.write( S )
0058 
0059 #-------------------- CLI Commands -------------------------
0060 COMMANDS = {}
0061 COMMANDS['help'] = 1
0062 #-----------------------------------------------------------
0063 
0064 #------------------------------
0065 # draw_banner
0066 #------------------------------
0067 def draw_banner():
0068     
0069     # Get terminal size and store in globals
0070     global NROWS, NCOLS
0071     NROWS, NCOLS, hp, wp = struct.unpack('HHHH', fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, struct.pack('HHHH', 0, 0, 0, 0)))
0072     
0073     banner_height = 15
0074 
0075     # Make sure we have enough lines to draw banner. Inform user if not
0076     if NROWS<banner_height+5 or NCOLS<60:
0077         mess = 'Please make terminal '
0078         if NROWS<banner_height+5:
0079             mess += 'taller'
0080             if NCOLS<60: mess += ' and wider'
0081         if NCOLS<60: mess += 'wider'
0082         MOVETO(1,1)
0083         CLEARLINE()
0084         sys.stdout.write( REVERESED )
0085         PRINTCENTERED(1, mess)
0086         sys.stdout.write( RESET )
0087         MOVETO(1,NROWS)
0088         sys.stdout.flush()
0089         return
0090 
0091     # Draw border/background
0092     sys.stdout.write( BACKGROUND_MAGENTA + BRIGHT_WHITE + BOLD  )
0093     PRINTAT( 1, 1, '-'*NCOLS)
0094     for i in range(2, banner_height): PRINTAT( 1, i, '|' + ' '*(NCOLS-2) + '|')
0095     PRINTAT( 1, banner_height, '-'*NCOLS)
0096 
0097     # Draw status
0098     PRINTAT( 3, 2, 'Num. Events Processed: %d' % jana.GetNeventsProcessed() )
0099     #PRINTAT( 3, 3, ' Num. Tasks Completed: %d' % jana.GetNtasksCompleted() ) # This no longer exists
0100     PRINTAT( 3, 4, '           Num. Cores: %d' % jana.GetNcores() )
0101     PRINTAT( 3, 5, '        Num. JThreads: %d' % jana.GetNThreads() )
0102 
0103     PRINTAT( NCOLS/2, 2, 'Rate: %5.0fHz (%5.0fHz avg.)' % (jana.GetInstantaneousRate(), jana.GetIntegratedRate()) )
0104 
0105     # Cursor is repositioned and stdout flushed in command_line after calling this
0106     # so no need to do it here. Just reset to default drawing options.
0107     sys.stdout.write( RESET )
0108 
0109 #------------------------------
0110 # print_help
0111 #------------------------------
0112 def print_help():
0113     print('\n JANA Python Interactive CLI Help')
0114     print('\r------------------------------------')
0115     print('\r banner [on/off]    set banner on/off (def. on)"')
0116     print('\r exit               same as "quit"')
0117     print('\r help               print this message')
0118     print('\r history            print history of this session')
0119     print('\r nthreads [N]       get or set the number of processing threads')
0120     print('\r parameter cmd ...  get/set/list config. parameters')
0121     print('\r quit               stop data processing and quit the program')
0122     print('\r resume             resume data processing')
0123     print('\r status             print some status info')
0124     print('\r stop               pause data processing')
0125 
0126 #------------------------------
0127 # process_command
0128 #------------------------------
0129 def process_command( input ):
0130     global CLI_ACTIVE, BANNER_ON, mode
0131 
0132     stripped = input.rstrip()
0133     tokens = input.rstrip().split()
0134     if len(tokens) < 1: return
0135     cmd = tokens[0]
0136     args = tokens[1:]
0137     
0138     print('processing command: ' + ' '.join(tokens))
0139     LEFT(1000)
0140 
0141     #--- banner
0142     if cmd=='banner':
0143         if len(args) == 0:
0144             print('command banner requires you to specify "on" or "off". (see help for details)')
0145         elif args[0] == 'on' : BANNER_ON = True
0146         elif args[0] == 'off': BANNER_ON = False
0147         else: print('command banner requires you to specify "on" or "off". (see help for details)')
0148     #--- exit, quit
0149     elif cmd=='exit' or cmd=='quit':
0150         CLI_ACTIVE = False
0151         jana.Quit()
0152     #--- help
0153     elif cmd=='help':
0154         print_help()
0155     #--- history
0156     elif cmd=='history':
0157         idx = 0
0158         for h in history:
0159             print('%3d %s\r' % (idx, h))
0160             idx += 1
0161         print('%3d %s\r' % (idx, ' '.join(tokens) ) ) # include this history command which will be added below
0162     #--- nthreads
0163     elif cmd=='nthreads':
0164         if len(args) == 0:
0165             print('Number of JThreads: %d' % jana.GetNThreads())
0166         elif len(args)==1:
0167             prev = jana.SetNThreads( int(args[0]) )
0168             print('Number of JThreads set to: %d (was %d)' %  (int(args[0]), prev))
0169         else:
0170             print('nthreads takes either 0 or 1 argument (see help for details)')
0171     #--- parameter
0172     elif cmd=='parameter':
0173         if len(args) == 0:
0174             print('command parameter requires arguments. (see help for details)')
0175         elif args[0] == 'get':
0176             if len(args)==2:
0177                 print('%s: %s' % (args[1], jana.GetParameterValue(args[1])))
0178             else:
0179                 print('command parameter get requires exactly 1 argument! (see help for details)')
0180         elif args[0] == 'set':
0181             if len(args)==3:
0182                 jana.SetParameterValue(args[1], args[2])
0183             else:
0184                 print('command parameter set requires exactly 2 arguments! (see help for details)')
0185         elif args[0] == 'list':
0186             if len(args)==1:
0187                 jana.PrintParameters(True)
0188             else:
0189                 print('command parameter list requires no arguments! (see help for details)')
0190     #--- resume
0191     elif cmd=='resume':
0192         jana.Resume()
0193         print('event processing resumed')
0194     #--- status
0195     elif cmd=='status':
0196         jana.PrintStatus()
0197         print('')
0198     #--- stop
0199     elif cmd=='stop':
0200         jana.Stop(True)
0201         print('event processing stopped after %d events (use "resume" to start again)' % jana.GetNeventsProcessed())
0202     #--- unknown command
0203     else:
0204         print('Unknown command: ' + cmd)
0205         return
0206 
0207     history.append( ' '.join(tokens) ) # add to history
0208 
0209 
0210 #------------------------------
0211 # tab_complete
0212 #------------------------------
0213 def tab_complete( input ):
0214     return input
0215 
0216 #------------------------------
0217 # syntax_highlight
0218 #------------------------------
0219 def syntax_highlight(input):
0220     stripped = input.rstrip()
0221     return stripped + RED + " " *  (len(input) - len(stripped)) + RESET
0222 
0223 #------------------------------
0224 # command_line
0225 #------------------------------
0226 def command_line():
0227 
0228     global CLI_ACTIVE, history, mode, BANNER_ON
0229 
0230     # Record tty settings so we can restore them when finished
0231     # processing the CLI
0232     mode = termios.tcgetattr(sys.stdin)
0233     
0234     # Wait for first event to process so all messages are printed
0235     # before switching to "raw" mode which screws up newlines
0236     while jana.GetNeventsProcessed()<1: time.sleep(1)
0237 
0238     # Set to raw mode so single characters get passed to us as they are typed
0239     tty.setraw(sys.stdin)
0240 
0241     prompt = 'jana> '
0242     highlighted_prompt = BOLD+prompt+RESET
0243 
0244     CLI_ACTIVE = True
0245     BANNER_ON  = True
0246     history    = []
0247     last_draw_time = 0
0248 
0249     while CLI_ACTIVE and not jana.IsDrainingQueues(): # loop for each line
0250         # Define data-model for an input-string with a cursor
0251         input = ""
0252         index = 0
0253         input_save = ""
0254         history_index = len(history)
0255         sys.stdout.write(highlighted_prompt)
0256         sys.stdout.flush()
0257         while CLI_ACTIVE and not jana.IsDrainingQueues(): # loop for each character
0258         
0259             # Redraw the screen periodically
0260             if BANNER_ON and (time.time() - last_draw_time > 1):
0261                 draw_banner()
0262                 MOVETO(1,NROWS)
0263                 if index >= 0: RIGHT( index+len(prompt) ) ; sys.stdout.flush()
0264                 last_draw_time = time.time()
0265 
0266             # Wait for a character to be typed. 0.100 is timeout in seconds
0267             # Doing this first allows us to check if the app is quitting
0268             # even if the user is not typing so *maybe* we can restore the
0269             # termios settings before the final report is printed. It also
0270             # allows us to update the screen periodically when nothing is
0271             # being typed.
0272             i, o, e = select.select( [sys.stdin], [], [], 0.100 )
0273             if not i: continue  # nothing was typed
0274 
0275             char = ord(sys.stdin.read(1)) # read one char and get char code
0276             
0277             # Manage internal data-model
0278             if char == 3: return    # CTRL-C
0279             elif char in {10, 13}: break # LF or CR
0280             elif char ==  9:        # TAB
0281                 rindex = len(input) - index
0282                 input = tab_complete(input)
0283                 index = len(input) - rindex
0284             elif 32 <= char <= 126: # Non-special character
0285                 input = input[:index] + chr(char) + input[index:]
0286                 index += 1
0287             elif char == 127:       # Delete/Backspace
0288                 input = input[:index-1] + input[index:]
0289                 index -= 1
0290             elif char == 27:        # Left or right arrow start
0291                 next1, next2 = ord(sys.stdin.read(1)), ord(sys.stdin.read(1))
0292                 if next1==91 and next2==68: index = max(0, index - 1)    # Left arrow
0293                 if next1==91 and next2==67: index = min(len(input), index + 1)    # Right arrow
0294                 if next1==91 and next2==66:                              # Down arrow
0295                     if history_index < (len(history)-1):
0296                         history_index += 1
0297                         input = history[ history_index ]
0298                         index = len(input)
0299                     elif history_index == (len(history)-1):
0300                         history_index += 1
0301                         input = input_save
0302                         index = len(input)
0303 
0304                 if next1==91 and next2==65:                              # Up arrow
0305                     if history_index > 0:
0306                         if history_index == len(history): input_save = input
0307                         history_index -= 1
0308                         input = history[ history_index ]
0309                         index = len(input)
0310 
0311 #           else:
0312 #               print '\nunknown char: %d\n' % int(char)
0313 #               sys.stdout.flush()
0314 
0315             # Print current input-string
0316             MOVETO(1,NROWS)
0317             CLEARLINE()
0318             sys.stdout.write(highlighted_prompt + syntax_highlight(input))
0319             MOVETO(1,NROWS)
0320             if index >= 0: RIGHT( index+len(prompt) )
0321             sys.stdout.flush()
0322         
0323         # Process one input line
0324         print('')
0325         MOVETO(1,NROWS)
0326         termios.tcsetattr(sys.stdin, termios.TCSAFLUSH, mode)
0327         process_command( input )
0328         tty.setraw(sys.stdin)
0329         MOVETO(1,NROWS)
0330         sys.stdout.flush()
0331         input = ""
0332         index = 0
0333         last_draw_time = 0 # force banner to redraw on next iteration
0334 
0335     # Restore terminal settings
0336     termios.tcsetattr(sys.stdin, termios.TCSAFLUSH, mode)
0337     print('\nCLI exiting ...\n')
0338 
0339 #===========================================================
0340 #                         MAIN
0341 
0342 jana.SetTicker( False )
0343 jana.Start()
0344 time.sleep(2)
0345 # jana.WaitUntilAllThreadsRunning()
0346 
0347 # print '=================================================================================='
0348 # import inspect
0349 # for m in inspect.getmembers(jana): print str(m)
0350 # print '=================================================================================='
0351 command_line()
0352 
0353