66 lines
2.3 KiB
Swift
66 lines
2.3 KiB
Swift
import SwiftUI
|
|
import AppKit
|
|
import SwiftTerm
|
|
|
|
/// Full terminal emulator view (SwiftTerm): cursor addressing, colors,
|
|
/// scrollback, selection, and full-screen apps like vim/htop.
|
|
/// Keyboard goes straight to the pty (Tab completion, arrows, Ctrl+C, Esc);
|
|
/// pty output is fed in via PTYSession.onData. Dracula themed.
|
|
struct SwiftTermView: NSViewRepresentable {
|
|
@ObservedObject var term: PTYSession
|
|
|
|
func makeCoordinator() -> Coordinator {
|
|
Coordinator(term: term)
|
|
}
|
|
|
|
func makeNSView(context: Context) -> TerminalView {
|
|
let view = TerminalView(frame: .zero,
|
|
font: .monospacedSystemFont(ofSize: 13, weight: .regular))
|
|
view.terminalDelegate = context.coordinator
|
|
view.nativeForegroundColor = Dracula.nsColor(for: nil)
|
|
view.nativeBackgroundColor = Dracula.nsBackground
|
|
let palette = Dracula.ansiPalette
|
|
if palette.count == 16 {
|
|
view.installColors(palette)
|
|
}
|
|
context.coordinator.view = view
|
|
term.onData = { [weak view] data in
|
|
let bytes = Array(data)
|
|
DispatchQueue.main.async {
|
|
view?.feed(byteArray: bytes[...])
|
|
}
|
|
}
|
|
// Sync current size once the view exists (later resizes via delegate).
|
|
DispatchQueue.main.async {
|
|
term.setWinsize(cols: view.terminal.cols, rows: view.terminal.rows)
|
|
}
|
|
return view
|
|
}
|
|
|
|
func updateNSView(_ view: TerminalView, context: Context) {
|
|
context.coordinator.term = term
|
|
}
|
|
|
|
final class Coordinator: NSObject, TerminalViewDelegate {
|
|
var term: PTYSession?
|
|
weak var view: TerminalView?
|
|
|
|
init(term: PTYSession) {
|
|
self.term = term
|
|
}
|
|
|
|
func send(source: TerminalView, data: ArraySlice<UInt8>) {
|
|
term?.sendBytes(Data(data))
|
|
}
|
|
|
|
func sizeChanged(source: TerminalView, newCols: Int, newRows: Int) {
|
|
term?.setWinsize(cols: newCols, rows: newRows)
|
|
}
|
|
|
|
func setTerminalTitle(source: TerminalView, title: String) {}
|
|
func hostCurrentDirectoryUpdate(source: TerminalView, directory: String?) {}
|
|
func scrolled(source: TerminalView, position: Double) {}
|
|
func rangeChanged(source: TerminalView, startY: Int, endY: Int) {}
|
|
}
|
|
}
|