GithubHelp home page GithubHelp logo

xtermsharp's Introduction

XtermSharp

Build Status

XtermSharpGuiXtermSharpMac

XtermSharp is a VT100/Xterm terminal emulator for .NET, the engine is intended to be agnostic from potential front-ends and backends.

Consumers use a higher-level implementation that provides integration with their UI toolkit of choice. This module contains both implementation a Cocoa/Mac and a Terminal.Gui implementations that can serve as a reference to other ports.

The terminal itself does not deal with connecting the data to to a process or a remote server. Data is sent to the terminal by passing a byte array with data to the "Feed" method.

Convenience classes exist to spawn a subprocess and connecting the terminal to a local process, and allow some customization of the environment variables to pass to the child.

The SampleTester program is an internal test program that exercises some of the Terminal API.

Long term, I want to have an embeddable console for MonoDevelop/VisualStudioMac that is a proper terminal, so I can debug things like gui.cs without launching an external window as well as having a full terminal for my Gui.cs library.

XtermSharp.Mac

This is a library built on top of XtermSharp that provides a MacOS NSView that can be used in your applications to embed a terminal emulator. This maps the Mac input to send data to the underlying terminal.

Like XtermSharp, this does not wire up the terminal to a backend or a process, this is something that your code still needs to do.

An example terminal on how to connect a Unix shell process is available in the MacTerminal project.

Features

The engine is pretty good at this point and lets you use Emacs, vi, top, mc, blessed and gui.cs both with the keyboard and the mouse. Some features are only available on the Mac version, as the text-version with curses imposes some limitations.

The unicode handling is pretty decent, but does not have support for Grapheme clusters yet, that is coming up later.

Scrollback and reflow are currently missing, those are tied together, and I think it can be done better than the original xterm.js design supported.

Roadmap

There are many issues filed that track some of the capabilities that are missing, the list is by no means complete. What I would like to do is package this in a reusable form for all available platforms (Windows, Mac, Linux, iOS, Android) so others can use this to embed terminal emulators where necessary.

There is currently a native piece of code needed to fork/exec safely on MacOS in the presence of MacOS recent "Runtime Hardening".

Some of the Gui.cs code needs to be moved to its XtermSharp.GuiCs library, and the SubprocessTerminalView needs to introduced for MacOS.

History

I wanted to have a console emulator for .NET since the days of Silverlight, but never quite got around it - but having an engine that could have different front-ends and backends is something that I have desired for a long time. I did some bits and pieces some years ago which are not required nowadays.

This code was originally a port of xterm.js, but has been adjusted for proper processing Unicode using NStack and to make the front-end pluggable in a .NET way. While xterm.js was a useful starting point, the code has deviated and there is limited value in continuing the port, this code can now live on its own.

xtermsharp's People

Contributors

bergmeister avatar bratsche avatar migueldeicaza avatar mrward avatar nosami avatar sgmunn avatar therzok 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

xtermsharp's Issues

Events in XtermSharp

XtermSharp started with a TerminalDelegate pattern to notify of events, and overtime got a handful of .NET-style events later on added. This was because the TerminalDelegate was useful for Terminal, but the higher-level constructs did not use this.

I want to make XtermSharp mirror the design of SwiftTerm, where the notification pattern is always the delegate, even if this means re-publishing events to other delegates.

So for example, the TerminalView for AppKit implements TerminalDelegate and in addition, reports events via its own TerminalViewDelegate and so on.

Buffer recycling glitch

I am still trying to understand the root issue here, but if you set the scroll back to something low, like 5, and cause the buffer to start recycling rows there are 2 glitches that happen. The first is a blank line inserted in the display buffer and the second is a ghosting of the first line of data.

Screen Recording 2020-03-02 at 02 48 PM

Debugging this in UpdateDisplay, the buffer has 53 lines, the first contains the ghosted data, the last contains a blank line (which maps to what we see as line[0] is recycled).

Screen Shot 2020-03-02 at 2 58 02 PM

With a breakpoint in UpdateDisplay that stops when the content we are updating contains the string "Xterm" and a breakpoint in Terminal.Scroll(bool) on line 301 (buffer.Lines.Recycle ().CopyFrom (newLine)), we see that the str contains the text before we start to recycle lines. What appears to be happening is that the terminal view's buffer is being loaded with text from the terminal buffer, the terminal buffer is full. CircularList.Push bumps startIndex immediately after adding an element when length == array.Length.

It is possible that CircularList.startIndex is being incremented too soon, since no additional items has been added yet. Actually, this might be the case, looking at xterm.js, length is incremented after the check to adjust startIndex.

Test Coverage

  • BS
  • CBT
  • CR
  • CUP
  • CHA
  • CHT
  • CHA
  • CUB
  • CUD
  • CUF
  • CUU
  • HTS
  • RM
  • TBC
  • DCS
  • DECERA
  • HPR
  • TBC
  • SOS
  • VPR
  • PM
  • DECFRA
  • DECDSR
  • DECSTR
  • DECSTBM

  • apc
  • cat
  • chi
  • change_color, change_dynamic_color, change_special_color
  • cnl
  • ppl
  • da - caveat, we report our own version of the terminal
  • DCH - needs to restrict the deletion to the margin boundaries, and not "pull" from beyond the - [ ]margins.
  • decaln - test pattern tests
  • decbi (tests in iTerm2 mode shows this as ignored)
  • deccra - modulo a couple of debatable changes
  • decdc
  • decdsr
  • decfi
  • decic
  • decid - obsolete
  • decrqm - not supported
  • decrqss - running in iterm2 mode, and disagree on hardcoded values
  • decscl - not worth it?
  • decsed/decsel/decsera - needs support for character protection (DECSCA)
    ...

some remarks regarding the parser

xterm.js' parser was written with JS string (UTF-16 codepoints) in mind. Plz note that it will not work correctly with raw UTF8 bytes (for any byte with the 8th bit set). For this to work you would have to rewrite Parse in a way to correctly decode multibyte chars on the fly. Another and prolly easier approach is to simply decode the whole byte chunk beforehand to UTF16 or UTF32, this way the parser can stay mostly untouched. In xterm.js we went with UTF32 after some longish testing, mainly for performance reasons (with a small memory sacrifice compared to UTF16).

Furthermore the older version of the parser has some loose ends, that are already fixed upstream:

  • some rare control codes are not handled correctly (not a big deal, since those are not part of typical terminal data, see the updated transition table)
  • support for the colon subparam notation, which is needed for true color sequences (see xtermjs/xterm.js#2241) with explicit ZDM setting. ZDM is a tricky topic, its deprecated since mid 80s and not part of the latest ECMA spec, but since all DEC VTs are operating in ZDM we kept it for now. Note that this might change with newer sequences though.
  • function identifier based handler registration to better reflect the ECMA defined function space determined by prefix, intermediate and final bytes (see xtermjs/xterm.js#2346)
  • support for REP (repeat previous character, ECMA-48, see xtermjs/xterm.js#2199)
  • some bug fixes regarding abort conditions during OSC/DCS sequences. The old parser would always enter the handlers, which is not wanted for SUB/CAN (again not a big deal since hardly seen)

Last but not least the parser has seen some code/perf improvements, but those are mostly JS engine related and less likely show a big impact in C#. On a sidenote - the somewhat complicated print handling with aggregating chunk slices shows a major perf improvement in JS (5 to 10 times compared to single char handling), which is not true for the original C parser. In C jumping for every single char into print is much faster, prolly due to heavy inlining/unrolling (JS JITs are still lacking in this regard). Not sure how C# would do here. In general the perf of the parser should not be an issue, in JS it handles typical sequences with 80-150 MB/s (the C variant only being twice as fast).

GUI.cs backend

This describes the tasks to complete an Xterm control for https://github.com/migueldeicaza/gui.cs:

  • Upgrade to Terminal.Gui 1.0
  • Mouse support
  • missing colors/attributes
  • explore the effect of utf8 envy variable on output support (why are drawing characters not rendering at work)
  • terminal size vs visible region: auto adjust or support scrolling
  • inout handler - need an “escape” hit key

Pending backports from SwiftTerm

  • Large - the rendering support for Mac/iOS was redone by Marcin extensively and is now really good, and better than what is here, among others: 22e7a52ad1ab85968a0e778c5f8fe9ff11bf127d and 831bd5c66868d6ab86b3e5749dea66e1fd2cae7e fd58508c4bad2fb2abaeb547d77823fbbaabe27d b645fda692e012d215230934a49ee30c4ed9a445
  • Different way of doing selection (some of those from Marcin: krzyzanowskim/marcin/draw-selection, it starts there, and could serve as inspiration, but the code now has many fixes, so best to look at guidance and then port the existing code)
  • Fuzzing fixes: a2b290d43d20588cf3f035480a39e5703828bb2a
  • URL payload support migueldeicaza/SwiftTerm#64
  • Fix 522b5e06a72b552fd5149b06a2940d6249ea7341
  • 502b46447a5eaec9de7c37c0d662a9c3bb304bef
  • Fix: abfe54ee2254bd7347aea199839986cb9e973b56
  • Feature: 22d95b6f96d0bf22992db136f66ca3a2672221b1
  • iOS backend: migueldeicaza/SwiftTerm#85
  • af0ed8c9eb2cf63080ad93fabeb20e80bb02c4bb
  • State tracking: c3ec9c4485f075f76f31ad1566de074e1327f1cc

These are changes for improved correctness, few people need them, but they make the test suite work better:

  • RIS fixes: 226229760a6afbb0440854232f7cec76a351e00b
  • LineFeed Mode: efff2a0ddb1b55aa2ad48b7a245e9ee8b92a41fd
  • Implement MarginMode for (SU) 8219188b1b4394b7f3a2f5b447bedf343a496e7f
  • DECIC 30ee9d1ff119240c02608cbfe7f1f51278c702cc
  • FF Tests pass 67917033378d974a3b65cdd2eb7a2dbe87a80f24
  • Complete DCH fba4cdb904dac46f6f6c4d86e13018bbe7a8b4c9
  • Complete DECDC 27331e3ef0407f97f1ab7869bf415e99444e48be
  • Complete HVP 23ec0c4e5c9f8c3967c051e3915b8a3e3cb1f0c3
  • Complete ICH and IL 833905ab776bb66d57b3f482683e5278c14451a3
  • LF fixes 528f8662c3c37b75512eb71915e8c1fc67a3cc79
  • Simplify 068043ef03c47af339f9314cfa01640d7810a4d0
  • Needed to implement repeat: 65470212ecb42a37a1c8eee6305624cd864ca60a
  • 0f8ac8e363ff7966031394dd4bef0f0158016b1b
  • f601eaeae95cbbb757847fe01b7e8469598dfa2c
  • Color palettes, proper fg/bg 66b49c472eb176d6d69c9636faec195ab3805521
  • Indexed colors 41b70b394d72bdf5dd13d6f4056eb7d48e5f8d01
  • FG/BG chnages: ef62a251d1a24edfe1b6ad82ab0819aa9d4c7689
  • Default colro handling 2fcee46eb98108bb540fc1a67a57d2de0cb1143d
  • More capabilities 408a8e818c32f03697890a8fa8018ffc56571652
  • Behavior fx e9f87d485e17def034160229f7c5214cf891b9b0
  • aa062ec6e759807a34e241c86d92ad1a46e44e45
  • SD fixes 4ce620bca07e521fde88e9bf3179f868f918545d
  • Emulation fixes 63b08568bbb9263d417403f86a441c7f38c67f7d
  • [ ]
    Fuzzer fixes:
  • 4fc8ecbb853ec74a178c615387abf75456c0ebd0
  • 3cf43dafe2fa2146677b7effc93c1f50dbd311cf
  • e6441ee27fb963c6258181daf546081333081177
  • 29e86565a059d5f1e9b490417bd551dc8862387a
  • fd5ec178c0568ff057c9d79afdcac026f57f0595
  • 3fe5fd7a5fb8daf979efe1525d7f94406d5d561a
  • b290efbbe01033cc450db6e7eb529b329311b5df
  • 7edbf003eb8ebb282178e5801e777182c3f7607f
  • 26c194094ccef75b7ccb194259231f9aae4c0b13

Mac App:

  • 229b22e643ef7e4965786d79f03fb0bc34f238c8
  • b69995142d7ac4acece0d60139e6b917f3b51ff5

Cocoa Implementation

Things pending:

  • Cursor drawing (block, underline, blink)
  • Complete color rendering
  • Default colors, customizable colors
  • Scrollback capability
  • Blink support in text
  • Allow fonts to be configured, and add fallback for Bold/Italic to use properties in NSAttr

Screen scraping API

Now that I made HeadlessTerminal public, as I need it for fuzzing, perhaps I should surface more information about the contents of the screen and make a handful of internal classes public.

APIs to surface:

Saving:

  • save (to: URL, format: SaveFormat = .txt)

Accessing content"

  • cols/rows
  • cursorLeft/cursorTop
  • scrollRegion/marginRegion
  • getCell (line: Int, col: Int) -> CharData
  • getText (line: Int)
  • getAttributedText (line: Int) -> [CharData]

Writing to the screen, some basic operations, could surface more:

  • clear ()
  • setColor (...)
  • setCursorPosition (...)
  • write (str)
  • getRegionText (...) -> [String]

Record input/output:

  • setOutputRecorder (...)
  • setInputRecorder (...)

24bit fg/bg color is not implemented and I haz questions...

https://github.com/migueldeicaza/XtermSharp/blob/master/XtermSharp/Terminal.cs#L683

		public int MatchColor (int r1, int g1, int b1)
		{
			throw new NotImplementedException ();
		}

The code in InputHandler.cs looks right:

				} else if (p == 38) {
					// fg color 256
					if (pars [i + 1] == 2) {
						i += 2;
						fg = terminal.MatchColor (
							pars [i] & 0xff,
							pars [i + 1] & 0xff,
							pars [i + 2] & 0xff);
						if (fg == -1)
							fg = 0x1ff;
						i += 2;
					} else if (pars [i + 1] == 5) {
						i += 2;
						p = pars [i] & 0xff;
						fg = p;
					}
				} else if (p == 48) {

But without MatchColor implemented, 24bit color is not implemented. The spec is:

ESC[ 38;2;⟨r⟩;⟨g⟩;⟨b⟩ m Select RGB foreground color
ESC[ 48;2;⟨r⟩;⟨g⟩;⟨b⟩ m Select RGB background color

I tried a naïve try:

	public int MatchColor (int r1, int g1, int b1)
	{
            return (int)System.Drawing.Color.FromArgb(r1,g1, b1).ToArgb();
	}

I obviously don't know what I'm doing because this always returns 255 even though in the debugger I see my values for r1, g1, and b1 being passed in.

What is the value of the the int fg and int bg supposed to hold?

I built this too to help:

        public class XtermCharAttribute {
            public int Attribute { get; set; }

            public static XtermCharAttribute FromAttribute(int attribute) {
                return new XtermCharAttribute(attribute);
            }

            public XtermCharAttribute(int attribute) {
                Attribute = attribute;
            }

            public bool Bold => ((FLAGS)(Attribute >> 18)).HasFlag(FLAGS.BOLD);
            public bool Italic => ((FLAGS)(Attribute >> 18)).HasFlag(FLAGS.ITALIC);
            public bool Underline => ((FLAGS)(Attribute >> 18)).HasFlag(FLAGS.UNDERLINE);

            public System.Drawing.Color FgColor => System.Drawing.Color.FromArgb((Attribute >> 9) & 0x1ff);
            public System.Drawing.Color BgColor => System.Drawing.Color.FromArgb(Attribute & 0x1ff);
        }

What am I doing wrong/missing?

Enter key doesn't always do the right thing

Enter key works for submitting a terminal command, but does not work for selecting a file in Vim or Emacs in their respective file browsers.

It appears to always be trying to insert a line in a read only buffer.

TerminalController

The recently introduced TerminalController was originally introduced to make the run-a-child-process scenario simpler to reuse without duplicating the code in the sample app.

Then the code was extended to handle scrolling. And now we have both TerminalView and TerminalController. I suspect this division could be better.

The scroll handling should be moved into TerminalView and the TerminalControl should probably be renamed ProcessTerminalView or something like that - reflecting the fact that this is a terminal that hosts a local process vs say, be a front-end to a remote network connection

.net Core

Any plan for a future .net core version?

Mouse support

Mouse support to enable reporting of mouse events, sending mouse events, and wiring that up in the UI frameworks.

XtermSharp as a Console Terminal?

Can I use XtermSharp to render a VT stream to the console? Kind of doing a Putty but inside the windows console. I looked at the source a little bit and it lacks a Console driver, which I could find in the Gui.cs repo, but I am not completely sure how it works... Does it just copy the whole XtermSharp buffer frame to the Console on each input?

What approach would you recommend?

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.