Есть ли способ настроить общесистемные разделители слов для текста в GNOME / GTK +?


5

Я ищу способ определения или просмотра и изменения того, какие символы считаются границами слов в GNOME, аналогично символам «выбор по слову», используемым в терминале GNOME ( связанный вопрос ) или ножам в rxvt.

Например, когда я использую gedit, я могу напечатать abc123xyzи дважды щелкнуть, но будут выбраны только три символа, так как числа по умолчанию считаются границами. Я вижу такое же поведение в Tomboy и, по крайней мере, в нескольких других приложениях GNOME / GTK +, которые я тестировал. Это также присутствует - и особенно раздражает - в строке адреса (но не на внутренних страницах) Google Chrome. Firefox кажется нормальным, я полагаю, поскольку его пользовательский интерфейс написан на XUL, который делает свое дело.

Обратите внимание, что я ищу общее решение, если оно существует - я уже знаю, что есть плагины для gedit, в частности, и, возможно, другие настройки для каждого приложения, но я хочу знать, можно ли это сделать таким образом, чтобы затрагивает большинство или все программы, которые наследуют это поведение от оконного менеджера (я полагаю?).


Пожалуйста, дайте мне знать, если вы не можете воспроизвести это поведение. Если это так, я подозреваю, что это может иметь какое-то отношение к локали ... Я на Debian wheezy, использую GNOME 3, локаль en_US.UTF-8 (иногда fr_FR.UTF-8).
Noyo

Дальнейшие исследования намекают на то, что это, возможно, связано не с языком, а с устоявшейся загадкой, касающейся того, как (все?) Приложения Gtk + ведут себя по умолчанию: mail.gnome.org/archives/gtk-list/2011-June/ msg00060.html и mail.gnome.org/archives/gtk-i18n-list/2011-June/msg00003.html
Noyo

Ответы:


2

Видимо, это было исправлено в версии 1.34.1. Проверьте git log и фиксирует между 1.34.0 и 1.34.1 тегами. Ubuntu 13.04 имеет версию 1.32.5 libpango1.0-0, такую ​​же, как sid. Так что пока нет радости для дистрибутивов на основе Debian. Если вам нужна библиотека, вы можете скомпилировать ее из источников.

Это проблема с PangoLogAttr()функцией, которая кажется, что никто не сообщил об ошибке, жалующейся на это. Выпуск восходит к 2003 году до настоящего времени. Appart почты, которые вы поставляете там:

Если моя интерпретация руководящих принципов верна, то ожидается, что слово, содержащее числа, будет ограничено тем же числом, что и пробелами и символами, кроме '.

Чтобы сообщить об ошибках в панго, просто перейдите по этой ссылке https://bugzilla.gnome.org/enter_bug.cgi?product=pango


Хорошее исследование, спасибо! Странно, однако, что даже пример, приведенный в руководящих принципах, не соответствует значению по умолчанию, обозначающему .границу. В любом случае это может быть скорее запрос функции, чем ошибка. Можете ли вы включить ссылку на то, где можно подать ошибку?
Noyo

Еще раз спасибо! После некоторого быстрого поиска, похоже, что люди этого хотят и действительно подали запросы об ошибках / функциях : bugzilla.gnome.org/show_bug.cgi?id=111503 и bugzilla.gnome.org/show_bug.cgi?id=530427 и bugzilla .gnome.org / show_bug.cgi? id = 97545 как минимум. Может быть, я просто буду следить / комментировать один из них на данный момент.
Noyo

На самом деле, согласно этому последнему, исправлено для моего конкретного примера "abcc123": bug97545.bugzilla-attachments.gnome.org/… . Не знаю, когда эта версия попадет в мой дистрибутив Linux.
Noyo

Это объединено, но это намного более недавно чем ссылка в Вашем комментарии. Смотрите здесь: git.gnome.org/browse/pango/commit/pango/… . Теперь убедитесь, что эта версия включена в какую-либо стабильную версию дистрибутива Linux на данный момент.
Noyo

Я понял, что, хотя вы полностью отвечаете на конкретный случай раздражения границы слова / числа, о котором я упоминал (действительно, основная проблема, которую я лично хотел решить), суть вопроса не была полностью решена. Можете ли вы отредактировать свой ответ, чтобы дополнительно включить ссылки на три вопроса, которые я упомянул во втором комментарии, и кратко оценить их статус? Я не уверен, что то, о чем вы говорите, PangoLogAttr()является правильным, и также были проблемы, связанные с этой функцией. Ваше исследование определенно заслуживает награды, спасибо, еще раз спасибо!
Noyo

0

Для Debian 7 (Wheezy):

Вы можете скачать исходные файлы из Debian и внести изменения самостоятельно, затем перекомпилировать и установить созданные пакеты .deb:

Откройте корневой терминал:

apt-get install dpkg-dev;
apt-get build-dep libpango1.0-0;
exit;

Откройте обычный терминал:

cd; mkdir patch-libpango; cd patch-libpango;
apt-get source libpango1.0-0;

Теперь перейдите в вашу домашнюю папку и откройте файл patch-libpango/pango1.0-1.30.0/pango/break.c, затем найдите этот блок кода:

/* ---- Word breaks ---- */

/* default to not a word start/end */
attrs[i].is_word_start = FALSE;
attrs[i].is_word_end = FALSE;

if (current_word_type != WordNone)
{
    /* Check for a word end */
    switch ((int) type)
    {
    case G_UNICODE_SPACING_MARK:
    case G_UNICODE_ENCLOSING_MARK:
    case G_UNICODE_NON_SPACING_MARK:
    case G_UNICODE_FORMAT:
        /* nothing, we just eat these up as part of the word */
        break;

    case G_UNICODE_LOWERCASE_LETTER:
    case G_UNICODE_MODIFIER_LETTER:
    case G_UNICODE_OTHER_LETTER:
    case G_UNICODE_TITLECASE_LETTER:
    case G_UNICODE_UPPERCASE_LETTER:
        if (current_word_type == WordLetters)
        {
            /* Japanese special cases for ending the word */
            if (JAPANESE (last_word_letter) ||
                    JAPANESE (wc))
            {
                if ((HIRAGANA (last_word_letter) &&
                            !HIRAGANA (wc)) ||
                        (KATAKANA (last_word_letter) &&
                            !(KATAKANA (wc) || HIRAGANA (wc))) ||
                        (KANJI (last_word_letter) &&
                            !(HIRAGANA (wc) || KANJI (wc))) ||
                        (JAPANESE (last_word_letter) &&
                            !JAPANESE (wc)) ||
                        (!JAPANESE (last_word_letter) &&
                            JAPANESE (wc)))
                attrs[i].is_word_end = TRUE;
            }
        }
        else
        {
            /* end the number word, start the letter word */
            attrs[i].is_word_end = TRUE;
            attrs[i].is_word_start = TRUE;
            current_word_type = WordLetters;
        }

        last_word_letter = wc;
        break;

    case G_UNICODE_DECIMAL_NUMBER:
    case G_UNICODE_LETTER_NUMBER:
    case G_UNICODE_OTHER_NUMBER:
        if (current_word_type != WordNumbers)
        {
            attrs[i].is_word_end = TRUE;
            attrs[i].is_word_start = TRUE;
            current_word_type = WordNumbers;
        }

        last_word_letter = wc;
        break;

    default:
        /* Punctuation, control/format chars, etc. all end a word. */
        attrs[i].is_word_end = TRUE;
        current_word_type = WordNone;
        break;
    }
}
else
{
    /* Check for a word start */
    switch ((int) type)
    {
    case G_UNICODE_LOWERCASE_LETTER:
    case G_UNICODE_MODIFIER_LETTER:
    case G_UNICODE_OTHER_LETTER:
    case G_UNICODE_TITLECASE_LETTER:
    case G_UNICODE_UPPERCASE_LETTER:
        current_word_type = WordLetters;
        last_word_letter = wc;
        attrs[i].is_word_start = TRUE;
        break;

    case G_UNICODE_DECIMAL_NUMBER:
    case G_UNICODE_LETTER_NUMBER:
    case G_UNICODE_OTHER_NUMBER:
        current_word_type = WordNumbers;
        last_word_letter = wc;
        attrs[i].is_word_start = TRUE;
        break;

    default:
        /* No word here */
        break;
    }
}

и замените его следующим:

/* ---- Word breaks ---- */

/* default to not a word start/end */
attrs[i].is_word_start = FALSE;
attrs[i].is_word_end = FALSE;

if (current_word_type != WordNone)
{
    /* Check for a word end */
    switch ((int) type)
    {
    case G_UNICODE_SPACING_MARK:
    case G_UNICODE_ENCLOSING_MARK:
    case G_UNICODE_NON_SPACING_MARK:
    case G_UNICODE_FORMAT:
        /* nothing, we just eat these up as part of the word */
        break;

    case G_UNICODE_LOWERCASE_LETTER:
    case G_UNICODE_MODIFIER_LETTER:
    case G_UNICODE_OTHER_LETTER:
    case G_UNICODE_TITLECASE_LETTER:
    case G_UNICODE_UPPERCASE_LETTER:
        if (current_word_type == WordLetters)
        {
            /* Japanese special cases for ending the word */
            if (JAPANESE (last_word_letter) ||
                    JAPANESE (wc))
            {
                if ((HIRAGANA (last_word_letter) &&
                            !HIRAGANA (wc)) ||
                        (KATAKANA (last_word_letter) &&
                            !(KATAKANA (wc) || HIRAGANA (wc))) ||
                        (KANJI (last_word_letter) &&
                            !(HIRAGANA (wc) || KANJI (wc))) ||
                        (JAPANESE (last_word_letter) &&
                            !JAPANESE (wc)) ||
                        (!JAPANESE (last_word_letter) &&
                            JAPANESE (wc)))
                attrs[i].is_word_end = TRUE;
            }
        }

        last_word_letter = wc;
        break;

    case G_UNICODE_DECIMAL_NUMBER:
    case G_UNICODE_LETTER_NUMBER:
    case G_UNICODE_OTHER_NUMBER:

        last_word_letter = wc;
        break;

    default:
        if (wc == 0x005F) break; //underscore
        /* Punctuation, control/format chars, etc. all end a word. */
        attrs[i].is_word_end = TRUE;
        current_word_type = WordNone;
        break;
    }
}
else
{
    /* Check for a word start */
    switch ((int) type)
    {
    case G_UNICODE_LOWERCASE_LETTER:
    case G_UNICODE_MODIFIER_LETTER:
    case G_UNICODE_OTHER_LETTER:
    case G_UNICODE_TITLECASE_LETTER:
    case G_UNICODE_UPPERCASE_LETTER:
        current_word_type = WordLetters;
        last_word_letter = wc;
        attrs[i].is_word_start = TRUE;
        break;

    case G_UNICODE_DECIMAL_NUMBER:
    case G_UNICODE_LETTER_NUMBER:
    case G_UNICODE_OTHER_NUMBER:
        current_word_type = WordNumbers;
        last_word_letter = wc;
        attrs[i].is_word_start = TRUE;
        break;

    default:
        /* No word here */
        break;
    }
}

Вернитесь к своему обычному терминалу:

cd ~/patch-libpango/pango*;
dpkg-buildpackage -rfakeroot -uc -b;

Теперь перейдите в вашу домашнюю папку и откройте папку patch-libpango, вы должны найти там несколько .debфайлов. Установите их все, кроме пакетов debug и doc (в именах которых есть -dbg и -doc)

Теперь вы можете удалить patch-libpangoкаталог, вернитесь к обычному терминалу:

cd; rm -rf patch-libpango;

Готово, вам не нужно перезагружать вашу систему.

Примечание: это также будет обрабатывать подчеркивание как часть слова (найдите 0x005F в отредактированном коде).

Рекомендации:

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.