mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			159 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			159 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
| #! /usr/local/bin/python
 | |
| 
 | |
| # A Python program implementing rmt, an application for remotely
 | |
| # controlling other Tk applications.
 | |
| # Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.5-8, pp. 273-276.
 | |
| 
 | |
| # Note that because of forward references in the original, we
 | |
| # sometimes delay bindings until after the corresponding procedure is
 | |
| # defined.  We also introduce names for some unnamed code blocks in
 | |
| # the original because of restrictions on lambda forms in Python.
 | |
| 
 | |
| # XXX This should be written in a more Python-like style!!!
 | |
| 
 | |
| from Tkinter import *
 | |
| 
 | |
| # 1. Create basic application structure: menu bar on top of
 | |
| # text widget, scrollbar on right.
 | |
| 
 | |
| root = Tk()
 | |
| tk = root.tk
 | |
| mBar = Frame(root, {'relief': 'raised', 'bd': 2,
 | |
| 		    Pack: {'side': 'top', 'fill': 'x'}})
 | |
| f = Frame(root)
 | |
| f.pack({'expand': 1, 'fill': 'both'})
 | |
| s = Scrollbar(f, {'relief': 'flat',
 | |
| 		  Pack: {'side': 'right', 'fill': 'y'}})
 | |
| t = Text(f, {'relief': 'raised', 'bd': 2, 'yscrollcommand': (s, 'set'),
 | |
| 	     'setgrid': 1,
 | |
| 	     Pack: {'side': 'left', 'fill': 'both', 'expand': 1}})
 | |
| 
 | |
| t.tag_config('bold', {'font': '-Adobe-Courier-Bold-R-Normal-*-120-*'}) 
 | |
| s['command'] = (t, 'yview')
 | |
| root.title('Tk Remote Controller')
 | |
| root.iconname('Tk Remote')
 | |
| 
 | |
| # 2. Create menu button and menus.
 | |
| 
 | |
| file = Menubutton(mBar, {'text': 'File', 'underline': 0,
 | |
| 			 Pack: {'side': 'left'}})
 | |
| file_m = Menu(file)
 | |
| file['menu'] = file_m
 | |
| file_m_apps = Menu(file_m)
 | |
| file_m.add('cascade', {'label': 'Select Application', 'underline': 0,
 | |
| 		       'menu': file_m_apps})
 | |
| file_m.add('command', {'label': 'Quit', 'underline': 0, 'command': 'exit'})
 | |
| 
 | |
| # 3. Create bindings for text widget to allow commands to be
 | |
| # entered and information to be selected.  New characters
 | |
| # can only be added at the end of the text (can't ever move
 | |
| # insertion point).
 | |
| 
 | |
| def single1(e):
 | |
| 	x = e.x
 | |
| 	y = e.y
 | |
| 	t.setvar('tk_priv(selectMode)', 'char')
 | |
| 	t.mark_set('anchor', At(x, y))
 | |
| 	# Should focus W
 | |
| t.bind('<1>', single1)
 | |
| 
 | |
| def double1(e):
 | |
| 	x = e.x
 | |
| 	y = e.y
 | |
| 	t.setvar('tk_priv(selectMode)', 'word')
 | |
| 	t.tk_textSelectTo(At(x, y))
 | |
| t.bind('<Double-1>', double1)
 | |
| 
 | |
| def triple1(e):
 | |
| 	x = e.x
 | |
| 	y = e.y
 | |
| 	t.setvar('tk_priv(selectMode)', 'line')
 | |
| 	t.tk_textSelectTo(At(x, y))
 | |
| t.bind('<Triple-1>', triple1)
 | |
| 
 | |
| def returnkey(e):
 | |
| 	t.insert(AtInsert(), '\n')
 | |
| 	invoke()
 | |
| t.bind('<Return>', returnkey)
 | |
| 
 | |
| def controlv(e):
 | |
| 	t.insert(AtInsert(), t.selection_get())
 | |
| 	t.yview_pickplace(AtInsert())
 | |
| 	if t.index(AtInsert())[-2:] == '.0':
 | |
| 		invoke()
 | |
| t.bind('<Control-v>', controlv)
 | |
| 
 | |
| # 4. Procedure to backspace over one character, as long as
 | |
| # the character isn't part of the prompt.
 | |
| 
 | |
| def backspace(e):
 | |
| 	if t.index('promptEnd') != t.index('insert - 1 char'):
 | |
| 		t.delete('insert - 1 char', AtInsert())
 | |
| 		t.yview_pickplace(AtInsert())
 | |
| t.bind('<BackSpace>', backspace)
 | |
| t.bind('<Control-h>', backspace)
 | |
| t.bind('<Delete>', backspace)
 | |
| 
 | |
| 
 | |
| # 5. Procedure that's invoked when return is typed:  if
 | |
| # there's not yet a complete command (e.g. braces are open)
 | |
| # then do nothing.  Otherwise, execute command (locally or
 | |
| # remotely), output the result or error message, and issue
 | |
| # a new prompt.
 | |
| 
 | |
| def invoke():
 | |
| 	cmd = t.get('promptEnd + 1 char', AtInsert())
 | |
| 	if t.getboolean(tk.call('info', 'complete', cmd)): # XXX
 | |
| 		if app == root.winfo_name():
 | |
| 			msg = tk.call('eval', cmd) # XXX
 | |
| 		else:
 | |
| 			msg = t.send(app, cmd)
 | |
| 		if msg:
 | |
| 			t.insert(AtInsert(), msg + '\n')
 | |
| 		prompt()
 | |
| 	t.yview_pickplace(AtInsert())
 | |
| 
 | |
| def prompt():
 | |
| 	t.insert(AtInsert(), app + ': ')
 | |
| 	t.mark_set('promptEnd', 'insert - 1 char')
 | |
| 	t.tag_add('bold', 'insert linestart', 'promptEnd')
 | |
| 
 | |
| # 6. Procedure to select a new application.  Also changes
 | |
| # the prompt on the current command line to reflect the new
 | |
| # name.
 | |
| 
 | |
| def newApp(appName):
 | |
| 	global app
 | |
| 	app = appName
 | |
| 	t.delete('promptEnd linestart', 'promptEnd')
 | |
| 	t.insert('promptEnd', appName + ':')
 | |
| 	t.tag_add('bold', 'promptEnd linestart', 'promptEnd')
 | |
| 
 | |
| def fillAppsMenu():
 | |
| 	file_m_apps.add('command')
 | |
| 	file_m_apps.delete(0, 'last')
 | |
| 	names = root.winfo_interps()
 | |
| 	names = map(None, names) # convert tuple to list
 | |
| 	names.sort()
 | |
| 	for name in names:
 | |
| 		try:
 | |
| 			root.send(name, 'winfo name .')
 | |
| 		except TclError:
 | |
| 			# Inoperative window -- ignore it
 | |
| 			pass
 | |
| 		else:
 | |
| 			file_m_apps.add('command', {'label': name,
 | |
| 						    'command':
 | |
| 						    lambda name=name:
 | |
| 						    newApp(name)})
 | |
| 
 | |
| file_m_apps['postcommand'] = fillAppsMenu
 | |
| mBar.tk_menuBar(file)
 | |
| 
 | |
| # 7. Miscellaneous initialization.
 | |
| 
 | |
| app = root.winfo_name()
 | |
| prompt()
 | |
| t.focus()
 | |
| 
 | |
| root.mainloop()
 | 
