123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- //
- // ViewController.swift
- // MacTerminal
- //
- // Created by Miguel de Icaza on 3/11/20.
- // Copyright © 2020 Miguel de Icaza. All rights reserved.
- //
- import Cocoa
- import SwiftTerm
- class ViewController: NSViewController, LocalProcessTerminalViewDelegate, NSUserInterfaceValidations {
- @IBOutlet var loggingMenuItem: NSMenuItem?
- var changingSize = false
- var logging: Bool = false
- var zoomGesture: NSMagnificationGestureRecognizer?
- var postedTitle: String = ""
- var postedDirectory: String? = nil
-
- func sizeChanged(source: LocalProcessTerminalView, newCols: Int, newRows: Int) {
- if changingSize {
- return
- }
- changingSize = true
- //var border = view.window!.frame - view.frame
- var newFrame = terminal.getOptimalFrameSize ()
- let windowFrame = view.window!.frame
-
- newFrame = CGRect (x: windowFrame.minX, y: windowFrame.minY, width: newFrame.width, height: windowFrame.height - view.frame.height + newFrame.height)
- view.window?.setFrame(newFrame, display: true, animate: true)
- changingSize = false
- }
-
- func updateWindowTitle ()
- {
- var newTitle: String
- if let dir = postedDirectory {
- if let uri = URL(string: dir) {
- if postedTitle == "" {
- newTitle = uri.path
- } else {
- newTitle = "\(postedTitle) - \(uri.path)"
- }
- } else {
- newTitle = postedTitle
- }
- } else {
- newTitle = postedTitle
- }
- view.window?.title = newTitle
- }
-
- func setTerminalTitle(source: LocalProcessTerminalView, title: String) {
- postedTitle = title
- updateWindowTitle ()
- }
-
- func hostCurrentDirectoryUpdate (source: TerminalView, directory: String?) {
- self.postedDirectory = directory
- updateWindowTitle()
- }
-
- func processTerminated(source: TerminalView, exitCode: Int32?) {
- view.window?.close()
- if let e = exitCode {
- print ("Process terminated with code: \(e)")
- } else {
- print ("Process vanished")
- }
- }
- var terminal: LocalProcessTerminalView!
- static var lastTerminal: LocalProcessTerminalView!
-
- func getBufferAsData () -> Data
- {
- return terminal.getTerminal().getBufferAsData ()
- }
-
- func updateLogging ()
- {
- let path = logging ? "/Users/miguel/Downloads/Logs" : nil
- terminal.setHostLogging (directory: path)
- NSUserDefaultsController.shared.defaults.set (logging, forKey: "LogHostOutput")
- }
-
- override func viewDidLoad() {
- super.viewDidLoad()
- terminal = LocalProcessTerminalView(frame: view.frame)
- zoomGesture = NSMagnificationGestureRecognizer(target: self, action: #selector(zoomGestureHandler))
- terminal.addGestureRecognizer(zoomGesture!)
- ViewController.lastTerminal = terminal
- terminal.processDelegate = self
- terminal.feed(text: "Welcome to SwiftTerm")
- FileManager.default.changeCurrentDirectoryPath (FileManager.default.homeDirectoryForCurrentUser.path)
- terminal.startProcess (executable: "/bin/bash", execName: "-bash")
- view.addSubview(terminal)
- logging = NSUserDefaultsController.shared.defaults.bool(forKey: "LogHostOutput")
- updateLogging ()
- }
-
- @objc
- func zoomGestureHandler (_ sender: NSMagnificationGestureRecognizer) {
- if sender.magnification > 0 {
- biggerFont (sender)
- } else {
- smallerFont(sender)
- }
- }
- override func viewDidLayout() {
- super.viewDidLayout()
- changingSize = true
- terminal.frame = view.frame
- changingSize = false
- terminal.needsLayout = true
- }
- @objc @IBAction
- func set80x25 (_ source: AnyObject)
- {
- terminal.resize(cols: 80, rows: 25)
- }
- var lowerCol = 80
- var lowerRow = 25
- var higherCol = 160
- var higherRow = 60
-
- func queueNextSize ()
- {
- // If they requested a stop
- if resizificating == 0 {
- return
- }
- var next = terminal.getTerminal().getDims ()
- if resizificating > 0 {
- if next.cols < higherCol {
- next.cols += 1
- }
- if next.rows < higherRow {
- next.rows += 1
- }
- } else {
- if next.cols > lowerCol {
- next.cols -= 1
- }
- if next.rows > lowerRow {
- next.rows -= 1
- }
- }
- terminal.resize (cols: next.cols, rows: next.rows)
- var direction = resizificating
-
- if next.rows == higherRow && next.cols == higherCol {
- direction = -1
- }
- if next.rows == lowerRow && next.cols == lowerCol {
- direction = 1
- }
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.03) {
- self.resizificating = direction
- self.queueNextSize()
- }
- }
-
- var resizificating = 0
-
- @objc @IBAction
- func resizificator (_ source: AnyObject)
- {
- if resizificating != 1 {
- resizificating = 1
- queueNextSize ()
- } else {
- resizificating = 0
- }
- }
- @objc @IBAction
- func resizificatorDown (_ source: AnyObject)
- {
- if resizificating != -1 {
- resizificating = -1
- queueNextSize ()
- } else {
- resizificating = 0
- }
- }
- @objc @IBAction
- func allowMouseReporting (_ source: AnyObject)
- {
- terminal.allowMouseReporting.toggle ()
- }
-
- @objc @IBAction
- func exportBuffer (_ source: AnyObject)
- {
- saveData { self.terminal.getTerminal().getBufferAsData () }
- }
- @objc @IBAction
- func exportSelection (_ source: AnyObject)
- {
- saveData {
- if let str = self.terminal.getSelection () {
- return str.data (using: .utf8) ?? Data ()
- }
- return Data ()
- }
- }
- func saveData (_ getData: @escaping () -> Data)
- {
- let savePanel = NSSavePanel ()
- savePanel.canCreateDirectories = true
- savePanel.allowedFileTypes = ["txt"]
- savePanel.title = "Export Buffer Contents As Text"
- savePanel.nameFieldStringValue = "TerminalCapture"
-
- savePanel.begin { (result) in
- if result.rawValue == NSApplication.ModalResponse.OK.rawValue {
- let data = getData ()
- if let url = savePanel.url {
- do {
- try data.write(to: url)
- } catch let error as NSError {
- let alert = NSAlert (error: error)
- alert.runModal()
- }
- }
- }
- }
- }
-
- @objc @IBAction
- func softReset (_ source: AnyObject)
- {
- terminal.getTerminal().softReset ()
- terminal.setNeedsDisplay(terminal.frame)
- }
-
- @objc @IBAction
- func hardReset (_ source: AnyObject)
- {
- terminal.getTerminal().resetToInitialState ()
- terminal.setNeedsDisplay(terminal.frame)
- }
-
- @objc @IBAction
- func toggleOptionAsMetaKey (_ source: AnyObject)
- {
- terminal.optionAsMetaKey.toggle ()
- }
-
- @objc @IBAction
- func biggerFont (_ source: AnyObject)
- {
- let size = terminal.font.pointSize
- guard size < 72 else {
- return
- }
-
- terminal.font = NSFont.monospacedSystemFont(ofSize: size+1, weight: .regular)
- }
- @objc @IBAction
- func smallerFont (_ source: AnyObject)
- {
- let size = terminal.font.pointSize
- guard size > 5 else {
- return
- }
-
- terminal.font = NSFont.monospacedSystemFont(ofSize: size-1, weight: .regular)
- }
- @objc @IBAction
- func defaultFontSize (_ source: AnyObject)
- {
- terminal.font = NSFont.monospacedSystemFont(ofSize: NSFont.systemFontSize, weight: .regular)
- }
-
- @objc @IBAction
- func addTab (_ source: AnyObject)
- {
-
- // if let win = view.window {
- // win.tabbingMode = .preferred
- // if let wc = win.windowController {
- // if let d = wc.document as? Document {
- // do {
- // let x = Document()
- // x.makeWindowControllers()
- //
- // try NSDocumentController.shared.newDocument(self)
- // } catch {}
- // print ("\(d.debugDescription)")
- // }
- // }
- // }
- // win.tabbingMode = .preferred
- // win.addTabbedWindow(win, ordered: .above)
- //
- // if let wc = win.windowController {
- // wc.newWindowForTab(self()
- // wc.showWindow(source)
- // }
- // }
- }
-
- func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool
- {
- if item.action == #selector(debugToggleHostLogging(_:)) {
- if let m = item as? NSMenuItem {
- m.state = logging ? NSControl.StateValue.on : NSControl.StateValue.off
- }
- }
- if item.action == #selector(resizificator(_:)) {
- if let m = item as? NSMenuItem {
- m.state = resizificating == 1 ? NSControl.StateValue.on : NSControl.StateValue.off
- }
- }
- if item.action == #selector(resizificatorDown(_:)) {
- if let m = item as? NSMenuItem {
- m.state = resizificating == -1 ? NSControl.StateValue.on : NSControl.StateValue.off
- }
- }
- if item.action == #selector(allowMouseReporting(_:)) {
- if let m = item as? NSMenuItem {
- m.state = terminal.allowMouseReporting ? NSControl.StateValue.on : NSControl.StateValue.off
- }
- }
- if item.action == #selector(toggleOptionAsMetaKey(_:)) {
- if let m = item as? NSMenuItem {
- m.state = terminal.optionAsMetaKey ? NSControl.StateValue.on : NSControl.StateValue.off
- }
- }
-
- // Only enable "Export selection" if we have a selection
- if item.action == #selector(exportSelection(_:)) {
- return terminal.selectionActive
- }
- return true
- }
-
- @objc @IBAction
- func debugToggleHostLogging (_ source: AnyObject)
- {
- logging = !logging
- updateLogging()
- }
-
- }
|