vscode Misaligned editor cursor movement with Hangul Jamo characters

qni6mghb  于 6个月前  发布在  Vscode
关注(0)|答案(8)|浏览(51)

当所有扩展都被禁用时,这个问题是否仍然发生?:是

  • VS Code 版本:1.87.2
  • 操作系统版本:Windows 11 23H2 22631.3296

注意
(更新于2024-03-18)
事实证明,下面描述的大多数问题并非来自VSCode的bug。
而是VSCodeVim的问题。抱歉给您带来了误导。
韩文(含汉字)仍然存在问题。
重现步骤:

  • 示例文本
The quick brown fox jumps over a lazy dog. the quick brown fox
The quick brown fox jumps over a lazy dog. The quick brown fox jumps over a lazy dog. The quick brown fox jumps over a lazy dog.
とりなくこゑす / ゆめさませ / みよあけわたる / ひんがしを / そらいろはえて / おきつへに / ほふねむれゐぬ / もやのうち
Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich
정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날. 정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날. 정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날.
정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날. 정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날. 정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날.
เป็นมนุษย์สุดประเสริฐเลิศคุณค่า กว่าบรรดาฝูงสัตว์เดรัจฉาน จงฝ่าฟันพัฒนาวิชาการ อย่าล้างผลาญฤๅเข่นฆ่าบีฑาใคร ไม่ถือโทษโกรธแช่งซัดฮึดฮัดด่า
鉴于对人类家庭所有成员的固有尊严及其平等的和不移的权利的承认,乃是世界自由、正义与和平的基础。鉴于对人类家庭所有成员的固有尊严及其平等的
鑑於人類社會個成員儕有個固有尊嚴脫仔平等個脫仔勿移個權利承認,是世界自由、正義脫仔和平個基礎。鑑於人類社會個成員儕有個固有尊嚴脫仔平等個

字符串的每一行都由以下语言中的字符组成:

  • 英文,全角拉丁字符
  • 英文,半角拉丁字符
  • 日本文
  • 德文
  • 韩文(含汉字Unicode块字符)
  • 韩文(含韩文音节Unicode块字符)
  • 泰文
  • 简体中文
  • 繁体中文

分别表示。
请注意,对于泰文和韩文音节字符,一些Unicode字符组可以组合成单个显示字符。

  • 用于创建示例图像的字体

NeoDunggeunmo 用于拉丁和韩文字形
GNU Unifont 作为备选字体。
两者都是基于8x16网格位图的等宽字体,因此字形完美对齐。
(我认为这只与Unifont有关)。

  1. 步骤
  2. 点击第一个全角字符 左侧将光标放置在那里。
  3. 按上下箭头键分别上下移动光标。
  4. 预期行为

光标垂直移动,不水平移动,沿着图像上的标记线移动。

  1. 当前行为

光标在垂直移动的同时水平移动,忽略字符宽度和组合。

woobm2wo

woobm2wo1#

抱歉,出现了巨大的误导信息。
在测试过程中,VSCodeVim没有被正确地禁用。这个问题的主要原因是VSCodeVim。
除了"Korean with Hangul Jamo",其他一切都按照预期工作。

xxls0lw8

xxls0lw82#

当前行为的记录,正确禁用了扩展

您可以看到光标清楚地在韩文字母行上碰撞。

z4bn682m

z4bn682m3#

字形的宽度完全由字体控制。你是否尝试过像Inconsolata这样的字体,它以制作所有字形等宽而闻名?

wvmv3b1j

wvmv3b1j4#

我在复制中使用的字体字形是“均匀”宽的。
更具体地说,像CJK这样的每个“全角”字形的宽度正好是“半角”字形的两倍。
(它是等宽设计的,但不是技术上的。CJK编程字体通常表现得像这样。)
而VSCode在计算垂直移动时只是将全角字符视为“双倍大小”。
您可以使用像Last Resort这样的字体来测试这种行为,它是一种特殊用途的备用字体,用于指示“tofu”字符所在的Unicode块,并且具有“相等”大小的正方形框字形,覆盖了所有可能的Unicode代码点。

使用该字体,示例文本看起来如下所示。高亮显示的字符位于同一“VSCode垂直线”中。
如您所见,与韩文音节(第5行)不同,韩文假名(第6行)似乎被视为“半角”,因为它与英语、德语和泰语等“半角”字符位于同一“显示垂直线”中。

g6ll5ycj

g6ll5ycj5#

是的,这是当前的实现方式。我们目前的堆栈将字体渲染委托给浏览器,因此我们不自己实现文本布局。要实现基于真实宽度的垂直移动,我们需要基本上渲染光标将降落在的行,并执行偏移搜索以找出最接近当前水平偏移量的列。当前的实现硬编码了一个启发式方法,即宽字符的宽度是窄字符的两倍。这个方法在
vscode/src/vs/editor/common/core/cursorColumns.ts
文件的第37行到第55行中实现。

|  | /** |
|  | * Returns a visible column from a column. |
|  | * @see {@link CursorColumns} |
|  | */ |
|  | publicstaticvisibleColumnFromColumn(lineContent: string,column: number,tabSize: number): number{ |
|  | consttextLen=Math.min(column-1,lineContent.length); |
|  | consttext=lineContent.substring(0,textLen); |
|  | constiterator=newstrings.GraphemeIterator(text); |
|  | |
|  | letresult=0; |
|  | while(!iterator.eol()){ |
|  | constcodePoint=strings.getNextCodePoint(text,textLen,iterator.offset); |
|  | iterator.nextGraphemeLength(); |
|  | |
|  | result=this._nextVisibleColumn(codePoint,result,tabSize); |
|  | } |
|  | |
|  | returnresult; |
|  | } |
and at
vscode/src/vs/editor/common/core/cursorColumns.ts
Lines 27 to 35 in  [0a41778](https://github.com/microsoft/vscode/commit/0a417782b1781d39803b8f1791cfb22f8835ddae)
|  | privatestatic_nextVisibleColumn(codePoint: number,visibleColumn: number,tabSize: number): number{ |
|  | if(codePoint===CharCode.Tab){ |
|  | returnCursorColumns.nextRenderTabStop(visibleColumn,tabSize); |
|  | } |
|  | if(strings.isFullWidthCharacter(codePoint)||strings.isEmojiImprecise(codePoint)){ |
|  | returnvisibleColumn+2; |
|  | } |
|  | returnvisibleColumn+1; |
|  | } |
xesrikrc

xesrikrc6#

这个功能请求现在是我们待办事项列表的候选项目。社区有60天的时间对这个问题进行投票。如果它收到20个赞成票,我们将把它移到我们的待办事项列表中。如果没有,我们将关闭它。要了解更多关于我们如何处理功能请求的信息,请参阅我们的documentation
快乐编码!

m1m5dgzv

m1m5dgzv7#

@alexdima
我不是指“根据当前字体的实际字形大小移动光标垂直方向”的事情。
它是这样的,尽管Hangul Jamo块字符是全角的,但它们并不被视为全角。

omtl5h9j

omtl5h9j8#

在vscode/src/vs/base/common/strings.ts的第677行到第721行中定义了一个名为isFullWidthCharacter的函数,该函数接收一个字符编码(charCode)作为参数,返回一个布尔值。这个函数通过一些特定的Unicode字符范围来判断一个字符是否为全角字符。例如,全角字符的范围包括:0x2E80 - 0xD7AF(CJK部首、康熙部首等)、0xF900 - 0xFAFF(CJK兼容部首)、0xFF01 - 0xFF5E(全角ASCII字符,如:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~A-Z)等。

相关问题