« get me outta code hell

Wide character support in ANSI compressor - tui-lib - Pure Node.js library for making visual command-line programs (ala vim, ncdu)
about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorrie <towerofnix@gmail.com>2018-12-05 16:27:59 -0400
committerFlorrie <towerofnix@gmail.com>2018-12-05 16:27:59 -0400
commitbc5199c288bb93451927af0cc31a98cf0a25f843 (patch)
tree8fed173eae9769960a3a5458aba3871593b86184
parent754f834035271279b279a13514c8031069dc4f76 (diff)
Wide character support in ANSI compressor
-rw-r--r--package-lock.json21
-rw-r--r--package.json1
-rw-r--r--util/ansi.js19
3 files changed, 38 insertions, 3 deletions
diff --git a/package-lock.json b/package-lock.json
index d020d44..aa06ee1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4,6 +4,27 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "clone": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+      "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
+    },
+    "defaults": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
+      "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
+      "requires": {
+        "clone": "^1.0.2"
+      }
+    },
+    "wcwidth": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+      "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
+      "requires": {
+        "defaults": "^1.0.3"
+      }
+    },
     "word-wrap": {
       "version": "1.2.3",
       "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
diff --git a/package.json b/package.json
index 2d55077..da401ed 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
   "author": "Florrie <towerofnix@gmail.com>",
   "license": "GPL-3.0",
   "dependencies": {
+    "wcwidth": "^1.0.1",
     "word-wrap": "^1.2.3"
   }
 }
diff --git a/util/ansi.js b/util/ansi.js
index 04722c0..f0d7bf7 100644
--- a/util/ansi.js
+++ b/util/ansi.js
@@ -1,3 +1,5 @@
+const wcwidth = require('wcwidth')
+
 const ESC = '\x1b'
 
 const isDigit = char => '0123456789'.indexOf(char) >= 0
@@ -138,6 +140,7 @@ const ansi = {
 
     for (let charI = 0; charI < text.length; charI++) {
       const cursorIndex = (cursorRow - 1) * scrCols + (cursorCol - 1)
+
       if (text[charI] === ESC) {
         charI++
 
@@ -170,8 +173,8 @@ const ansi = {
 
         // CUP - Cursor Position (moveCursor)
         if (text[charI] === 'H') {
-          cursorRow = args[0]
-          cursorCol = args[1]
+          cursorRow = parseInt(args[0])
+          cursorCol = parseInt(args[1])
         }
 
         // SM - Set Mode
@@ -264,7 +267,17 @@ const ansi = {
         char: text[charI], attributes
       }
 
-      cursorCol++
+      // Some characters take up multiple columns, e.g. Japanese text. Take
+      // this into consideration when drawing.
+      const charColumns = wcwidth(text[charI])
+      cursorCol += charColumns
+
+      // If the character takes up 2+ columns, treat columns past the first
+      // one (where the character is) as empty. (Note this is different from
+      // "blank", which represents an empty space character ' '.)
+      for (let i = 1; i < charColumns; i++) {
+        chars[cursorIndex + i] = {char: '', attributes: []}
+      }
 
       if (cursorCol > scrCols) {
         cursorCol = 1