comparison cmd2.py @ 348:09145e5d7c26

beginning to change output redirection
author catherine@Drou
date Tue, 16 Feb 2010 17:33:11 -0500
parents 432ccab7c6c8
children 6116360f6e03
comparison
equal deleted inserted replaced
347:432ccab7c6c8 348:09145e5d7c26
347 else: 347 else:
348 result = get_paste_buffer() 348 result = get_paste_buffer()
349 return result 349 return result
350 350
351 class EmbeddedConsoleExit(Exception): 351 class EmbeddedConsoleExit(Exception):
352 pass
353
354 class EmptyStatement(Exception):
352 pass 355 pass
353 356
354 def ljust(x, width, fillchar=' '): 357 def ljust(x, width, fillchar=' '):
355 'analogous to str.ljust, but works for lists' 358 'analogous to str.ljust, but works for lists'
356 if hasattr(x, 'ljust'): 359 if hasattr(x, 'ljust'):
726 return p 729 return p
727 730
728 def postparsing_precmd(self, statement): 731 def postparsing_precmd(self, statement):
729 stop = 0 732 stop = 0
730 return stop, statement 733 return stop, statement
731
732 def postparsing_postcmd(self, stop): 734 def postparsing_postcmd(self, stop):
733 return stop 735 return stop
736
734 def func_named(self, arg): 737 def func_named(self, arg):
735 result = None 738 result = None
736 target = 'do_' + arg 739 target = 'do_' + arg
737 if target in dir(self): 740 if target in dir(self):
738 result = target 741 result = target
745 def onecmd_plus_hooks(self, line): 748 def onecmd_plus_hooks(self, line):
746 line = self.precmd(line) 749 line = self.precmd(line)
747 stop = self.onecmd(line) 750 stop = self.onecmd(line)
748 stop = self.postcmd(stop, line) 751 stop = self.postcmd(stop, line)
749 return stop 752 return stop
750 def onecmd(self, line): 753 def complete_statement(self, line):
751 """Interpret the argument as though it had been typed in response 754 if (not line) or (
752 to the prompt. 755 not pyparsing.Or(self.commentGrammars).
753 756 setParseAction(lambda x: '').transformString(line)):
754 This may be overridden, but should not normally need to be; 757 raise EmptyStatement
755 see the precmd() and postcmd() methods for useful execution hooks. 758 statement = self.parsed(line)
756 The return value is a flag indicating whether interpretation of 759 while statement.parsed.multilineCommand and (statement.parsed.terminator == ''):
757 commands by the interpreter should stop. 760 statement = '%s\n%s' % (statement.parsed.raw,
758 761 self.pseudo_raw_input(self.continuation_prompt))
759 This (`cmd2`) version of `onecmd` already override's `cmd`'s `onecmd`. 762 statement = self.parsed(statement)
760
761 """
762 # TODO: output from precmd and postcmd goes untrapped... and I don't
763 # know how to fix it...
764 if not line:
765 return self.emptyline()
766 if not pyparsing.Or(self.commentGrammars).setParseAction(lambda x: '').transformString(line):
767 return 0 # command was empty except for comments
768 try:
769 statement = self.parsed(line)
770 while statement.parsed.multilineCommand and (statement.parsed.terminator == ''):
771 statement = '%s\n%s' % (statement.parsed.raw,
772 self.pseudo_raw_input(self.continuation_prompt))
773 statement = self.parsed(statement)
774 except Exception, e:
775 self.perror(e)
776 return 0
777 if statement.parsed.command not in self.excludeFromHistory:
778 self.history.append(statement.parsed.raw)
779 try:
780 (stop, statement) = self.postparsing_precmd(statement)
781 except Exception, e:
782 self.perror(e)
783 return 0
784 if stop:
785 return self.postparsing_postcmd(stop)
786
787 if not statement.parsed.command: 763 if not statement.parsed.command:
788 return self.postparsing_postcmd(stop=0) 764 raise EmptyStatement
789 765 return statement
766
767 def output_state(self, statement):
790 statekeeper = None 768 statekeeper = None
791
792 if statement.parsed.pipeTo: 769 if statement.parsed.pipeTo:
793 redirect = subprocess.Popen(statement.parsed.pipeTo, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE) 770 redirect = subprocess.Popen(statement.parsed.pipeTo, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
794 statekeeper = Statekeeper(self, ('stdout',)) 771 statekeeper = Statekeeper(self, ('stdout',))
795 self.stdout = redirect.stdin 772 self.stdout = redirect.stdin
796 elif statement.parsed.output: 773 elif statement.parsed.output:
797 statekeeper = Statekeeper(self, ('stdout',)) 774 statekeeper = Statekeeper(self, ('stdout',))
798 if statement.parsed.outputTo: 775 if statement.parsed.outputTo:
799 mode = 'w' 776 mode = 'w'
800 if statement.parsed.output == '>>': 777 if statement.parsed.output == '>>':
801 mode = 'a' 778 mode = 'a'
802 try: 779 self.stdout = open(os.path.expanduser(statement.parsed.outputTo), mode)
803 self.stdout = open(os.path.expanduser(statement.parsed.outputTo), mode)
804 except Exception, e:
805 self.perror(e)
806 return self.postparsing_postcmd(stop=0)
807 else: 780 else:
808 statekeeper = Statekeeper(self, ('stdout',)) 781 statekeeper = Statekeeper(self, ('stdout',))
809 self.stdout = tempfile.TemporaryFile() 782 self.stdout = tempfile.TemporaryFile()
810 if statement.parsed.output == '>>': 783 if statement.parsed.output == '>>':
811 self.stdout.write(get_paste_buffer()) 784 self.stdout.write(get_paste_buffer())
812 try: 785 return statekeeper
786
787 def onecmd(self, line):
788 """Interpret the argument as though it had been typed in response
789 to the prompt.
790
791 This may be overridden, but should not normally need to be;
792 see the precmd() and postcmd() methods for useful execution hooks.
793 The return value is a flag indicating whether interpretation of
794 commands by the interpreter should stop.
795
796 This (`cmd2`) version of `onecmd` already override's `cmd`'s `onecmd`.
797
798 """
799 # TODO: output from precmd and postcmd goes untrapped... and I don't
800 # know how to fix it...
801
802 try:
803 statement = self.complete_statement(line)
804 except EmptyStatement:
805 return 0
806
807 (stop, statement) = self.postparsing_precmd(statement)
808 if stop:
809 return self.postparsing_postcmd(stop)
810
811 try:
812 if statement.parsed.command not in self.excludeFromHistory:
813 self.history.append(statement.parsed.raw)
814 statekeeper = self.output_state(statement)
813 try: 815 try:
814 # "heart" of the command, replaces cmd's onecmd() 816 # "heart" of the command, replaces cmd's onecmd()
815 self.lastcmd = statement.parsed.raw 817 self.lastcmd = statement.parsed.raw
816 funcname = self.func_named(statement.parsed.command) 818 funcname = self.func_named(statement.parsed.command)
817 if not funcname: 819 if not funcname:
836 self.perror(e) 838 self.perror(e)
837 elif statement.parsed.pipeTo: 839 elif statement.parsed.pipeTo:
838 for result in redirect.communicate(): 840 for result in redirect.communicate():
839 statekeeper.stdout.write(result or '') 841 statekeeper.stdout.write(result or '')
840 self.stdout.close() 842 self.stdout.close()
841 statekeeper.restore() 843 statekeeper.restore()
842
843 return self.postparsing_postcmd(stop) 844 return self.postparsing_postcmd(stop)
844 845
845 def _default(self, statement): 846 def _default(self, statement):
846 arg = statement.full_parsed_statement() 847 arg = statement.full_parsed_statement()
847 if self.default_to_shell: 848 if self.default_to_shell: