未在Ruby中打印的Unicode框图字符

时间:2018-09-20 16:37:31

标签: python c ruby linux ncurses

我用Ruby开发游戏。它使用ncurses绘制窗口内容并刷新屏幕。这一切在macOS上都可以正常工作,我在那儿进行开发。但是在Linux上,从Ruby 或纯C 与ncurses接口时,除了纯ASCII外,我什么都无法打印。

例如,我得到以下输出:

Hello, world! M-b~U~TM-b~U~PM-b~U~WM-b~U~QM-b~U~QM-b~U~ZM-b~U~PM-b~U~]M-b~U~_M-b~T~@M-b~UM-"

而不是我输入的内容:

Hello, world! ╔═╗║║╚═╝╟─╢

文件编码为UTF-8,envlocale输出报告,LANGLC_*变量在适当情况下为en_USen_US.UTF-8 。终端可以很好地打印这些字符,因此不是字体或终端仿真器设置。

Python 3也可以正常工作。 Ruby和C不会。

(在安装了libncurses5-dev的全新Linux Mint 19安装程序上进行了测试。)

所以,我是否缺少某些设置,或者Python绑定有点特殊,我很走运吗?


看起来是什么

它应该看起来像这样(macOS):

macOS reference pic

但是看起来确实像这样:

ruby on linux

Python代码

此代码可以正常工作:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import locale
import curses

locale.setlocale(locale.LC_ALL, '')

stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.addstr(0, 0, "╔═╗║║╚═╝╟─╢") # dont even need .encode('UTF-8')
stdscr.refresh()
stdscr.getkey()
curses.endwin()

curses模块的文档指出,自ncurses 5起,您必须执行此操作:https://docs.python.org/3/library/curses.html

  

从5.4版开始,ncurses库决定如何使用nl_langinfo函数解释非ASCII数据。这意味着您必须在应用程序中调用locale.setlocale()并使用系统可用的编码之一对Unicode字符串进行编码。

Ruby代码

# coding: utf-8
require "curses"

Curses.init_screen
Curses.start_color
Curses.stdscr.keypad(true) # enable arrow keys
Curses.cbreak # no line buffering / immediate key input
Curses.ESCDELAY = 0
Curses.curs_set(0) # Invisible cursor
Curses.noecho # Do not print keyboard input

Curses.stdscr.addstr(STYLES[:single])
Curses.stdscr.setpos(2,0)
Curses.stdscr.addstr(%Q{╔═╗║║╚═╝╟─╢})

Curses.getch

尝试使用ffi-ncurses宝石代替curses,但无济于事。输出是相同的。

C代码

我用

进行编译
gcc -finput-charset=UTF-8 -fexec-charset=UTF-8 -pedantic -Wall -o main main.c -lncurses

代码如下:

// Most of the code is sample code from "CURHELLO.C"
// (c) Copyright Paul Griffiths 1999

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <langinfo.h>
#include <locale.h>
#include <ncurses.h>

int main(void) {

    // Here I tried to copy what Python is doing:
    setlocale(LC_ALL, ""); // Also tried "C.UTF-8", "en_US.UTF-8"
    nl_langinfo(CODESET);


    WINDOW * mainwin;
    if ( (mainwin = initscr()) == NULL ) {
        fprintf(stderr, "Error initialising ncurses.\n");
        exit(EXIT_FAILURE);
    }

    start_color();
    clear();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);

    mvaddstr(1, 1, "Hello, world! ╔═╗║║╚═╝╟─╢");
    refresh();
    sleep(3);

    delwin(mainwin);
    endwin();
    refresh();

    return EXIT_SUCCESS;
}

编辑

通过链接到ncursesw(请注意结尾的W)使其正常工作,但是在Linux上,它使用Ubuntu Mono(与我尝试过的相同字体)一起以文本宽度的两倍显示特殊字符。在OSX上使用iTerm。

enter image description here

1 个答案:

答案 0 :(得分:2)

实际上这应该是几个问题,但是最近的一个问题询问如何将字符显示为全角。

屏幕截图与给定的示例程序不匹配。这只画了几个示例字符,而屏幕截图显示了方框。

但是,相对于语言环境表(并取决于所使用的 actual 程序),特定的画线字符可能是问题所在。这是因为这些代码是ambiguous width(请参阅U+2550)。该标准由实施者决定将其视为单角还是双角。并非所有人都同意实际宽度。

如果这是bug report,我将得到实际的程序源进行测试,但怀疑问题出在Ruby。