console.groovy

来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· GROOVY 代码 · 共 606 行 · 第 1/2 页

GROOVY
606
字号
		shell.setVariable("__", history.collect {it.result})
    }
    
    // Handles menu event
    void captureStdOut(EventObject evt) {
    	captureStdOut = evt.source.selected
    }

    void caretUpdate(CaretEvent e){
        textSelectionStart = Math.min(e.dot,e.mark)
        textSelectionEnd = Math.max(e.dot,e.mark)
    }

    
    void clearOutput(EventObject evt = null) {
    	outputArea.setText('')
    }
    
    // Confirm whether to interrupt the running thread
    void confirmRunInterrupt(EventObject evt) {
    	def rc = JOptionPane.showConfirmDialog(frame, "Attempt to interrupt script?",
    		"GroovyConsole", JOptionPane.YES_NO_OPTION) 
    	if (rc == JOptionPane.YES_OPTION && runThread != null) {
    		runThread.interrupt()
    	}
    }
    
    void exit(EventObject evt = null) {
    	if (askToSaveFile()) {
            frame.hide()
            frame.dispose()
        }
    }
    
    void fileNewFile(EventObject evt = null) {
    	if (askToSaveFile()) {
	    	scriptFile = null
	    	setDirty(false)
	    	inputArea.text = ''
    	}
    }
    
    // Start a new window with a copy of current variables
    void fileNewWindow(EventObject evt = null) {
      (new Console(new Binding(new HashMap(shell.context.variables)))).run()
    }

    void fileOpen(EventObject evt = null) {
        scriptFile = selectFilename();
        if (scriptFile != null) {
            inputArea.text = scriptFile.readLines().join('\n');
            setDirty(false)
            inputArea.caretPosition = 0
        }
    }

	// Save file - return false if user cancelled save
    boolean fileSave(EventObject evt = null) {
        if (scriptFile == null) {
            scriptFile = selectFilename("Save");
        }
        if (scriptFile != null) {
            scriptFile.write(inputArea.text)
            setDirty(false);
            return true
        } else {
            return false
        }
    }
    
    def finishException(Throwable t) {
    	statusLabel.text = 'Execution terminated with exception.'
    	history[-1].exception = t

		appendOutputNl("Exception thrown: ", promptStyle)
		appendOutput(t.toString(), resultStyle)

		StringWriter sw = new StringWriter()
		new PrintWriter(sw).withWriter { pw -> t.printStackTrace(pw) }

		appendOutputNl("\n${sw.buffer}\n", outputStyle)
		bindResults()
    }
    
    def finishNormal(Object result) {
    	// Take down the wait/cancel dialog
    	history[-1].result = result
    	if (result != null) {
	    	statusLabel.text = 'Execution complete.'
	    	appendOutputNl("Result: ", promptStyle)
			appendOutput("${InvokerHelper.inspect(result)}", resultStyle)
		} else {
	    	statusLabel.text = 'Execution complete. Result was null.'
		}
		bindResults()	
    }
    
    // Gets the last, non-null result
    def getLastResult() {
    	// runtime bugs in here history.reverse produces odd lookup
    	// return history.reverse.find {it != null}
    	if (!history) {
    		return
    	}
    	for (i in (history.size() - 1)..0) {
    		if (history[i].result != null) {
    			return history[i].result
    		}
    	}
    	return null
    }

	// Allow access to shell from outside console 
	// (useful for configuring shell before startup)
    GroovyShell getShell() {
		return shell
    }
    
    void historyNext(EventObject evt = null) {
    	if (historyIndex < history.size()) {
    		historyIndex++;
    		setInputTextFromHistory()
    	} else {
    		statusLabel.text = "Can't go past end of history (time travel not allowed)"
    		beep()
    	}
    }

    void historyPrev(EventObject evt = null) {
    	if (historyIndex > 0) {
    		historyIndex--;
    		setInputTextFromHistory()
    	} else {
    		statusLabel.text = "Can't go past start of history"
    		beep()
    	}
    }
    
    void inspectLast(EventObject evt = null){
        if (null == lastResult) {
        	JOptionPane.showMessageDialog(frame, "The last result is null.", 
        		"Cannot Inspect", JOptionPane.INFORMATION_MESSAGE)
        	return
        }
        ObjectBrowser.inspect(lastResult)
    }

    void inspectVariables(EventObject evt = null) {
        ObjectBrowser.inspect(shell.context.variables)    
    }
    
    void largerFont(EventObject evt = null) {
        if (inputArea.font.size > 40) return
        def newFont = new Font('Monospaced', Font.PLAIN, inputArea.font.size + 2)
        inputArea.font = newFont
        outputArea.font = newFont
    }
    
    Boolean notifySystemOut(String str) {
    	if (!captureStdOut) {
    		// Output as normal
	    	return true
	    }
	    
	    // Put onto GUI
    	if (EventQueue.isDispatchThread()) {
    		appendOutput(str, outputStyle)
    	} 
    	else {
	    	SwingUtilities.invokeLater {
		    	appendOutput(str, outputStyle)
		    }
		}
    	return false
    }
    
    // actually run the
    void runScript(EventObject evt = null) {
    	def record = new HistoryRecord( allText: inputArea.getText(),
    		selectionStart: textSelectionStart, selectionEnd: textSelectionEnd)
    	addToHistory(record)

		// Print the input text    	
        for (line in record.textToRun.tokenize("\n")) {
            appendOutputNl('groovy> ', promptStyle)
            appendOutput(line, commandStyle)
        }
        
        //appendOutputNl("") - with wrong number of args, causes StackOverFlowError;
        appendOutputNl("\n", promptStyle)
        
        // Kick off a new thread to do the evaluation
        statusLabel.text = 'Running Script...'
        
        // Run in separate thread, so that System.out can be captured
    	runThread = Thread.start {
    		try {
    			SwingUtilities.invokeLater { showRunWaitDialog() }
		        String name = "Script${scriptNameCounter++}"
				def result = shell.evaluate(record.textToRun, name);
				SwingUtilities.invokeLater { finishNormal(result) }
	    	} catch (Throwable t) {
	    		SwingUtilities.invokeLater { finishException(t) }
	    	} finally {
                SwingUtilities.invokeLater {
                	runWaitDialog.hide();
                	runThread = null
                }
	    	}
    	}
    }
    
    def selectFilename(name = "Open") {
        def fc = new JFileChooser()
        fc.fileSelectionMode = JFileChooser.FILES_ONLY
        fc.acceptAllFileFilterUsed = true
        if (fc.showDialog(frame, name) == JFileChooser.APPROVE_OPTION) {
            return fc.selectedFile
        } else {
            return null
        }
    }

    void setDirty(boolean newDirty) {
        dirty = newDirty
        updateTitle()
    }
    
    private void setInputTextFromHistory() {
		if (historyIndex < history.size()) {
			def record = history[historyIndex]
			inputArea.text = record.allText
			inputArea.selectionStart = record.selectionStart
			inputArea.selectionEnd = record.selectionEnd
			setDirty(true) // Should calculate dirty flag properly (hash last saved/read text in each file)
			statusLabel.text = "command history ${history.size() - historyIndex}"
		} else {
			inputArea.text = ""
			statusLabel.text = 'at end of history'
		}    	
    }
    
    // Adds a variable to the binding
    // Useful for adding variables before openning the console
    void setVariable(String name, Object value) {
    	shell.context.setVariable(name, value)
    }
    
    void showAbout(EventObject evt = null) {
        def version = InvokerHelper.getVersion()
        def pane = swing.optionPane()
         // work around GROOVY-1048
        pane.setMessage('Welcome to the Groovy Console for evaluating Groovy scripts\nVersion ' + version)
        def dialog = pane.createDialog(frame, 'About GroovyConsole')
        dialog.show()
    }

    // Shows the 'wait' dialog
    void showRunWaitDialog() {
    	runWaitDialog.pack()
    	int x = frame.x + (frame.width - runWaitDialog.width) / 2
    	int y = frame.y + (frame.height - runWaitDialog.height) / 2
    	runWaitDialog.setLocation(x, y)
    	runWaitDialog.show()
    }

    void smallerFont(EventObject evt = null){
        if (inputArea.font.size < 5) return
        def newFont = new Font('Monospaced', Font.PLAIN, inputArea.font.size - 2)
        inputArea.font = newFont
        outputArea.font = newFont
    }

    void updateTitle() {
        if (scriptFile != null) {
            frame.title = scriptFile.name + (dirty?" * ":"") + " - GroovyConsole"
        } else {
            frame.title = "GroovyConsole"
        }
    }
}

/** A single time when the user selected "run" */
class HistoryRecord {
	def allText
	def selectionStart
	def selectionEnd
	def scriptName
	def result
	def exception
	
	def getTextToRun() {
        if (selectionStart != selectionEnd) {   
            return allText[selectionStart ..< selectionEnd]
        }
        return allText
	}
	
	def getValue() {
		return exception ? exception : result
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?