Source

codeaide / codeaide / modes / base / console.py

Full commit
# -*- coding: utf-8 -*-
import sys
import os

from PyQt4.QtCore import SIGNAL, QTimer
from PyQt4.QtGui import qApp, QFileDialog, QMessageBox

from codeaide.base import *


print_stdout = lambda *args: sys.__stdout__.write(" ".join(unicode(a) for a in args)) 



class ConsoleBase(ModeBase):

    ps1 = "?"
    ps2 = ">"
    completer = None


    def init(self):
        #self.state = id(self)
        #self.textedit.switch_state(self.state)
        self.textedit.setMaximumBlockCount(5000)
        self.textedit.setAttribute(Qt.WA_KeyCompression, False)
        self.history = [""]
        self.history_index = 0
        self.echo = True
        self.tab_state = - 1
        self.buf = []
        self.buffer_output = True
        self.timer = QTimer()
        self.timer.connect(self.timer, SIGNAL("timeout()"), self.on_timeout)
        self.timer.start(250)
        self.init_console()
        self.write("%s" % self.ps1)


    def init_console(self):
        pass


        
    def keyboard_hooks(self):
        return {
             (-1,-1): self.keyPressEvent
        }


    @command("Clear console", context_menu=True)
    def clear(self):
        self.clear_console()


    history_filename = "history.txt"
    history_pattern = "*.txt"

    @command("Save history", context_menu=True)
    def save_history(self):
        filename = QFileDialog.getSaveFileName(
          self.textedit, "Save history",
          self.history_filename, self.history_pattern)
        if filename:
##            if os.path.exists(filename):
##                ret = QMessageBox.question( 
##                  self.textedit, "Overwrite existing file?", 
##                  "The specified file already exists.\n" + \
##                  "Are you sure you want to overwrite this file?",
##                  QMessageBox.Save | QMessageBox.Cancel
##                  )
##                if ret != QMessageBox.Save:
##                    return
            t = "\n".join(self.history)
            open(filename, "w").write(t)
            self.history_filename = filename

                        
    @command("Clear history", context_menu=True)
    def clear_history(self):
        self.history = [""]
        self.history_index = 0        

        
    @command("Clear console", context_menu=True)
    def clear_console(self):
        self.textedit.setPlainText("")
        self.write("%s" % self.ps1)


    def keyPressEvent(self, event, key, modifiers, text):
        def remove_line():
            cursor = self.textedit.textCursor()
            cursor.select(QTextCursor.BlockUnderCursor)
            cursor.removeSelectedText()

        l = len(self.ps1)
        #line = unicode(self.textedit.document().end().previous().text())
        doc = self.textedit.document()
        line =  unicode(doc.findBlockByNumber(doc.blockCount() - 1).text())
        ps1orps2, line = line[:l], line[l:]

        if not key in [Qt.Key_Tab, Qt.Key_Backtab] and len(text):
            self.tab_state = -1

        if key == Qt.Key_Up:
            if self.history_index + 1 < len(self.history):
                self.history_index += 1
            remove_line()
            self.write("\n%s%s" % (ps1orps2, self.history[self.history_index]))
        elif key == Qt.Key_Down:
            if self.history_index > 0:
                self.history_index -= 1
            remove_line()
            self.write("\n%s%s" % (ps1orps2, self.history[self.history_index]))
        elif key == Qt.Key_Tab:
            if modifiers & Qt.ControlModifier:
                self.write(" " * 4)
            elif self.completer:
                self.tab_state += 1
                remove_line()
                self.write("\n%s%s" % (
                    ps1orps2, self.completer.complete(line, self.tab_state) or line))
        elif key == Qt.Key_Backtab:
            if self.completer:
                if self.tab_state >= 0:
                    self.tab_state -= 1
                remove_line()
                self.write("%s%s" % (
                    ps1orps2, self.completer.complete(line, self.tab_state) or line))
        elif key in [Qt.Key_Backspace, Qt.Key_Left]:
            if self.textedit.textCursor().columnNumber() > len(ps1orps2) + 1:
                return False
        elif key == Qt.Key_Return:
            self.textedit.moveCursor(QTextCursor.EndOfLine,  QTextCursor.MoveAnchor)
            self.write("\n")
            if self.push(line):
                self.write("%s" % self.ps2)
            else:
                self.write("%s" % self.ps1)
            if line and line != self.history[self.history_index]:
                self.history.insert(1, line)
            self.history_index = 0
        else:
            return False
        return True


    def mouse_press_hook(self, event):
        # disable mouse selection
        self.textedit.setFocus()
        return True


    mouse_double_click_hook = mouse_press_hook

    
    def on_timeout(self):
        if self.buf:
            self.flush()
            self.timer.stop()


    def write(self, s):
        if self.echo:
            print_stdout(s)
        if self.buffer_output:
            self.buf.append(s)
            if not self.timer.isActive():
                self.timer.start()
            return
        self.write_direct(s)
        

    def write_direct(self, s):
        cursor = self.textedit.textCursor()
        cursor.clearSelection()
        cursor.movePosition(QTextCursor.End, QTextCursor.MoveAnchor)
        cursor.insertText(s)
        cursor.movePosition(QTextCursor.End, QTextCursor.MoveAnchor)
        cursor.clearSelection()
        self.textedit.ensureCursorVisible()
        qApp.processEvents()


    def writelines(l):
        self.write("\n".join(l))


    def flush(self):
        s = "".join(self.buf)
        self.buf = []
        self.write_direct(s)


    def close(self):
        pass


    def push(self, line):
        return True