-
Notifications
You must be signed in to change notification settings - Fork 15
fix(width): align display width handling with LuaSystem 0.7.0 #208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,170 @@ | ||
| local helpers = require "spec.helpers" | ||
|
|
||
|
|
||
| describe("terminal.text.width", function() | ||
|
|
||
| local width | ||
|
|
||
| setup(function() | ||
| helpers.load() | ||
| width = require("terminal.text.width") | ||
| end) | ||
|
|
||
|
|
||
| teardown(function() | ||
| helpers.unload() | ||
| end) | ||
|
|
||
|
|
||
|
|
||
| describe("utf8cwidth()", function() | ||
|
|
||
| it("returns 1 for ASCII characters", function() | ||
| assert.are.equal(1, width.utf8cwidth(65)) | ||
| assert.are.equal(1, width.utf8cwidth("A")) | ||
| assert.are.equal(1, width.utf8cwidth(" ")) | ||
| end) | ||
|
|
||
|
|
||
| it("accepts string or codepoint and returns same width", function() | ||
| assert.are.equal(width.utf8cwidth("x"), width.utf8cwidth(0x78)) | ||
| end) | ||
|
|
||
|
|
||
| it("returns 2 for fullwidth characters (e.g. CJK)", function() | ||
| assert.are.equal(2, width.utf8cwidth("你")) | ||
| assert.are.equal(2, width.utf8cwidth(0x4F60)) | ||
| end) | ||
|
|
||
|
|
||
| it("uses ambiguous_width for ambiguous characters", function() | ||
| local mid = require("utf8").char(0x00B7) | ||
| width.set_ambiguous_width(1) | ||
| assert.are.equal(1, width.utf8cwidth(mid), "ambiguous_width=1 should give 1") | ||
| width.set_ambiguous_width(2) | ||
| local w2 = width.utf8cwidth(mid) | ||
| assert.is_true(w2 == 1 or w2 == 2, "ambiguous_width=2 should give 1 or 2, got " .. tostring(w2)) | ||
| width.set_ambiguous_width(1) | ||
| end) | ||
|
|
||
|
|
||
| it("errors on invalid type", function() | ||
| assert.has_error(function() | ||
| width.utf8cwidth({}) | ||
| end, "expected string or number, got table") | ||
| end) | ||
|
|
||
| end) | ||
|
|
||
|
|
||
|
|
||
| describe("utf8swidth()", function() | ||
|
|
||
| it("returns 0 for empty string", function() | ||
| assert.are.equal(0, width.utf8swidth("")) | ||
| end) | ||
|
|
||
|
|
||
| it("returns correct width for ASCII string", function() | ||
| assert.are.equal(5, width.utf8swidth("Hello")) | ||
| end) | ||
|
|
||
|
|
||
| it("returns correct width for double-width characters", function() | ||
| assert.are.equal(4, width.utf8swidth("你好")) | ||
| end) | ||
|
|
||
|
|
||
| it("returns correct width for mixed ASCII and wide", function() | ||
| assert.are.equal(6, width.utf8swidth("Hi你好")) | ||
| end) | ||
|
|
||
|
|
||
| it("respects set ambiguous_width", function() | ||
| local mid = require("utf8").char(0x00B7) | ||
| width.set_ambiguous_width(1) | ||
| local w1 = width.utf8swidth(mid) | ||
| width.set_ambiguous_width(2) | ||
| local w2 = width.utf8swidth(mid) | ||
| assert.are.equal(1, w1) | ||
| assert.is_true(w2 == 1 or w2 == 2, "ambiguous_width=2 should give 1 or 2, got " .. tostring(w2)) | ||
| width.set_ambiguous_width(1) | ||
| end) | ||
|
|
||
| end) | ||
|
|
||
|
|
||
|
|
||
| describe("set_ambiguous_width()", function() | ||
|
|
||
| it("accepts only 1 or 2", function() | ||
| width.set_ambiguous_width(1) | ||
| width.set_ambiguous_width(2) | ||
| assert.has_error(function() | ||
| width.set_ambiguous_width(0) | ||
| end, "ambiguous_width must be 1 or 2, got 0") | ||
| assert.has_error(function() | ||
| width.set_ambiguous_width(3) | ||
| end, "ambiguous_width must be 1 or 2, got 3") | ||
| end) | ||
|
|
||
| end) | ||
|
|
||
|
|
||
|
|
||
| describe("detect_ambiguous_width()", function() | ||
|
|
||
| it("returns 1 when terminal not ready (no write)", function() | ||
| width.ambiguous_width = nil | ||
| local w = width.detect_ambiguous_width() | ||
| assert.are.equal(1, w) | ||
| assert.are.equal(1, width.ambiguous_width) | ||
| end) | ||
|
|
||
|
|
||
| it("is idempotent when ambiguous_width already set", function() | ||
| width.set_ambiguous_width(2) | ||
| local w = width.detect_ambiguous_width() | ||
| assert.are.equal(2, w) | ||
| width.set_ambiguous_width(1) | ||
| end) | ||
|
|
||
| end) | ||
|
|
||
|
|
||
|
|
||
| describe("test()", function() | ||
|
|
||
| it("returns same value as utf8swidth for given string", function() | ||
| width.set_ambiguous_width(1) | ||
| local str = "hello" | ||
| assert.are.equal(width.utf8swidth(str), width.test(str)) | ||
| end) | ||
|
|
||
|
|
||
| it("returns 0 for empty or nil", function() | ||
| assert.are.equal(0, width.test("")) | ||
| assert.are.equal(0, width.test(nil)) | ||
| end) | ||
|
|
||
| end) | ||
|
|
||
|
|
||
|
|
||
| describe("test_write()", function() | ||
|
|
||
| it("returns width of written string", function() | ||
| local str = "ab" | ||
| local w = width.test_write(str) | ||
| assert.are.equal(2, w) | ||
| end) | ||
|
|
||
|
|
||
| it("returns 0 for empty or nil", function() | ||
| assert.are.equal(0, width.test_write("")) | ||
| assert.are.equal(0, width.test_write(nil)) | ||
| end) | ||
|
|
||
| end) | ||
|
|
||
| end) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -83,16 +83,15 @@ end | |
|
|
||
|
|
||
|
|
||
| --- Preload known characters into the width-cache. | ||
| -- Typically this should be called right after initialization. It will check default | ||
| -- characters in use by this library, and the optional specified characters in `str`. | ||
| -- Characters loaded will be the `terminal.draw.box_fmt` formats, and the `progress` spinner sprites. | ||
| -- Uses `terminal.text.width.test` to test the widths of the characters. | ||
| -- @tparam[opt] string str additional character string to preload | ||
| --- Detect the terminal's ambiguous character width (for East Asian width). | ||
| -- Call once after `initialize` so that `terminal.text.width.utf8cwidth` and | ||
| -- `utf8swidth` use the correct width (1 or 2) for ambiguous-width characters. | ||
| -- Optional `str` is ignored; kept for API compatibility. | ||
| -- @tparam[opt] string str ignored; kept for backward compatibility | ||
| -- @return true | ||
| -- @within Initialization | ||
| function M.preload_widths(str) | ||
| text.width.test((str or "") .. M.progress._spinner_fmt_chars() .. M.draw._box_fmt_chars()) | ||
| text.width.detect_ambiguous_width() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this function name no longer covers what it does. This can be removed all together. We can just call the detection from the terminal initialization. |
||
| return true | ||
| end | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,6 +42,14 @@ end | |
|
|
||
|
|
||
|
|
||
| --- Returns the current output stream (e.g. for isatty checks). | ||
| -- @treturn file the stream set by `set_stream` or the default | ||
| function M.get_stream() | ||
| return t | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. an alternative could be to add |
||
| end | ||
|
|
||
|
|
||
|
|
||
| --- Writes to the stream. | ||
| -- This is a safer write-function than the standard Lua one. | ||
| -- It doesn't add add tabs between arguments, and it doesn't add a newline at the end (like `print` does). | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since this is removed, the 2 functions;
_spinner_fmt_chars()and_box_fmt_chars()have lost their utility and can be removed from their respective modules.