dr_magnus 04.10.2011 23:32

Tips & tricksПеревод manpages с помощью vim и StarDict

Всем привет.

Что-то давненько я ничего не писал, хотя материала накопилось уже довольно много - ощущается нехватка времени.

В этой статье я расскажу как настроил перевод отдельных слов при чтении man-страниц.

Всем нам время от времени приходится курить маны, и, не смотря на все наши англоязычные познания, мы иногда забываем перевод того или иного слова.

Для себя эту проблему я решил следующим образом.

  1. Pager:
  2. Есть такая чудная вещь, как vimpager - скрипт к vim'у, который может выступать в качестве стандартного пэйджера вместо less.
  3. Переводчик:
  4. Будем использовать консольную версию StarDict - sdcv, которая замечательным образом умеет пользовать скрипты.
  5. Набор словарей для StarDict'а:
  6. Можно использовать любые словари, которые совместимы с StarDict, в зависимости от потребностей.
  7. Чудесный скрипт, который поможет нам все вышеуказанное связать воедино.


Приступим.

  1. Пэйджер.
  2. Установите vimpager любым способом, доступным для вашего дистра и добавьте в .bashrc следующую строку для использования его по умолчанию:
    1
    export PAGER='vimpager'

  3. SDCV и словари к нему.
  4. SDCV, опять же, устанавливается как вашей душе угодно, а словари к нему можно взять на вышеуказанном сайте. Словари можно сделать общесистемными (/usr/share/stardict/dic) или личными ($HOME/.stardict/dic).
  5. Скрипт объединения.
  6. Добавив эти строки в .vimrc, мы можем, при подведении курсора к интересующему нас слову, нажать F3 и получить его перевод.
    Рекомендую: обратить внимание на 'sdcv -u', с помощью которого можно определить используемый словарь

     1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    map <f3>  :call TRANSLATE()<cr>
    function TRANSLATE()
    let a=getline('.')
    let co=col('.')-1
    let starts=strridx(a," ",co)
    let ends = stridx(a," ",co)
    if ends==-1
    let ends=strlen(a)
    endif
    let res = strpart(a,starts+1,ends-starts)
    let cmds = "sdcv -n " . res
    let out = system(cmds)
    echo out
    endfunction


    Рекомендую: обратить внимание на vim-команды отображения текста:
    :set wrap
    :set linebreak
    и др. Они помогут более читабельно отобразить переводимый текст.

Скрин:
На терминале "man mutt". В качестве переводимого слова выбрано "configuration".


З.Ы.
Всё вышесказанное собрано на просторах интернета и не претендует на оригинальность, а только показано с целью продемонстрировать гибкость инструментов Линукса.


Тэги: stardict vim
+ 5 -
Похожие Поделиться

mironov_orig 05.10.2011 00:09 #
кастую скриншот
dr_magnus 05.10.2011 00:58 #
сделал. вот там, где начинается русский текст, там начинает работать переводчик.
dr_magnus 05.10.2011 01:02 #
в качестве словаря выбран "Английский Компьютерный" (en-ru-comp).
отображение переводимого текста реализовано через ж..пу. нужно, наверное, поэкспериментировать с VIM. если кто-нить может что-нить подсказать - буду признателен.
kstep 05.10.2011 03:46 #
А чем тебя не устраивает expand('')? Просто
let res = expand('')
и выкинь всю часть функции до этой строчки нафиг.
kstep 05.10.2011 03:47 #
Парсер-лох. expand('[cword]'), квадратные скобки заменить на угловые.
kstep 05.10.2011 03:50 #
Вот полная функция, которую юзаю я для тех же целей:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if !executable('sdcv')
finish
endif

fun! Translate(word)
let word = system('sdcv -n ' . a:word)
return word
endfun

fun! WinTranslate(word)
let word = Translate(a:word)
if word == '' || word =~# 'Ничего похожего на'
echoerr "No translation found!"
return
endif

silent new
silent put =word
silent exec 'file "Translation for '.a:word.'"'
silent setl nomodified nomodifiable filetype=sdviv
silent 1
endfun

map <leader>t :call WinTranslate(expand('<cword>'))<cr>



По нажатию на Leader-t (при установках по-умолчанию это "\t") открывает окно с переводом слова под курсором.
dr_magnus 05.10.2011 22:56 #
у меня возникла пара вопросов:

1. При использовании твоей функции у меня выбивает ошибку "E21: Изменения невозможны, т.к. отключена опция modifiable: silent put =word". В .vimrc я прописал set modifiable, но это не помогло. Поделись, плз, секретом - ЧЯДНТ.

2. Т.к. я новичек в VIM, может прокоментируешь код, что бы таким как я было легче изучить этот редактор?

Спасибо.
kstep 06.10.2011 00:38 #
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
" Проверка требований, если нет утилиты sdcv то не включаем плагин
if !executable('sdcv')
finish
endif

" Фукнция для перевода слова
" На входе слово для перевода, на выходе — перевод слова,
" который выдаёт sdcv
fun! Translate(word)
let word = system('sdcv -n ' . a:word)
return word
endfun

" Функция для открытия окна с переводом слова
" На входе слово для перевода, на выходе ничего,
" создаёт новое окно с переводом данного слова.
fun! WinTranslate(word)
" Получение перевода, см. функцию выше
let word = Translate(a:word)

" Проверка, есть ли перевод.
" С пустой строкой всё ясно, оператор =~# это поиск
" по регулярке с учётом регистра
" (мнемоника: =(равно)~(регулярка)#(учитывать регистр))
"
" У меня в русской локали LC_ALL=ru_RU.UTF-8
" sdcv выдаёт "Ничего похожего на &lt;слово&gt;",
" если словно не найдено.
if word == '' || word =~# 'Ничего похожего на'
echoerr "No translation found!"
return
endif

" Ок, перевод есть, он в переменной word
" Ниже все команды по настройке окна с переводом
" заглушены командой silent, запрещающей всякий вывод от команд.

silent new " Создаём новое окно

" Специально для dr_magnus, у меня работает без этой строчки.
" Явно разрешить модификацию окна с переводом.
silent setl modifiable

silent put =word " Вставляем перевод в это окно
" Далее командой file устанавливаем красивое имя окна
" "Translation for &lt;слово&gt;"
silent exec 'file "Translation for '.a:word.'"'

" Последний штрих, установка локальных параметров окна:
" nomodified - притворимся, что мы его не меняли, чтобы вим не ругался
" на несохранённые данным при закрытии окна,
" nomodifiable - запретим все изменения в окне, ибо нефиг,
" filetype=sdviv - нужно для отличия окна с переводом от других,
" так что можно на него повесить специфичные автокоманды или подсветку
" синтаксиса.
silent setl nomodified nomodifiable filetype=sdviv

" Переходим на первую строку в окне
silent 1
endfun

" Настройка горячей клавишы, expand('<cword>') выдаёт текущее слово под
" курсором, можно также использовать <сWORD> для получения СЛОВА под курсором.
" Мнемника: c(urrent) word.
map <leader>t :call WinTranslate(expand('<cword>'))<cr>


kstep 06.10.2011 00:42 #
Вот, расписал как ты просил. Почему у тебя не работает... Ты скорее всего запускаешь вим в режиме только для чтения? (это vimpager тот же организует).
Этот плагин я пользую с обычным вимом, просто читаю книжки когда, навожу курсор на непонятное слово и жму \t, получаю перевод в новом окне над текущим.

Специально для тебя я указал нужный параметр silent setl modifiable (см. комментарий). Дело в том, что параметр modifiable является сугубо локальным для данного конкретного буфера, когда ты в .vimrc делаешь set modifiable ты устанавливаешь право на модификацию текущего буфера, потом плагин открывает новое окно с новым буфером, а там этот параметр установлен по-умолчанию для твоего варианта запуска вима, то есть nomodifiable.
kstep 06.10.2011 00:48 #
Ах да, установка. Лучше всего кинуть в ~/.vim/plugin/translate.vim.

Если хочешь это прописать прямо в ~/.vimrc (что не рекомендуется), то убедись, что закомментил первые три строки с проверкой на существование sdcv и выходом из скрипта, потому что если у тебя sdcv не окажется, то не только не создадутся эти все функции и обвязки, но не будет выполнена часть скрипта ~/.vimrc после тела этого плагина.
dr_magnus 06.10.2011 01:39 #
ОФИГЕННО! Большое спасибо! Всё заработало!
но опять же - вопросы:
- расскажи, если не сложно, про silent - встроенную справку я читал, но не очень понял :-(
- если можешь, то расскажи, плз, про методы вывода текста из VIM - можно ли как-нить отформатировать вывод sdcv? в этом выводе явно проглядываются какие-то тэги форматирования, но вот как их использовать не совсем понятно.
kstep 06.10.2011 03:34 #
silent — это команда-глушилка, как раз для скриптов. Дело в том, что при нормальном выполнении команды могут иногда что-то писать на выход, например "echo 123" выведет тебе "123". В скриптах это иногда не нужно, и тогда используется silent как префикс к команде. Можешь попробовать в самом виме ввести "echo 123", а потом "silent echo 123". В первом случае ты увидишь 123 в командной строке как результат вывода echo, во втором этого не произойдёт. В принципе команда "set" ничего не пишет, так что в моём случае это просто перестраховка, но вот та же команда "file" выведет новое имя файла в буфере и краткую инфу по нему, и этот вывод глушится через silent. При этом в случае, если команда будет плеваться ошибками, silent их глушить не будет, для этого нужно делать "silent!", тогда даже сообщения об ошибках ты не увидишь.

Отформатировать можно трёмя способами. Первый — через описание синтаксиса. Вот какой использую я для переводов (~/.vim/syntax/sdviv.vim):

 1
2
3
4
5
6
7
8
9
10
11
12
13
syn match SdvivDictinaryName /^-->.*$/
syn match SdvivTranscription /\[[^]]\+\]/
syn match SdvivWordArticle /\<[0-9]\+\./
syn match SdvivWordMeaning /\<[0-9абвгдезжиклмнопрстуфхцчшщэюя]\+)/
syn match SdvivListItem /\(^\| \)- .*$/
syn match SdvivTerms /_\S\+\.\|\<\S\{2,5}\./

hi link SdvivDictinaryName Title
hi link SdvivTranscription Character
hi link SdvivWordArticle SubTitle
hi link SdvivWordMeaning Number
hi link SdvivListItem Comment
hi link SdvivTerms SpecialChar



Второй — обычными командами редактирования вима, типа "d", "s///" и т.д. Или через скриптинг до вставки через put =word, манипулированием переменной word в данном случае (ну теми же strpart(), substitute() и прочими).

Третий через команды-фильтры на уровне шелла, например system('sdcv -n ' . a:word . ' | sed "s/a/b/g"'), ну или чем-то подобным, либо фильтрвать уже в виме через команды вроде ":.!sed s/a/b/g", что удобнее.

Естественно это всё можно комбинировать как угодно, например откорректировать вывод после вставки в окно, а потом применить синтаксическую расцветку.
kstep 06.10.2011 03:40 #
Да, в 7.3 появилась возможность через синтаксические правила указывать «скрытые» символы и строки, которые раньше «скрывались» через установку цвета символов равным цвету фона, теперь их можно честно спятать, так что эти символы даже видны юзеру не будут, так можно скрывать синтаксические маркеры, которые нужно только для определения расцветки текста (например теги в HTML).

Подробнее см. help conceal, help 'conceallevel' и help 'concealcursor'.
kstep 06.10.2011 03:45 #
Другими словами silent command это аналог command > /dev/null в шеле, а silent! command — это command > /dev/null 2> /dev/null.
philosoft 08.10.2011 21:38 #
И таким образом, лёгким мановением руки, пост-ссылка (ибо весь пост содержится по одной из ссылок в статье) превращается в лекцию-пересказ хелпа вима c комментариями от kstep
kstep 09.10.2011 01:20 #
Не виноватый я, он сам спросил.