Skip to content
This repository has been archived by the owner on Feb 13, 2019. It is now read-only.

Suggestion: Better xterm compatibility #5

Open
holzschu opened this issue Jan 7, 2018 · 11 comments
Open

Suggestion: Better xterm compatibility #5

holzschu opened this issue Jan 7, 2018 · 11 comments
Labels
enhancement New feature or request

Comments

@holzschu
Copy link
Contributor

holzschu commented Jan 7, 2018

Would it be possible to have the terminal window emulate a xterm? With control caracters to change font color, bold, etc?

Try "curl -s wttr.in/london" in a MacOS Terminal window and in Terminal so see the effects.

@holzschu
Copy link
Contributor Author

holzschu commented Jan 8, 2018

This could probably be done by using a WebView instead of the TextView, and combining with xterm.js https://github.com/xtermjs/xterm.js?files=1
Seems like a big change, though.

@tbodt
Copy link

tbodt commented Jan 9, 2018

You can look at my app for how to do this: https://github.com/tbodt/ish/blob/master/app/TerminalView.m https://github.com/tbodt/ish/tree/master/app/xtermjs

@louisdh louisdh added the enhancement New feature or request label Jan 10, 2018
@palmin
Copy link
Contributor

palmin commented Jan 14, 2018

I have some objective-c code for converting a NSString into a NSAttributtedString where some ANSI escape sequences are interpreted. Avoiding a trip through a web-context might be worth considering.

You can get really far by supporting foreground & background colours sequences and ignoring all other escape sequences.

@ColdGrub1384
Copy link

@tbodt Yes, I'm also using xterm.js, it's very useful and easy to implement

@ian-mcdowell
Copy link
Contributor

I think NSAttributedString & CoreText is probably the best approach for this app. I'd like to not have to deal with WKWebView and its own sandboxing & file I/O issues if possible.

@palmin Where can I find this code? I'd like to Swift-ify it.. 🙂

@palmin
Copy link
Contributor

palmin commented Jan 31, 2018

Very simple and only supports the most basic foreground/background color commands, but it should be easy to adjustAnsiTextState to support additional commands.

@interface AnsiTextState : NSObject {
    UIColor* foregroundColor;
    UIColor* backgroundColor;
}

-(NSUInteger)parseRange:(NSRange)range text:(NSString*)text;
-(NSDictionary*)attributes;

@end

@implementation AnsiTextState

-(void)reset {
    foregroundColor = nil;
    backgroundColor = nil;
}

-(UIColor*)colorWithIndex:(int)index {
    if(index == 0) return [UIColor blackColor];
    if(index == 1) return [UIColor redColor];
    if(index == 2) return [UIColor greenColor];
    if(index == 3) return [UIColor yellowColor];
    if(index == 4) return [UIColor blueColor];
    if(index == 5) return [UIColor magentaColor];
    if(index == 6) return [UIColor cyanColor];
    if(index == 7) return [UIColor whiteColor];

    return nil;
}

-(void)setForegroundColor:(int)index {
    foregroundColor = [self colorWithIndex:index];
}

-(void)setBackgroundColor:(int)index {
    backgroundColor = [self colorWithIndex:index];
}

-(NSUInteger)parseRange:(NSRange)range text:(NSString*)text {
    NSUInteger pos = range.location, end = range.location + range.length;
    while(pos < end) {
        // Ends at ASCII 64 to 126 (@ to ~ / hex 0x40 to 0x7E)
        unichar ch = [text characterAtIndex:pos];
        if(ch >= 64 && ch <= 126) {
            // we have start and end and run through updating state
            NSString* payload = [text substringWithRange:NSMakeRange(range.location, pos - range.location)];
            NSArray<NSString*>* commands = [payload componentsSeparatedByString:@";"];
            for (NSString* command in commands) {
                int cmd = [command intValue];

                if(cmd == 0) [self reset];
                if(cmd >= 30 && cmd <= 37) [self setForegroundColor: cmd-30];
                if(cmd >= 40 && cmd <= 47) [self setBackgroundColor: cmd-40];
            }
            
            return pos+1;
        }
        
        pos += 1;
    }
    return end;
}

-(NSDictionary*)attributes {
    NSMutableDictionary* attr = [NSMutableDictionary new];
    if(foregroundColor != nil) attr[NSForegroundColorAttributeName] = foregroundColor;
    if(backgroundColor != nil) attr[NSBackgroundColorAttributeName] = backgroundColor;
    return attr;
}

@end

@implementation NSString (AnsiEscapeSequence)

-(NSAttributedString*)interpretedEscapeSequences {
    NSMutableAttributedString* string = [NSMutableAttributedString new];

    AnsiTextState* state = [AnsiTextState new];
    NSUInteger pos = 0, len = self.length;
    while(pos < len) {
        // skip forward to next escape sequence
        NSUInteger next = [self rangeOfString:@"\e[" options:0 range:NSMakeRange(pos, len-pos)].location;
        if(next == NSNotFound) next = len;
        if(pos < next) {
            NSString* substr = [self substringWithRange:NSMakeRange(pos, next - pos)];
            NSAttributedString* substring = [[NSAttributedString alloc] initWithString:substr
                                                                            attributes:state.attributes];
            [string appendAttributedString: substring];
        }
        
        // parse escape sequence and adjust state
        NSUInteger done = [state parseRange: NSMakeRange(next+2, len-next-2) text:self];
        pos = done;
    }
    return string;
}

@end

@palmin
Copy link
Contributor

palmin commented Feb 1, 2018

Maybe it would make sense to disable the ansi color commands when using a non-standard background color in the app or perhaps just to have a warning where you change the background color?

Most of these ansi color coded outputs are only readable if you have a dark background or if the colors are adjusted to match a non-standard background color.

@louisdh
Copy link
Owner

louisdh commented Feb 1, 2018

This issue is being (partially?) addressed by #62, btw.

@louisdh
Copy link
Owner

louisdh commented Feb 1, 2018

@palmin Good point. I noticed Terminal on macOS lets users change ANSI colors, which solves background color issues. Not sure if we should go that far, though.

@palmin
Copy link
Contributor

palmin commented Feb 1, 2018

Yes. The escape sequence color/style stuff seems to happen in #62 which seems like a good idea as this issue here is very broad.

@ian-mcdowell
Copy link
Contributor

More work on this in #85. We can support curl progress bars now!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

6 participants