Code Monkey home page Code Monkey logo

swiftterm's Introduction

Swift

SwiftTerm

SwiftTerm is a VT100/Xterm terminal emulator library for Swift applications that can be embedded into macOS, iOS applications, text-based, headless applications or other custom scenarios. It has been used in several commercially available SSH clients, including Secure Shellfish, La Terminal and CodeEdit

Check the API Documentation

This repository contains both a terminal emulator engine that is UI agnostic, as well as front-ends for this engine for iOS using UIKit, and macOS using AppKit. A curses-based terminal emulator (to emulate an xterm inside a console application) is available as part of the TermKit library.

Sample Code There are a couple of minimal sample apps for Mac and iOS showing how to use the library inside the TerminalApp directory.

  • The sample Mac app has much of the functionality of MacOS' Terminal.app, but without the configuration UI.
  • The sample iOS application uses an SSH library to connect to a remote system (as there is no native shell on iOS to run), and the sample happens to be hardcoded to my home machine, you can change that in the source code.

Companion App SwiftTermApp builds an actual iOS app that uses this library and is more complete than the testing apps in this module and provides a proper configuration UI.

This is a port of my original XtermSharp, which was itself based on xterm.js. At this point, I consider SwiftTerm to be a more advanced terminal emulator than both of those (modulo Selection/Accessibility) as it handles UTF, Unicode and grapheme clusters better than those and has a more complete coverage of terminal emulation. XtermSharp is generally attempting to keep up.

Features

  • Pretty decent terminal emulation, on or better than XtermSharp and xterm.js (and more comprehensive in many ways)
  • Unicode rendering (including Emoji, and combining characters and emoji)
  • Reusable and pluggable engine allows multiple user interfaces to be built on top of it.
  • Selection engine (with macOS support in the view)
  • Supports colors (ANSI, 256, TrueColor)
  • Supports mouse events
  • Supports terminal resizing operations (controlled by remote host, or locally)
  • Hyperlinks in terminal output
  • AppKit, UIKit front-ends; ncruses front-end provided separately
  • Local process and SSH connection support (some assembly required for the last one)
  • Proper CoreText rendering can munch through the hardened Unicode test suites.
  • Sixel graphics (Use img2sixel to test)
  • iTerm2-style graphic rendering (Use imgcat to test)
  • Fuzzed and abused
  • Seems pretty fast to me

SwiftTerm library

The SwiftTerm library itself contains the source code for both the engine and the front-ends. The front-ends are conditionally compiled based on the target platform.

The engine is in this directory, while code for macOS lives under Mac, and code for iOS, lives under iOS. Given that those two share a lot of common traits, the shared code is under Apple.

Using SwiftTerm

SwiftTerm uses the Swift Package Manager for its build, and you can add the library to your project by using the url for this project or a fork of it.

MacOS NSView

The macOS AppKit NSView implementation TerminalView is a reusable NSView control that can be connected to any source by implementing the TerminalViewDelegate.
I anticipate that a common scenario will be to host a local Unix command, so I have included LocalProcessTerminalView which is an implementation that connects the TerminalView to a Unix pseudo-terminal and runs a command there.

iOS UIView

There is an equivalent UIKit UIView implementation for TerminalView which like its NSView companion is an embeddable and reusable view that can be connected to your application by implementing the same TerminalViewDelegate. Unlike the NSView case running on a Mac, where a common scenario will be to run local commands, given that iOS does not offer access to processes, the most common scenario will be to wire up this terminal to a remote host. And the safest way of connecting to a remote system is with SSH.

Shared Code between MacOS and iOS

The iOS and UIKit code share a lot of the code, that code lives under the Apple directory.

Using SSH

The core library currently does not provide a convenient way to connect to SSH, purely to avoid the additional dependency. But this git module references a module that pulls a precompiled SSH client (Frugghi's SwiftSH), along with a UIKitSsshTerminalView in the iOS sample that that connects the TerminalView for iOS to an SSH connection.

Working on SwiftTerm

If you are using Xcode, there are two toplevel projects, one for Mac and one for iOS in the TerminalApp directory, one called "iOSTerminal.xcodeproj" and one called "MacTerminal.xcodeproj".

This is needed because Xcode does not provide code completion for iOS if you have a Mac project in the project. So I had to split them up. Both projects reference the same SwiftTerm package.

When working with these projects, if you choose the terminal application it will run this one. To run the test suite, select the 'SwiftTerm' target instead, and you can use 'SwiftTermFuzz' to run the fuzzer.

You can use swift build to build the package, and swift test to run the test suite - but be warned that the test suite expects the directory esctest to be checked out to run. You can see how I run these on GitHub actions in the file .github/workflows/swift.yml if you want to do this locally.

If using Xcode, you can select the "SwiftTerm" project, and then use Command-U to run the test suite.

Pending Work

GitHub issues has a list of desired features and enhancements

Long Term Plans

In the longer term, I want to also add a tvOS UIView, a SwiftGtk front-end for Linux.

Screenshots

24 Bit Color

24 bit color

Midnight Commander

Screen Shot 2020-04-12 at 12 17 49 AM

Solid UTF-8 support, excellent rendering: Screen Shot 2020-04-22 at 11 25 30 PM

Screen Shot 2020-04-22 at 11 25 24 PM

Supports hyperlinks emitted by modern apps:

image

iOS support:

image

Sixel support:

image

image

Resources

Additional and useful documents:

Test suites:

  • VTTest - old, but still good
  • EscTest - fantastic: George Nachman, the author of iTerm, created this test suite, and it became a FreeDesktop standard. Since then, Thomas E. Dickey, the xterm maintainer and maintainer of many text apps has contributed to this effort.

Authors

  • Thanks go to the xterm.js developers that originally wrote a terminal emulator that was licensed under a license that allowed for maximum reuse.
  • Marcin Krzyzanowski who masterfully improved and curated the rendering engine on AppKit/CoreText to be the glorious renderer that it is today - and for his contributions to the rendering engine
  • Greg Munn that did a lot of work in XtermSharp to support the needs of Visual Studio for Mac
  • Anders Borum has contributed reliability fixes, the sixel parser and changes required to put SwiftTerm to use in production.
  • Miguel de Icaza -me- who have been looking for an excuse to write some Swift code.

swiftterm's People

Contributors

crabtree-michael avatar ichizok avatar ijry avatar iosappssolutions avatar josephhill avatar kdrag0n avatar klein-artur avatar krzyzanowskim avatar lampmanyao avatar loganmoseley avatar maxdesiatov avatar migueldeicaza avatar nkleemann avatar osy avatar palmin avatar pouyakary avatar radare avatar taoso avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swiftterm's Issues

Bad reflow

The xterm.js-based reflow seems bad, it attempts to reflow what is on the screen, rather than keeping track of the semantics, which means that resizing will throw away data.

This should rather keep track at a character level, whether the position was triggered due to a hard newline or a wrapping.

EscapeParser issue with utf8

The issue that is causing trouble are the 8-bit sequnces that can be sent, which conflict with UTF8, in particular the DCS initiator (0x90). Previously the code was consuming this sequence when on 8 bit mode:

            if currentState == .Ground && code > 0x1f
           // Gather print data

So this was consuming the 0x90 as print data. So the variation became:

if currentState == .Ground && (code > 0x1f && code < 0x80 || (code > 0xc2 && code < 0xf3)) {

But this ends up eating UTF8 sequences (see mc running in this mode)

Public API desired features

  • Add support for passing fonts and color schemes
  • Add support for changing font on the fly
  • Add support for changing font size on the fly
  • Add support for changing color scheme on the fly
  • Add support for picking one of the new built-in color ANSI palettes
  • Add support for setting the history size.

The above probably should be surfaced as properties. Currently we have options which is ok, but I find cumbersome to copy, update and change. I rather have a more idiomatic set of properties.

Mac terminal view

Implement Command-R to switch between sending mouse events to target application and capturing it for selection and vice versa, like the Mac terminal.app does

Refresh bugs

Inserting text, when it pushes a long string, corrupts the next line.

Repeatedly pressing control-l re-renders things differently.

Correct:

image

Repeatedly pressing control-l sometimes shows this:

image

Selection mouse:

Double click should select the word
Triple click should select the line
On a large buffer, starting the selection, starts from somewhere way back
Scrolling looks busted.

Editing bug

Typing:

"while true foo" esc-b esc-b esc-d

This should delete "true", and it does, but also does not display "foo" anymore.

This happens on first use, afterwards this seems to work.

This seems to also cause, paste this:

while true; date; sleep 0.1; done

Then go with alt-b up until date and type "do", the rest of the line is erased.

VI is broken

VI is not working when you insert text.

Also, one time I saw it crash in a call to splice.

Mouse continues reporting after exiting mc

The reason for this problem is that we turn on the mouse-event sending as a global variable, but there is no way of turning it off - only turning off the individual modes.

So we need to remove the global from the Terminal, and make the MacTerminalView rely on the independent mouse variables in Terminal to operate, and not this ugly global

Mac: mouseDrag is raised even after a mouseUp

Not sure why, this causes the selection to be extended sometimes.

Repro:

in "bash$ foo" double click on the space between "$" and "foo", that should select that space, and quickly move a couple of lines down and quickly click - this currently extends the selection, because it receives a mouseDrag event, even when the mouse is up.

Test coverage

  • apc - s8c1t dependency
  • bs - works, but requires terminal to be in 80x25 to test
  • cup
  • dcs
  • cht
  • cat
  • cha
  • chi
  • change_color, change_dynamic_color, change_special_color
  • cnl
  • cpl
  • cr
  • cub
  • cud
  • cuf
  • cup
  • cuu
  • da - caveat, we report our own version of the terminal
  • DCH
  • dcs
  • decaln - test pattern tests
  • decbi - DECBI_Basic, DECBI_LeftOfMargin, DECBI_Scrolls, DECBI_WholeScreenScrolls
  • deccra - modulo a couple of debatable changes
  • decdc
  • decdsr
  • decera
  • decfi DECFI_WholeScreenScrolls
  • decfra
  • decic - DECIC_CursorWithinTopBotton, DECIC_IsNoOpWhenCursorBeginsOutsideScrollRegion
  • decid - obsolete
  • decrqm - not supported
  • decrqss - running in iterm2 mode, and disagree on hardcoded values
  • decscl - not worth it?
  • decset - mostly there, a few issues remain, and a few ugly things
  • decset-tit-inhibit
  • decstbm
  • decstr - we pass, but we have a "should not work that works"
  • dl - we need support for margins in the various delete line operations
  • ech - needs protected cells
  • el - needs protected cells
  • ff
  • hpa - delta are bugs fixed in SwiftTerm
  • hpr - delta are bugs fixed in SwiftTerm
  • hts
  • hvp
  • ich
  • il - scroll region support
  • ind - scroll region support
  • lf - scroll region support
  • nel - scroll region support
  • pm
  • rep
  • resetColor
  • resetSpecialColor
  • ri - scroll region
  • RIS - missing one column switch
  • s8c1t - missing cell protection support and see the bug on utf8 sequences and escape parser
  • rm
  • sd
  • sm
  • sos
  • su
  • tbc
  • vpa - problem with the origin cursor location
  • vpr
  • vt - one missing
  • xterm_save - low priority?
  • xterm_winops lots of goodies here

MacView: Selection bugs

  • does not copy the last character on Copy operation - only on the last visible character of a row.
  • Should copy immediately to a buffer, to not rely on the "Terminal" storage, which can go away after scrolling

Hosting Capabilities

When the baseline "Terminal" is embedded, the capabilities that it should surface to the client are bound by what the view can do. A cocoa view is very capable, but an ncurses view is not - so I need a way of customizing how much the Terminal reports back when capabilities are requested.

Crash

man nc

Then page to the end, then repeatedly hit "b", it crashes here:

        precondition(start < self.count)
with start = 188
count = 111

CircularList with NSAttributedString

head -60 /etc/services crashes because we have not filled out the buffer with an NSAttributedString, I think that I should populate on any growth or hook up makeEmpty.

getRectangleFromRequest is being too helpful

It tries to ensure a valid command (if things are invalid like left is higher that right), but in these cases, the commands should stop - see test test_DECCRA_invalidSourceRectDoesNothing for example

Should add support for TrueColor

There is now a work in progress patch to add support for TrueColor in the reworkAttributes brand, this is a list of pending issues:

  • In Terminal.swift, the SGR handler needs to implement the support for picking up the RGB data for fg and bg, as well as the indexed colors
  • While I am doing indexed colors, complete the support for configuring indexed colors -
  • Validate the constants documents in xterm.js vs the spec, because they are conflicting (the values for background have a range of colors, which on the original spec just listed one - 100)
  • Update Attribute.toSgr() to render the additional trueColor values.

Caret bugs

  • It does not show up solid, with the color I desire - this might be an issue with the default initializer in the property.

  • It does not show up after focus out/focus-in

vttest: character sets

The vttest for some character sets is not setting the second part of the attribute correctly for the second half

image

Should be:
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.