Инструменты пользователя

Инструменты сайта



// sdict - небольшой скрипт-оболочка для StarDict (qstardict и sdcv)

Могу напугать некоторых, но в стародавние времена со словарями (имеется в виду - удобные программы-оболочки и сами словари) в Linux было, мягко сказать, не густо. В то время я настроил у себя дома словарный сервер dictd (боле подробно на английском: dict), сначала просто на локальном хосте, потом, когда появилось ещё парочку компьютеров и достаточно дешёвый доступ в интернет сервер стал использоваться и на них, а так же с работы.

Удобным было почти всё:

  • приятная консольная программка dict - для быстрых запросов
  • возможность настроить словарную базу только в одном месте, а на остальных компьютерах указать только адрес сервера
  • прекрасная графическая программка kdict, которая, запускаясь, проверяла буфер обмена и если там что-то было - переводила его (программа проверяла запущенные копии, запускалась в одном экземпляре)

Время шло, начались появляться и недостатки:

  • много времени стало проводиться за нетбуком, да ещё в отстутствии интернета, иногда нужно было что-то быстро перевести
  • доступность домашнего сервера была явно не на высоте - и свет вырубали и связь рвалась
  • программа kdict со своими удобными свойствами канула в лету (уже и не знаю - вообще она существует, но переводить из буфера обмена она как-то перестала)

Пришлось искать дополнительное, оффлайн решение, желательно не менее функциональное. Благо, что при этом и прогресс не стоял на метсе, появилась чудная программа StarDict, словари для которой на ура переделывались формата dictd да и оболочки были разнообразны:

  • stardict - написана на Gtk+, каноническая версия
  • qstardict - оболочка на Qt4, по своими возможностям оказалась очень похожа на полюбившийся мне kdict, в частности возможности перевода содержимого буфера обмена, стоит ли говорить, что мой выбор остановился на ней? Плюс программа успешно управляется путём посылки DBus уведомлений, что и будет позже мной использовано.
  • sdcv - консольная программа для запроса перевода, по сути аналог dict

Теперь подробнее остановлюсь на qstardict, особенно на работе на переводе содержимого буфера обмена.

Тут достаточно всё просто, но специфично: в настройках говорится, следить за буфером - если там появляется новое значение, показывается всплывающее окно с переводом (или не показывается, если, допустим перевода не найдено и в настройках стоит соответствующий параметр). Можно задавать модификатор - что бы оно не реагировало на каждое выделение.

Мне показался такой вариант не очень удобным. Но не беда - благо программа может управляться по DBus, в частности, для показа этого самого всплывающего окна с переводом. Тут же вспоминаем про удобную программу xclip для работы с буфером обмена из состава Xorg, примешиваем немножно универсальности для работы из X11 или из консоли и получаем такой скрипт:

sdict.sh
#!/bin/sh
 
 
check_prog()
{
  local res
  prog=`which $1 2> /dev/null`
  res=$?
  if [ $res -ne 0 ]; then
    echo "Can't found program: " $1
    echo "Try to install it via your package manager"
    exit 1
  fi
 
  echo $prog
}
 
 
check_process()
{
  pidof "$1" > /dev/null 2>&1
}
 
 
sdict_x11()
{
  local res
  qstardict=`check_prog qstardict`
  qdbus=`check_prog qdbus`
 
  check_process "$qstardict"
  res=$?
  if [ $res -ne 0 ]; then
    # for begin - start qstardict
    "$qstardict" > /dev/null 2>&1 &
    sleep 2
  fi
 
  "$qdbus" org.qstardict.dbus /qstardict org.qstardict.dbus.showPopup "$@"
  "$qdbus" org.qstardict.dbus /qstardict org.qstardict.dbus.showTranslation "$@"
}
 
 
sdict_console()
{
  sdcv=`check_prog sdcv`
  $sdcv -n "$@"
}
 
# force no X11 version
no_x11="false"
if [ "$1" = "--no-x11" ]; then
  no_x11="true"
  shift
fi
 
# take word from commad line or from buffer
TRANSLATE=$@
if [ -z "$1" ]; then
  xclip=`check_prog xclip`
  TRANSLATE="`$xclip -o`"
fi
 
# run translation
if [ -z "$DISPLAY" -o "$no_x11" = "true" ]; then
  sdict_console "$TRANSLATE"
  exit $?
else
  sdict_x11 "$TRANSLATE"
  exit $?
fi

Как она работает?

Просто:

  • при запуске проверяет, что установлена переменная DISPLAY и начинает работать с qstardict
  • если переменная DISPLAY не задана, или первым аргументов в командной строке стоит –no-x11, то работа начинается с консольной версией sdcv
  • если в качестве аргументов sdict передаются какие-то слова - пытается их перевести
  • если список аргументов пуст - пытается получить содержимое буфера обмена при помощи xclip и перевести его
  • перед посылкой сообщения по DBus, проверяет, что qstardict запущен, если нет - то запускает его, ждёт 2 секунды и пытается вызвать его для перевода (тут может быть скрыт подводный камень: у нас на работе есть терминальный сервер на Linux, и графических сессий там может быть много, соответственно у каждого пользователя может быть запущена своя версия qstardict, тут проверка запущенности qstardict может отработать некорретно - исправляется легко, но для себя пока не вижу необходимости, поэтому просто информирую)
  • перед запросом команд xclip, qdbus, qstardict, sdcv производится проверка наличия их в пути поиска переменной окружения $PATH, если не находится - программа выдаёт сообщение об их отсутствии на стандартный вывод и завершает свою работу со статусом 1. Обычно эти программы есть почти в каждом дистрибутиве Linux в одноимённом пакете, в случае ArchLinux:
Команда Пакет Команда для устрановки Примечание
xclip xclip pacman -S xclip
qdbus qt pacman -S qt поставится как зависимость при установке qstardict
qstardict qstardict pacman -S qstardict
sdcv sdcv pacman -S sdcv

Собственно всё, после чего повесил у себя в XFCE4 вызов sdict на горячую клавишу, когда надо, выделяю слово и жму её - смотрю перевод во всплывающем окошке.

Пользуйтесь :)

// Интерактивный tclsh и readline

Стандартная интерактивная оболочка tclsh обладает крайне неприятной особенностью по работе с пользовательским вводом.

На данный момент нашёл такой пакет: tclreadline

Для пользователей ArchLinux в AUR лежит пакет, но он вряд ли соберётся на x86_64 архитектуре, да и другие недочёты есть. В общем, откорректировал немного: http://dl.dropbox.com/u/14324405/tclsh/tclreadline-2.1.0-6.src.tar.gz

Теперь собираем, ставим, прописываем в ~/.tclshrc примерно следующее:

if {$tcl_interactive} {
	  package require tclreadline
	    ::tclreadline::Loop
}

За подробностями в man'ы и на сайта разработчика, к примеру, более увесистый конфиг: http://tclreadline.sourceforge.net/sample.tclshrc

Так же следует не забывать пользоваться командой man:

man tclreadline

Примерно так будет выглядеть tclsh после установки:

Пользуясь случаем, хочу так же упомянуть и графическую tcl-консоль: tkcon, для неё же есть и рабочий PKGBUILD в AUR: https://aur.archlinux.org/packages.php?ID=6881

// Примитивный SMTP клиент

Про SMTP протокол знают все: текстовый, простой, можно почту отослать и при помощи telnet. Собственно, при помощи оного и сделан скрипт ниже.

// Консоль, скрипты, XML и XPath

Иногда в скриптах нужно мало-мало добраться до внутрянки XML файлов – к тегам или свойствам тегов. Для сих целей бывает удобно использовать XPath. Вопрос: а как это делать-то из скриптов?

На помощь приходит утилитка xmllint из состава libxml2. Начиная с версии 2.7.7 или 2.7.8 там появилась опция –xpath которая задаёт выражение для выборки. В более ранних версиях (2.7.6, к примеру) этой опции нет, но есть (в последних тоже) возможность вызова «консоли» и интерактивного разбора XML.

В общем два варианта:

xmllint --xpath '//File/@Name' test.xml

и

echo 'cat //File/@Name' | xmllint --shell test.xml

Остальное - фантазия.

// Делать было вечером, делать было нечего

Сначала поставлена задача: удалить рекомендации в своем блоге на Juick.com, вручную неохота было, решил написать скрипт, в результате получился некоторый аналог DELETEALL, только без удаления подписок, комментов.

Код:

#!/bin/bash
 
### Удаляет ваши сообщения или рекомендации с Juick.com
 
# section может быть: blog, recomm
section="blog"
# имя блога, по сути - ваш ник
blog="vasya"
 
# Jabber account, в котором у вас зарегестрирован juick@juick.com
jname="vasya.pupkin"
jpass="superpassword"
jserv="jabber.ru"
 
## BEGIN ##
u="http://juick.com/$blog/?show=$section"
tmp_file=tmp_$section.txt
while true
do
  # посты со страницы будут удалены, соответственно их место
  # займут более старые
  lynx -dump "$u" > $tmp_file
 
  # Вычленяем ссылку на следующу страницу
  tmp=`cat $tmp_file | grep 'Older ->' | grep '|'`
  if [ -z "$tmp" ]; then
    next_num=`cat $tmp_file | grep 'Older ->' | awk -F']' '{print $1}' | sed 's| \[||'`
  else
    next_num=`cat $tmp_file | grep 'Older ->' | awk -F'|' '{print $2}' | awk -F']' '{print $1}' | sed 's| \[||'`
  fi
  # да, этаким мы сделаем trim, сделайте при помощи sed, будет элегантней (и просто)
  next_num=`echo $next_num | awk '{print $1}'`
  next_link=`cat $tmp_file | grep "$next_num. http://" | grep "show=$section" | grep 'page=' | awk '{print $2}'`
 
  cat $tmp_file \
              | grep '\[[0-9]*\]#[0-9]*,' \
              | grep 'now\|ago' \
              | awk '{print $1}' \
              | sed 's|^\[[0-9]*\]||;s|,$||' \
              | while read line
              do
                post_num=`echo $line | sed 's|^#||'`
                action="D"
 
                [ x"$section" = x"recomm" ] && action='!'
 
                echo "Delete/unrecomend post: $line (http://juick.com/$post_num)"
                echo "$action $line" | sendxmpp -u $jname -p "$jpass" -j $jserv -s 'bye' juick@juick.com
 
                sleep 10
              done
 
  # А вот когда указателя на следующую страницу не будет, тогда выходим
  if [ -z "$next_num" ]; then
    break;
  fi
done

Для чего не спрашивайте, просто стало интересно написать :) Для работы нужно:

  • bash
  • lynx
  • sendxmpp

Счастливые арчеводы могут первые два пункта поставить из репозиториев, а sendxmpp собрать из AUR: http://aur.archlinux.org/packages.php?ID=17929

UPD: спасибо камраду sandr1x, в Ubuntu/Debian работа программы sendxmpp (там кстати её версия указана как 1.18, хотя актуальная - 0.0.8) завершается с ошибкой:

Can't use an undefined value as a HASH reference at /usr/share/perl5/XML/Stream.pm line 1165.

С подобным поведением сталкивались на работе когда настраивали sendxmpp для отправки уведомлений. Решение такое: открываем файл /usr/share/perl5/XML/Stream.pm переходим на строку указанную в ошибке (1165), находим чуть выше ее строку:

    delete($self->{SIDS}->{$currsid});

и заменяем на:

       delete($self->{SIDS}->{$currsid}) unless $currsid eq $sid;

Примерный патч выглядит так:

--- /usr/share/perl5/XML/Stream.pm.orig 2007-07-10 21:16:47.000000000 +0400
+++ /usr/share/perl5/XML/Stream.pm 2009-05-26 13:53:04.000000000 +0400
@@ -1160,7 +1160,7 @@
                $self->{SOCKETS}->{*STDIN} = $sid;
        }
 
-       delete($self->{SIDS}->{$currsid});
+       delete($self->{SIDS}->{$currsid}) unless $currsid eq $sid;
 
    if (exists($self->GetRoot($sid)->{version}) &&
        ($self->GetRoot($sid)->{version} ne ""))

Файл принадлежит пакету libxml-stream-perl версии 1.22 в ArchLinux это пакет perl-xml-stream версии 1.23, там данные исправления уже присутствуют, так что если есть возможность - обновляемся, или ставим Arch, правда не задаем глупых вопросов, а то новоявленные арчеводы ex-убунтоиды ими уже на форуме поддостали :)