Это сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

Бинарные часы на bash

Раз пошла такая пьянка (в смысле, раз уж день программиста), я на радостях решил не останавливаться на достигнутом и написать что-нибудь ещё на Bash.

Bash Binary Clock (9.50КиБ)

Бинарные часы — популярное сейчас развлечение программистов, вроде написания игры «Жизнь». Как можно догадаться из названия, они показывают время в двоичной системе исчисления. Самое интересное в моей реализации — как подавляется ввод клавиатуры, это неочевидно. Всё дело в следующих строчках:

# Нажатие «Enter» нужно отключать отдельно
bind -r '\r'
# Сохраняем предыдущее состояние
ORIG=`stty -g`
# Отключаем остальную клавиатуру
stty -echo
# На выходе всё нужно восстановить как было
function Restore {
    stty "$ORIG"
    bind '"\r":accept-line'
}

trap 'Restore' EXIT

Наверняка не раз ещё пригодится. Сама программа бинарных часов дальше, там у меня несколько сложнее, так как я ещё убираю с экрана курсор, чтобы не мешался. Выйти из программы просто — надо нажать Ctrl-C.

#!/bin/bash

declare -a xy

# Выключаем Enter
bind -r '\r'
# Выключаем остальную клавиатуру
ORIG=`stty -g`
stty -echo

function Restore {
    stty "$ORIG"
    bind '"\r":accept-line'
    echo -ne "\033[5B\033[?25h\033[m"
}

trap 'Restore' EXIT

# Цвета наших «стрелок»
colors=(30 34)

# Очистка графического массива
function Clear {
    xy=
}

# Подготовка маски одного разряда
function Print {
    mask=$(printf '%08d' `echo "obase=2; $1" | bc`)
    let pos="$2*4"

    for x in {0..1}; do
        for y in {0..3}; do
            xy[$pos+$x+$y*100]=${mask:$x*4+$y:1}
        done
    done
}

# Печать часов на экран
function PrintClock {
    echo -e "\033[?25l\033[1mBash Binary Clock by Evgeny Stepanischev\033[0m\n"

    for y in {0..3}; do
        for x in {0..9}; do
            c=${colors[${xy[$x+$y*100]:-0}]}
            echo -ne "\033[${c}m▣"
        done
        echo -e "\033[0m"
    done

    # после печати часов передвигаем курсов так,
    # чтобы следующий кадр выводился поверх предыдущего
    echo -en "\033[8A"
}

# Вывод часов
function Clock {
    Clear
    for i in {0..2}; do
        Print $1 $i
        shift
    done

    PrintClock

    echo -e "\n"
}

while true; do
    Clock `date "+%H %M %S"`
    sleep 1
done

Я писал под «Мак», так что на других системах может и не завестись.

7 комментариев
dinoel 2011

Тупо скопипейстил, не работает (ubuntu 10). Выложи файлом, интересно :)

Евгений Степанищев (bolknote.ru) 2011

Комментарий для dinoel:

Я под «Мак» это всё делаю, может и не работать где-то :) Вот, на 10 дней ссылка: http://zalil.ru/31696117

Евгений Степанищев (bolknote.ru) 2011

Комментарий для dinoel:

Посмотрел на CentOS, работает. Терминал ANSI-цвета поддерживает, запускаешь через bash (не через sh)?

about.me/rembish 2011

Ubuntu 10.04 работает.
Дело в bash, sh такое не тянет.

ks1v 2011

Тупо скопипейстил, работает (ubuntu 11.04) (=

maks_sergeich 2012

Спасибо, все работает
linux mint 12

maks_sergeich 2012

Спасибо, все работает
linux mint 12