+7.72
Тера
0.45
Рейтинг

peregrine

Делаем из XTerm "конфетку"

Краткое предисловие
В мире *nix (в первую очередь я говорю о Linux) существует огромное множество эмуляторов терминала. Эмулятор терминала — это такая программа, которая позволяет работать с консолью в графическом режиме (из запущенного графического сервера, обычно это Xorg). Тем, кому начало этой статьи кажется непонятным дальше можно не читать. Остальные могут найти в ней что-нибудь интересное для себя.
Среди множества эмуляторов терминала XTerm занимает особое место, так как он является стандартным терминалом Xorg, находится в практически любом дистрибутиве и не зависит от Qt или GTK. Почему то среди многих людей укоренилось мнение, что XTerm не удобен, не настраивается и страшно выглядит. В этом топике я хочу развеять этот миф.
Предполётная подготовка
Итак, на вашем компьютере стоит какой-нибудь Linux дистрибутив (для BSD тоже должно подойти), настроен видеодрайвер и запущен Xorg. Xterm уже установлен и выглядит как-то так (все картинки кликабельны):

тест стандартных цветов терминала показывает следующую цветовую гамму:

или ещё хуже, когда буковки чёрные на белом фоне или белые на чёрном.
Крайне неприятное зрелище, правда? Лично у меня от такого терминала глаза начинают краснеть и слезиться, особенно, если учесть, что так он выглядит на 24 дюймовом FullHD мониторе. Шрифт настолько мелкий, что читать его делается очень тяжело. Мы хотим увеличить его размер, для этого кликаем в окне XTerm левой кнопкой мыши и… ничего не происходит. Для открытия простого диалога изменения настроек XTerm необходимо кликнуть в нём левой кнопкой мыши, удерживая клавишу Ctrl и не отпуская яё выбрать какие-липо пункты. Но такая настройка практически не даёт изменить внешний вид XTerm и не сохраняется после закрытия терминала.
Настраиваем сам Xterm
После настройки XTerm будет выглядеть так:

Для этого нам надо отредактировать файл .Xresources, лежащий в домашнем каталоге того пользователя, от имени которого вы запускаете эмулятор терминала (в 99% случаев это ваш домашний каталог).
Откройте его вашим любимым текстовым редактором. Если файл отсутствует, то его надо создать. Внимание, в этом файле могут быть настройки и других программ, их менять не надо, если это не старые настройки XTerm. Так же скопируйте содержимое файла .Xdefaults, если он существует и в нём есть какой-либо текст, так как после завершения настройки файл .Xdefaults использоваться не будет.
Теперь рассмотрим содержимое файла .Xresources, необходимое для правильного отображения Xterm. Внимание, вам потребуется также бесплатный шрифт Droid Sans Mono.

!==============================================================================
! XTerm 
!==============================================================================
!Кириллица
XTerm*utf8Title: true
XTerm*faceName: Droid Sans Mono
XTerm*faceSize: 13
xterm*bolfFont: 
xterm*scrollBar:        false
xterm*geometry:         80x50
xterm*eightBitInput:    false
xterm*metaSendsEscape:  true
xterm*colorBDMode:      true
xterm*boldMode:         on
xterm*alwaysBoldMode:   false
xterm*dynamicColors:    on
xterm*colorMode:        on
xterm*saveLines:        10000
xterm*visualBell:       false

!==============================================================================
! Цвета 
!==============================================================================
xterm*colorBD:     #e6d51d
xterm*background:  #111111
xterm*foreground:  #b4b4b4
! Чёрный
xterm*color0:      #000000
xterm*color8:      #555753
! Красный
xterm*color1:      #b6212d
xterm*color9:      #ff6565
! Зелёный
xterm*color2:      #4c8d00
xterm*color10:     #6bbe1a
! Жёлтый
xterm*color3:      #ff8040
xterm*color11:     #e6d51d
! Синий
xterm*color4:      #0086d2
xterm*color12:     #00d2ff
! Маджента
xterm*color5:      #963c59
xterm*color13:     #d3649f
! Циановый
xterm*color6:      #105952
xterm*color14:     #177f75
! Белый
xterm*color7:      #cdcaa9
xterm*color15:     #ffffff

Цвета задаются в шестнадцатеричном коде, так же как и в HTML. Все параметры понятны из названий, например, xterm*geometry: 80x50 означает, что размер окна XTerm будет 50 символов (строк) в высоту и 80 символов (столбцов) в ширину.
Бонус: выпадающий XTerm Yeahconsole
Мне понравилась такая расцветка, но я очень давно полюбил выпадающие терминалы, вроде Guake или Tilda. Настроить их в стиле XTerm, так, чтоб они выглядили точно так же не получилось, потому было принято решение сделать выпадающим терминалом XTerm. Поискав немного в интернете я нашёл готовое решение — Yeahconsole.
Yeahconsole может использовать в качестве терминала и другие эмуляторы, такие, как uxrvt, но о них в следующий раз. Настроим Yeаhconsole в том же самом стиле, для этого допишем в файл .Xresources следующий текст:

!==============================================================================
!Yeahconsole
!==============================================================================
yeahconsole*term:xterm
yeahconsole*consoleHeight:25
yeahconsole*toggleKey:None+F12
yeahconsole*restart:1
yeahconsole*keyFull:None+F11
yeahconsole*saveLines:500
yeahconsole*keySmaller:Control+m
yeahconsole*keyBigger:Control+n
yeahconsole*aniDelay: 30
yeahconsole*metaSendsEscape: true

!==============================================================================
! Цвета 
!==============================================================================
yeahconsole*colorBD:     #e6d51d
yeahconsole*background:  #111111
yeahconsole*foreground:  #b4b4b4
! Чёрный
yeahconsole*color0:      #000000
yeahconsole*color8:      #555753
! Красный
yeahconsole*color1:      #b6212d
yeahconsole*color9:      #ff6565
! Зелёный
yeahconsole*color2:      #4c8d00
yeahconsole*color10:     #6bbe1a
! Жёлтый
yeahconsole*color3:      #ff8040
yeahconsole*color11:     #e6d51d
! Синий
yeahconsole*color4:      #0086d2
yeahconsole*color12:     #00d2ff
! Маджента
yeahconsole*color5:      #963c59
yeahconsole*color13:     #d3649f
! Циановый
yeahconsole*color6:      #105952
yeahconsole*color14:     #177f75
! Белый
yeahconsole*color7:      #cdcaa9
yeahconsole*color15:     #ffffff

Как вы могли догадаться, разница в настройке цветов лишь в том, что вместо xterm* надо писать yeahconsole*
Теперь вот что получилось:

Вы можете изменить цвета, шрифты и стили согласно вашим предпочтениям. Надеюсь всё было достаточно просто и понятно. Жду ваших комментариев и вопросов по настройке XTerm и Yeahconsole.

Пишем многопоточный скрипт на bash

Скажу сразу, что топик посвящён только пользователям *nix систем, в которых есть bash и присутствует утилита GNU parallel. Пользователи Windows могут тоже найти здесь что-то интересное, но они должны учитывать отличия bash скриптов от bat файлов. Статья рассчитана на начинающих, но не на полных новичков, потому элементарные вещи, такие как получение имён и путей файлов подробно рассматриваться не будут. Я лишь кратко напомню о них. Для примера напишем скрипт, оптимизирующий изображения для интернет страничек и удаляющий из них всю лишнюю информацию, такую, как EXIF. Возможно есть более удобные способы написания такого скрипта, но мне они не известны, если Вы знаете, как написать скрипт лучше (сохранив при этом совместимость с Linux), выложите вашу версию в комментариях, я обязательно посмотрю её. Скрипт проверялся только на трёх Linux дистрибутивах: Ubuntu 13.04, Ubuntu 13.10 и Gentoo. Сжатие изображений без потери качества — дело медленное, потому разумно запустить конвертирование в несколько потоков, что даёт значительный прирост (кратный количеству ядер процессора) на многопроцессорных и многоядерных системах. Сразу оговорюсь, что инструменты, которыми я буду пользоваться однопоточные, потому мы будем запускать одновременно несколько процессов обработки (по одному на каждый файл, но в то же время так, чтоб их не было больше, чем доступных машине ядер процессора, GNU Parallel без нас «знает» сколько ядер процессора у нашего ПК и в этом примере нагрузит их все). Вот собственно код скрипта:
#!/bin/bash
opt_optipng ()
{
	input="$1"
	echo "Обрабатывается: (optipng) $input"
	optipng -o3 "$input" >/dev/null 2>&1
}

opt_advpng ()
{
	input="$1"
	echo "Обрабатывается (advpng): $input"
	advpng -z -4 "$input">/dev/null 2>&1
}

opt_advdef ()
{
	input="$1"
	echo "Обрабатывается (advdef): $input"
	advdef -z -4 "$input">/dev/null 2>&1
}

opt_jpegtran ()
{
	input="$1"
	echo "Обрабатывается: $input"
	jpegtran -optimize -progressive -copy none -outfile "$input" "$input" 2>&1
}

opt_gifsicle ()
{
	input="$1"
	echo "Обрабатывается (gifsicle): $input"
	gifsicle --batch --optimize=3 "$input" >/dev/null 2>&1
}

SIZEPNG=$(find . -type f \( -iname '*.png' -o -iname '*.PNG' \) -printf '%s\n' | awk '{SUM+=$1} END {print SUM}');
SIZEGIF=$(find . -type f \( -iname '*.gif' -o -iname '*.GIF' \) -printf '%s\n' | awk '{SUM+=$1} END {print SUM}');
SIZEJPG=$(find . -type f \( -iname '*.JPG' -o -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.JPEG' \) -printf '%s\n' | awk '{SUM+=$1} END {print SUM}')
SIZE=$[SIZEPNG+SIZEGIF+SIZEJPG]

export -f opt_optipng
find  -type f | cut -c 3- | grep -ie '.png$' | sort | parallel opt_optipng '{}'
export -f opt_advpng
find  -type f | cut -c 3- | grep -ie '.png$' | sort | parallel opt_advpng '{}'
export -f opt_advdef
find  -type f | cut -c 3- | grep -ie '.png$' | sort | parallel opt_advdef '{}'
export -f opt_jpegtran
find  -type f | cut -c 3- | grep -e '.JPG$' -e '.jpg$' -e '.jpeg$' -e '.JPEG$' | sort | parallel opt_jpegtran '{}'
export -f opt_gifsicle
find  -type f | cut -c 3- | grep -ie '.gif$' | parallel opt_gifsicle '{}'

echo "Готово!"
SIZEPNG2=$(find . -type f \( -iname '*.png' -o -iname '*.PNG' \) -printf '%s\n' | awk '{SUM+=$1} END {print SUM}');
SIZEGIF2=$(find . -type f \( -iname '*.gif' -o -iname '*.GIF' \) -printf '%s\n' | awk '{SUM+=$1} END {print SUM}');
SIZEJPG2=$(find . -type f \( -iname '*.JPG' -o -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.JPEG' \) -printf '%s\n' | awk '{SUM+=$1} END {print SUM}')
SIZE2=$[SIZEPNG2+SIZEGIF2+SIZEJPG2]
if [ $SIZEPNG ]; then
	PERCENTPNG=$[100-SIZEPNG2*100/SIZEPNG]
fi
if [ $SIZEGIF ]; then
	PERCENTGIF=$[100-SIZEGIF2*100/SIZEGIF]
fi
if [ $SIZEJPG ]; then
	PERCENTJPG=$[100-SIZEJPG2*100/SIZEJPG]
fi
if [ $SIZE ]; then
	PERCENT=$[100-SIZE2*100/SIZE]
	echo "Исходный размер всех обрабатываемых файлов был $SIZE байт а после обработки составил $SIZE2 байт. Среднее сжатие на $PERCENT%
Из них:"
fi
if [ $SIZEPNG ]; then
	echo "PNG: было: $SIZEPNG байт, стало $SIZEPNG2 байт, сжалось на $PERCENTPNG%"
fi
if [ $SIZEGIF ]; then
	echo "GIF: было: $SIZEGIF байт, стало $SIZEGIF2 байт, сжалось на $PERCENTGIF%"
fi
if [ $SIZEJPG ]; then
	echo "JPG: было: $SIZEJPG байт, стало $SIZEPJPG байт, сжалось на $PERCENTJPG%"
fi

Теперь более детально разберём структуру скрипта и его работу:
Скрипт состоит из 5 функций, выполняющих различные оптимизации изображений при помощи программ optipng, AdvanceCOMP, jpegtran и gifsicle. Подробно разбирать их параметры мы не будем, для этого есть man-ы. Скажу, что на текущий момент такое их использование даёт наиболее сильное сжатие, какого мне удалось добиться. Поиск файлов в директориях осуществляется при помощи команды find, find. -type f означает, что искать будем в директории, откуда запущен скрипт и только файлы, а не каталоги и ссылки. Командой sort выполняется сортировка, можно обойтись и без неё, но так вывод скрипта во время работы получается более удобным и информативным. Про echo, grep, cut и awk можете почитать самостоятельно, благо информации по их использованию на русском языке в сети достаточно много и ничего сложного в них нет. Теперь пару слов о функциях:
opt_optipng ()
{
	input="$1"
	echo "Обрабатывается: (optipng) $input"
	optipng -o3 "$input" >/dev/null 2>&1
}

Это функция, код её очень прост. В качестве переменной $input она принимает первый аргумент, с которым её запустили, в нашем скрипте за это отвечает следующий код:
find  -type f | cut -c 3- | grep -ie '.png$' | sort | parallel opt_optipng '{}'

фигурные скобки {} требуются для GNU Parallel, именно там происходит «вставка» аргументов со стандартного ввода, а в нашем случае поступивших через пайп. Осталось обратить ваше внимание на последний, но очень важный момент. Перед запуском функции через GNU Parallel мы должны сделать её видимой для скрипта, как внешнюю команду. (GNU Parallel разрабатывался именно для запуска внешних программ в несколько потоков) Для этого служит строка
export -f opt_optipng

Названия для функции в таком случае надо выбирать такое, чтоб оно не совпадало со стандартными командами, такими как cat, grep, sed и т.д., во избежание недоразумений. После завершения скрипта, экспортированные командой export -f функции будут недоступны и не вызовут никаких проблем (новые команды терминала не появятся).

Надеюсь, кто-нибудь найдёт этот материал полезным. В случае, если Вы найдёте ошибки в статье, не стесняйтесь, зарегистрируйтесь (или войдите на сайт при помощи OpenID или социальных сетей) и напишите о моих ошибках в комментариях, я постараюсь их исправить.

Уроки по C++. Урок 0. Настройка рабочей системы.

Здравствуйте! Я решил написать некоторое количество уроков по C++. Весь код, приведённый мной в этой теме должен гарантированно работать в Linux. Сам я, на момент написания этого топика, использую операционную систему Ubuntu 13.04 и пишу и тестирую всё на ней.
Для Windows придётся вносить незначительные переменные, а именно подключать в начале программы заголовочный файл conio.h, так как Windows терминал (более известный, как командная строка) сразу после выполнения вашей программы закроется, а произойдёт это, если программа не совершает титанический труд очень быстро. Вы даже не успеете разглядеть, что она выведет. Поэтому на платформе Windows используйте функцию getch(), которая станет доступна, после подключения conio.h.
В качестве компилятора я использую g++, а как редактор кода — Geany.
Обязательно читайте книги по программированию. Рекомендую начинать с книги ВВ Подбельского «Стандартный C++».
Начнём с азов, а именно с программы Hello World.
В Geany (можете использовать любой редактор с подсветкой синтаксиса) сохраните его в каталоге my_first_programm под именем hello.cpp. Наберите в нём такой код:

    /*hello.cpp
    * Это моя первая программа, которая не делает ничего полезного, но выводит надпись Hello world!
    * Каждую программу лучше всего начинать с комментария, для чего она служит. Звёздочка в начале этой строки не обязательна, просто для более красивого отображения кода. Это многострочный комментарий. Компилятор его игнорирует, он нужен именно Вам, а не компьютеру.
    */
     
    #include <iostream>//Подключается заголовочный файл потоков ввода/вывода
     
    int main ()//объявляется точка входа в программу
    {//Открывается блок функции main
        std::cout << "Hello world!" << std::endl;//Выводится текст Hello world! std::endl объявляет переход на новую строку.
        return 0;//Так уж принято, что программа должна вернуть какое-либо целое цифровое значение операционной системе. 0 возвращают, если всё прошло успешно.
    }//Закрывается блок функции main
    

Пользователям Windows надо написать так:

    /*hello.cpp
    * Это моя первая программа, которая не делает ничего полезного, но выводит надпись Hello world!
    * Каждую программу лучше всего начинать с комментария, для чего она служит. Звёздочка в начале этой строки не обязательна, просто для более красивого отображения кода. Это многострочный комментарий. Компилятор его игнорирует, он нужен именно Вам, а не компьютеру.
    */
     
    #include <iostream>//Подключается заголовочный файл потоков ввода/вывода
    #include < conio.h>
     
    int main ()//объявляется точка входа в программу
    {//Открывается блок функции main
        std::cout << "Hello world!" << std::endl;//Выводится текст Hello world! std::endl объявляет переход на новую строку. Символ ; ставится после каждого оператора, не являщегося блоком.
        getch();//Ждём нажатия на любую клавишу
        return 0;//Так уж принято, что программа должна вернуть какое-либо целое цифровое значение операционной системе. 0 возвращают, если всё прошло успешно.
    }//Закрывается блок функции main
    

Сохраните файл. Перейдите в терминале в каталог my_first_programm при помощи команды cd. Если вы не знаете команд терминала в linux, то срочно читайте
man man

На английском, так как без него программировать очень туго, особенно в Unix.
Пользователи Windows могут почитать справку по командной строке и её командам в Windows. Но английский также желателен и им.
Считаю, что вы находитесь в каталоге с файлом hello.cpp, в терминале выполняете команду
g++ hello.cpp -o hello

Должен скомпилироваться бинарный файл hello (задан ключом -o hello)
Запустите его командой
./hello

Должно отобразиться сообщение Hello world!

Напишем теперь более полезную программу, считающую сумму двух целых чисел:
//summa.cpp
    #include <iostream>
     
    int main ()
    {
        int a, b;//Объявляем 2 переменные типа int, т.е. целые числа в диапазоне от -2147483648 до 2147483647
        std::cout << "Введите 2 целых числа через пробел" << std::endl;
        std::cin >> a >> b; //Считываем подряд две переменные a и b
        std::cout << a << "+" << b << "=" << a+b << std::endl;//текст при выводе надо заключать в "", а переменные нет.
        return 0;
    }

Так ка Windows не поддерживает UTF8 в командной строке, а соответственно кириллица выведется кракозябрами, то пользователи этой операционной системы должны написать код так:
//summa.cpp
    #include <iostream>
    #include < conio.h>
    #include <clocale>//Для поддержки русского языка при выводе
     
    int main ()
    {
        setlocale(LC_ALL, "russian");//Устанавливаем русскую локаль
        int a, b;//Объявляем 2 переменные типа int, т.е. целые числа в диапазоне от -2147483648 до 2147483647
        std::cout << "Введите 2 целых числа через пробел" << std::endl;
        std::cin >> a >> b; //Считываем подряд две переменные a и b
        std::cout << a << "+" << b << "=" << a+b << std::endl;//текст при выводе надо заключать в "", а переменные нет.
        getch();
        return 0;
    }

И, наконец, напишем более сложную программу, с условным оператором if
Его структура такова:
if(логическое выражение)
{
какие-то операторы,
}
else
{
какие-то операторы,
}

Логическое выражение должно принимать численные значения. В бинарной логике — это 1 (ИСТИНА) и 0 (ЛОЖЬ), но C++ будет трактовать любое число, отличное от 0, как истину. Не путайте знак присваивания a=7 со знаком равенства a==7. Первое выражение даст истину и приравняет переменную a к значению 7. Внутренний механизм его действия будет примерно таков:
1) Приравнять a к 7
2) Дальше с точки зрения компьютера это будет выглядеть как
if(7)
3)Сравнить 7 с 0
4)Так как 7 не равно 0, то значит выражение истинно и необходимо выполнить код в блоке if
Фигурные скобки после if или else не обязательны, если надо выполнить всего 1 оператор, но крайне желательны, чтоб вы не допустили ошибки.
Блок else не является обязательным. В случае, если логическое выражение вернёт истину, выполнятся только те операторы, которые заключены в блоке if, в противном случае те, что заключены в блоке else.
//numbers.cpp
#include <iostream>
 
int main()
{
    float a;
    std::cout << "Введите число\n";// символ \n является управляющим. Он переводит курсор на новую строку. Это пришло в C++ из языка C. Так тоже можно писать.
    std::cin>>a;
    if(a>0)//если a больше 0
    {
        std::cout<< a << ">" << 0<< std::endl;//0 - число, а не текст, его можно и не брать в кавычки
    }
    else
    {
        if(a!=0)//если a не равно 0
        {
            std::cout<< a << "<" << 0<< std::endl;
        }
        else
            std::cout<< a <<" это "<< 0 << std::endl;//Так можно, так как у нас один оператор после else, но лучше так не делать.
    }
    return 0;
}

Домашнее задание:
Написать 4 программы
1)Пользователь вводит с клавиатуры 2 целых числа, надо посчитать их разность.
2)Пользователь вводит с клавиатуры 3 целых числа a b и c. Найти значение x формулы x=2*a+4*b-9*c и вывести число x на экран.
3)Пользователь вводит с клавиатуры по вашему запросу целые числа a, b и c в квадратном уравнении (напомню формулу) a*x2+b*x+c=0. Найти x и написать решение. Т.е. прямо как в тетрадке в школе писали (а может кто из читателей и пишет ;-) ) по всем правилам оформления. Для того, чтобы сделать доступной функцию получения корня, необходимо подключить заголовочный файл math.h. Функция называется sqrt, используется так: y=sqrt(x); (Y равен корень квадратный от X). x передаётся в функцию в качестве аргумента. y храните в переменной типа double, так как может получиться дробное число. Подробнее о типах будет рассказано позже.
4)Пользователь вводит с клавиатуры 2 целых числа, расположить их в порядке возрастания и вывести на экран.