namespace Tmate { [SingleInstance] // *INDENT-OFF* class Stdout : Object { public enum TokenType { SOCKET, ADDRESS, MATES, EMPTY, COMMENT, RESTART, INIT, TERM, UNRECOGNIZED, NET_ERROR; public string to_string() { return EnumClass.to_string(typeof(TokenType), this) .replace("TMATE_STDOUT_TOKEN_TYPE_", "Tmate.Stdout.TokenType."); } } public class Token { public TokenType @class {get; private set;} public string[] tokens {get; private set;} public Token(string[] tokens, TokenType @class = UNRECOGNIZED) { this.class = @class; this.tokens = tokens; } public string to_string() { var sep = ""; var end = ""; if (this.tokens.length > 1) { sep += "\n\t"; end += "\n"; } if(this.tokens.length > 0) { sep += "\""; end += "\""; } return @"<$(this.class) {$sep$( string.joinv(@"\", $sep", this.tokens) )$(end.reverse()) }>"; } } private Regex r_connect = /^Connecting to (.+)\.\.\.$/; private Regex r_socket = /^To connect.+ tmate -S (.+) attach$/; private Regex r_mates = /^.+ (joined|left) \(([^()]+)\) -- (\d+) clients? .+$/; private Regex r_closed = /^Session closed$/; private Regex r_restarted = /^Session shell restarted$/; private Regex r_comment = /^(Note: |Reconnecting)/; private Regex r_dnsfail = /^([^ ]+ lookup failure\.).+ \((.+)\)$/; private Regex r_netfail = /^(Error [^:]+)[:] [^:]+[:] (.+)$/; private Regex r_address = /^(ssh|web) \w+ ?(|read only)[:](?:|.+) ([^ ]+)$/; public Token parse(string line) { MatchInfo info; if(line == "") return new Token({}, EMPTY); else if(r_mates.match(line, 0, out info)) return new Token({ info.fetch(1), // joined | left info.fetch(2), // mate ip/domain info.fetch(3) // active mates }, MATES); else if(r_dnsfail.match(line, 0, out info) || r_netfail.match(line, 0, out info)) return new Token({ info.fetch(1), info.fetch(2), }, NET_ERROR); else if(r_comment.match(line)) return new Token({line}, COMMENT); else if(r_restarted.match(line)) return new Token({}, RESTART); else if(r_address.match(line, 0, out info)) return new Token({ info.fetch(1), // web | ssh info.fetch(2), // read only? info.fetch(3) // address }, ADDRESS); else if(r_socket.match(line, 0, out info)) return new Token({ info.fetch(1) }, SOCKET); else if(r_closed.match(line)) return new Token({}, TERM); else if(r_connect.match(line, 0, out info)) return new Token({ info.fetch(1) }, INIT); return new Token({line}); } } }