From 4b3a5e1ae6df19530bc10f0e6dbcebefe1f23976 Mon Sep 17 00:00:00 2001 From: Florian Mounier Date: Thu, 29 Sep 2016 11:31:45 +0200 Subject: [PATCH] Add horizontal wrap (expandable no wrapping lines) on decset 77 --- butterfly/sass/_layout.sass | 28 ++++++++++++++ butterfly/static/ext.js | 23 +++++++++++ butterfly/static/main.css | 21 ++++++++++ butterfly/static/main.js | 76 +++++++++++++++++++++++++------------ coffees/term.coffee | 70 +++++++++++++++++++++------------- 5 files changed, 168 insertions(+), 50 deletions(-) diff --git a/butterfly/sass/_layout.sass b/butterfly/sass/_layout.sass index ac0637e..5b19c37 100644 --- a/butterfly/sass/_layout.sass +++ b/butterfly/sass/_layout.sass @@ -29,6 +29,34 @@ body .line.active background-color: $active-bg + .line.extended + overflow-x: auto + overflow-x: overlay + cursor: zoom-in + background-image: linear-gradient(90deg, rgba(darken($bg, 3%), 0), 95%, darken($bg, 3%)) + + &:not(.expanded):hover + background-color: lighten($bg, 2%) + + &.expanded + cursor: zoom-out + background-color: darken($bg, 3%) + + .extra + display: block + white-space: pre-line + word-break: break-all + + &::-webkit-scrollbar + background: rgba($scroll-bg, .1) + height: 0 + + &::-webkit-scrollbar-thumb + background: rgba($scroll-fg, .1) + + &::-webkit-scrollbar-thumb:hover + background: rgba($scroll-fg-hover, .1) + &::-webkit-scrollbar background: $scroll-bg width: $scroll-width diff --git a/butterfly/static/ext.js b/butterfly/static/ext.js index f1d975f..c77169d 100644 --- a/butterfly/static/ext.js +++ b/butterfly/static/ext.js @@ -156,6 +156,29 @@ } }); + Terminal.on('change', function(lines) { + var j, len1, line, results; + results = []; + for (j = 0, len1 = lines.length; j < len1; j++) { + line = lines[j]; + if (indexOf.call(line.classList, 'extended') >= 0) { + results.push(line.addEventListener('click', (function(line) { + return function() { + if (indexOf.call(line.classList, 'expanded') >= 0) { + return line.classList.remove('expanded'); + } else { + line.classList.add('expanded'); + return butterfly.nativeScrollTo(); + } + }; + })(line))); + } else { + results.push(void 0); + } + } + return results; + }); + walk = function(node, callback) { var child, j, len1, ref, results; ref = node.childNodes; diff --git a/butterfly/static/main.css b/butterfly/static/main.css index 036663b..949bc20 100644 --- a/butterfly/static/main.css +++ b/butterfly/static/main.css @@ -2816,6 +2816,27 @@ body { /* Pop ups */ } body .line.active { background-color: transparent; } + body .line.extended { + overflow-x: auto; + overflow-x: overlay; + cursor: zoom-in; + background-image: linear-gradient(90deg, rgba(9, 8, 10, 0), 95%, #09080a); } + body .line.extended:not(.expanded):hover { + background-color: #161419; } + body .line.extended.expanded { + cursor: zoom-out; + background-color: #09080a; } + body .line.extended.expanded .extra { + display: block; + white-space: pre-line; + word-break: break-all; } + body .line.extended::-webkit-scrollbar { + background: rgba(17, 15, 19, 0.1); + height: 0; } + body .line.extended::-webkit-scrollbar-thumb { + background: rgba(244, 234, 213, 0.1); } + body .line.extended::-webkit-scrollbar-thumb:hover { + background: rgba(244, 234, 213, 0.1); } body::-webkit-scrollbar { background: #110f13; width: 0.75em; } diff --git a/butterfly/static/main.js b/butterfly/static/main.js index 3f346a8..1269ddd 100644 --- a/butterfly/static/main.js +++ b/butterfly/static/main.js @@ -282,6 +282,7 @@ this.applicationCursor = false; this.originMode = false; this.autowrap = true; + this.horizontalWrap = false; this.normal = null; this.charset = null; this.gcharset = null; @@ -535,7 +536,7 @@ }; Terminal.prototype.refresh = function(force) { - var active, attr, ch, classes, cursor, data, fg, group, i, j, k, len, len1, len2, len3, len4, line, lines, m, modified, newOut, o, out, q, ref, ref1, ref2, ref3, ref4, ref5, skipnext, styles, u, v, x; + var active, attr, ch, classes, cls, cursor, data, fg, group, i, j, k, len, len1, len2, len3, len4, line, lines, m, modified, newOut, o, out, q, ref, ref1, ref2, ref3, ref4, ref5, skipnext, styles, u, v, x; if (force == null) { force = false; } @@ -678,14 +679,27 @@ if (line.wrap) { out += '\u23CE'; } + if (line.extra) { + out += '' + line.extra + ''; + } if (this.children[j]) { this.children[j].innerHTML = out; modified.push(this.children[j]); if (x !== -Infinity) { this.children[j].classList.add('active'); } + if (line.extra) { + this.children[j].classList.add('extended'); + } } else { - newOut += "
" + out + "
"; + cls = ['line']; + if (x !== -Infinity) { + cls.push('active'); + } + if (line.extra) { + cls.push('extended'); + } + newOut += "
" + out + "
"; } this.screen[j].dirty = false; } @@ -831,11 +845,17 @@ case "\n": case "\x0b": case "\x0c": - this.screen[this.y + this.shift].dirty = true; - this.nextLine(); + if (this.horizontalWrap) { + this.screen[this.y + this.shift].extra += ch; + } else { + this.screen[this.y + this.shift].dirty = true; + this.nextLine(); + } break; case "\r": - this.x = 0; + if (!this.horizontalWrap) { + this.x = 0; + } break; case "\b": if (this.x >= this.cols) { @@ -877,11 +897,15 @@ ch = this.charset[ch]; } if (this.x >= this.cols) { - if (this.autowrap) { - this.screen[this.y + this.shift].wrap = true; - this.nextLine(); + if (this.horizontalWrap) { + this.screen[this.y + this.shift].extra += ch; + } else { + if (this.autowrap) { + this.screen[this.y + this.shift].wrap = true; + this.nextLine(); + } + this.x = 0; } - this.x = 0; } this.putChar(ch); this.x++; @@ -1291,8 +1315,7 @@ attr = this.cloneAttr(this.curAttr); attr.html = "
" + safe + "
"; this.screen[this.y + this.shift].chars[this.x] = attr; - this.screen[this.y + this.shift].dirty = true; - this.screen[this.y + this.shift].wrap = false; + this.resetLine(this.screen[this.y + this.shift]); this.nextLine(); break; case "IMAGE": @@ -1307,8 +1330,7 @@ attr = this.cloneAttr(this.curAttr); attr.html = ""; this.screen[this.y + this.shift].chars[this.x] = attr; - this.screen[this.y + this.shift].dirty = true; - this.screen[this.y + this.shift].wrap = false; + this.resetLine(this.screen[this.y + this.shift]); break; case "PROMPT": this.send(content); @@ -1865,8 +1887,7 @@ line[x] = this.eraseAttr(); x++; } - this.screen[y + this.shift].dirty = true; - return this.screen[y + this.shift].wrap = false; + return this.resetLine(this.screen[y + this.shift]); }; Terminal.prototype.eraseLeft = function(x, y) { @@ -1874,14 +1895,19 @@ while (x--) { this.screen[y + this.shift].chars[x] = this.eraseAttr(); } - this.screen[y + this.shift].dirty = true; - return this.screen[y + this.shift].wrap = false; + return this.resetLine(this.screen[y + this.shift]); }; Terminal.prototype.eraseLine = function(y) { return this.eraseRight(0, y); }; + Terminal.prototype.resetLine = function(l) { + l.dirty = true; + l.wrap = false; + return l.extra = ''; + }; + Terminal.prototype.blankLine = function(cur, dirty) { var attr, i, line; if (cur == null) { @@ -1900,7 +1926,8 @@ return { chars: line, dirty: dirty, - wrap: false + wrap: false, + extra: '' }; }; @@ -2304,8 +2331,7 @@ this.screen[this.y + this.shift].chars.splice(this.x, 1); this.screen[this.y + this.shift].chars.push(this.eraseAttr()); } - this.screen[this.y + this.shift].dirty = true; - return this.screen[this.y + this.shift].wrap = false; + return this.resetLine(this.screen[this.y + this.shift]); }; Terminal.prototype.eraseChars = function(params) { @@ -2318,8 +2344,7 @@ while (param-- && j < this.cols) { this.screen[this.y + this.shift].chars[j++] = this.eraseAttr(); } - this.screen[this.y + this.shift].dirty = true; - return this.screen[this.y + this.shift].wrap = false; + return this.resetLine(this.screen[this.y + this.shift]); }; Terminal.prototype.charPosAbsolute = function(params) { @@ -2455,6 +2480,8 @@ return this.autowrap = true; case 66: return this.applicationKeypad = true; + case 77: + return this.horizontalWrap = true; case 9: case 1000: case 1002: @@ -2534,6 +2561,8 @@ return this.autowrap = false; case 66: return this.applicationKeypad = false; + case 77: + return this.horizontalWrap = false; case 9: case 1000: case 1002: @@ -2834,8 +2863,7 @@ while (i < l) { this.screen[i].chars.splice(this.x, 1); this.screen[i].chars.push(this.eraseAttr()); - this.screen[i].dirty = true; - this.screen[i].wrap = false; + this.resetLine(this.screen[i].dirty); results1.push(i++); } return results1; diff --git a/coffees/term.coffee b/coffees/term.coffee index 7be84a1..d7ef5fe 100644 --- a/coffees/term.coffee +++ b/coffees/term.coffee @@ -168,6 +168,7 @@ class Terminal @applicationCursor = false @originMode = false @autowrap = true + @horizontalWrap = false @normal = null # charset @@ -421,6 +422,8 @@ class Terminal @document.createTextNode(cursor.textContent), cursor) for active in @body.querySelectorAll(".line.active") active.classList.remove('active') + # for active in @body.querySelectorAll(".line.extended") + # active.classList.remove('extended') newOut = '' modified = [] @@ -526,14 +529,22 @@ class Terminal attr = data out += "" unless @equalAttr attr, @defAttr out += '\u23CE' if line.wrap + if line.extra + out += '' + line.extra + '' if @children[j] @children[j].innerHTML = out modified.push @children[j] if x isnt -Infinity @children[j].classList.add 'active' + if line.extra + @children[j].classList.add 'extended' else - newOut += "
#{out}
" + cls = ['line'] + if x isnt -Infinity + cls.push 'active' + if line.extra + cls.push 'extended' + newOut += "
#{out}
" @screen[j].dirty = false if newOut isnt '' @@ -644,12 +655,16 @@ class Terminal # '\n', '\v', '\f' when "\n", "\x0b", "\x0c" # @x = 0 if @convertEol - @screen[@y + @shift].dirty = true - @nextLine() + if @horizontalWrap + @screen[@y + @shift].extra += ch + else + @screen[@y + @shift].dirty = true + @nextLine() # '\r' when "\r" - @x = 0 + unless @horizontalWrap + @x = 0 # '\b' when "\b" @@ -697,11 +712,13 @@ class Terminal if ch >= " " ch = @charset[ch] if @charset?[ch] if @x >= @cols - if @autowrap - @screen[@y + @shift].wrap = true - @nextLine() - @x = 0 - + if @horizontalWrap + @screen[@y + @shift].extra += ch + else + if @autowrap + @screen[@y + @shift].wrap = true + @nextLine() + @x = 0 @putChar ch @x++ if @forceWidth and "\uff00" < ch < "\uffef" @@ -1150,8 +1167,6 @@ class Terminal switch @prefix # User-Defined Keys (DECUDK). when "" - # Disabling this for now as we need a good script - # striper to avoid malicious script injection pt = @currentParam unless pt[0] is ';' console.error "Unknown DECUDK: #{pt}" @@ -1171,8 +1186,7 @@ class Terminal attr.html = ( "
#{safe}
") @screen[@y + @shift].chars[@x] = attr - @screen[@y + @shift].dirty = true - @screen[@y + @shift].wrap = false + @resetLine @screen[@y + @shift] @nextLine() when "IMAGE" @@ -1190,8 +1204,7 @@ class Terminal "") @screen[@y + @shift].chars[@x] = attr - @screen[@y + @shift].dirty = true - @screen[@y + @shift].wrap = false + @resetLine @screen[@y + @shift] when "PROMPT" @send content @@ -1690,18 +1703,21 @@ class Terminal while x < @cols line[x] = @eraseAttr() x++ - @screen[y + @shift].dirty = true - @screen[y + @shift].wrap = false + @resetLine @screen[y + @shift] eraseLeft: (x, y) -> x++ @screen[y + @shift].chars[x] = @eraseAttr() while x-- - @screen[y + @shift].dirty = true - @screen[y + @shift].wrap = false + @resetLine @screen[y + @shift] eraseLine: (y) -> @eraseRight 0, y + resetLine: (l) -> + l.dirty = true + l.wrap = false + l.extra = '' + blankLine: (cur=false, dirty=true) -> attr = (if cur then @eraseAttr() else @defAttr) line = [] @@ -1713,6 +1729,7 @@ class Terminal chars: line dirty: dirty wrap: false + extra: '' ch: (cur) -> if cur then @eraseAttr() else @defAttr @@ -2193,8 +2210,7 @@ class Terminal while param-- @screen[@y + @shift].chars.splice @x, 1 @screen[@y + @shift].chars.push @eraseAttr() - @screen[@y + @shift].dirty = true - @screen[@y + @shift].wrap = false + @resetLine @screen[@y + @shift] # CSI Ps X # Erase Ps Character(s) (default = 1) (ECH). @@ -2204,8 +2220,7 @@ class Terminal j = @x # xterm @screen[@y + @shift].chars[j++] = @eraseAttr() while param-- and j < @cols - @screen[@y + @shift].dirty = true - @screen[@y + @shift].wrap = false + @resetLine @screen[@y + @shift] # CSI Pm ` Character Position Absolute # [column] (default = [row,1]) (HPA). @@ -2434,6 +2449,8 @@ class Terminal @autowrap = true when 66 @applicationKeypad = true + when 77 + @horizontalWrap = true # X10 Mouse # no release, no motion, no wheel, no modifiers. when 9, 1000, 1002, 1003 # any event mouse @@ -2595,6 +2612,8 @@ class Terminal @autowrap = false when 66 @applicationKeypad = false + when 77 + @horizontalWrap = false when 9, 1000, 1002 , 1003 # any event mouse @x10Mouse = false @vt200Mouse = false @@ -3175,8 +3194,7 @@ class Terminal while i < l @screen[i].chars.splice @x, 1 @screen[i].chars.push @eraseAttr() - @screen[i].dirty = true - @screen[i].wrap = false + @resetLine @screen[i].dirty i++ # DEC Special Character and Line Drawing Set.