На днях простудился, и пока сидел дома, вспомнил о своей библиотеке для создания консольных окошек в псевдографике. Одна из самых важных задач в её разработке – сделать её совместимой с Linux, потому как в Windows такого рода инструменты в принципе мало кому могут пригодиться. И чтобы она работала под Linux в Mono, я в своё время потратил немало времени. Научил её выводить в терминал псевдографику (сейчас для этого используется ncurses, но только как буфер для вывода), потом разобрался с тем, как обрабатывать пользовательский ввод (для этого я попробовал LibTermKey, и мне понравилось). Кстати, особенности реализации event-driven модели для консольного ввода я уже описывал в заметке об eventfd.
А в этот раз я исследовал проблему того, что после выхода из программы у терминала, из-под которого она запускалась (и gnome-terminal, и xterm), сбивались настройки, и в нём становилось невозможно работать до тех пор, пока пользователь не выполнял команду stty sane.
После локализации воспроизведения проблемы в отдельном консольном приложении выяснилось забавное. Если внутри блока работы с ncurses (между вызовами initscr() и endwin() ) выполнить один из read-методов консоли (Console.ReadLine(), Console.ReadKey()), то терминал убивается после выхода из приложения. Если же read-методы не вызывать вообще, то всё завершается корректно. Но если один из read-методов вызвать до инициализации ncurses, то всё тоже работает хорошо, и уже не важно, сколько раз и где после этого будут вызваны “опасные” read-методы. То есть, первый вызов read-методов в Mono Runtime имеет какие-то побочные эффекты, приводящие к таким последствиям.
// If uncomment next line - all will work OK // May be first access to Console.ReadKey(Line) or Console.KeyAvailable // has side effects and modifies current term settings //bool x = Console.KeyAvailable; IntPtr stdscr = initscr (); cbreak (); noecho (); nonl (); intrflush (stdscr, false); keypad (stdscr, true); start_color (); mvaddstr (4, 5, "Test string!"); refresh (); // If remove this line and dont call reading methods inside ncurses code - // all will work OK. But after first call (if reading method called before ncurses init) // we can call it safe. Console.ReadLine (); // or Console.ReadKey() endwin (); |
Но ведь не будешь же вызывать Console.ReadKey() при старте приложения, прося пользователя нажать клавишу, чтобы всё у нас было хорошо 🙂 К счастью, оказалось достаточно обратиться к свойству Console.KeyAvailable, чтобы выполнить эту инициализацию “первого чтения”. Таким образом, проблема была побеждена малой кровью.
Однако, я всё-таки собрался с силами и оформил баг в багзилле Mono. Надеюсь, это поведение будет исправлено, или хотя бы документировано (если так оно и должно работать).

Навеяно хабрапостом http://habrahabr.ru/post/194740/
Captain mode on. Все проблемы оттого, что у каждого человека своё понимание “справедливости” оценки того или иного труда. Каждый стремится максимизировать свою выгоду. Издатели выступают против “пиратов”, “пираты” – против издателей. Авторы, посредники, пираты и потребители – все лишь ищут способ, как бы урвать побольше. Можно и не ломать голову над тем, какой должна быть “справедливая система”. Её нельзя описать в рамках текущих представлений. Каждый в любом случае будет тянуть одеяло на себя. Возможно, справедливым распределением вознаграждения за труды была бы оценка трудоемкости этого труда. Вне зависимости от степени гениальности получившегося. Соответственно, при этой системе каждый человек бы получал свое вознаграждение пропорционально затраченному труду, а результат его деятельности тут же становился доступным всем остальным людям. Но это коммунизм получается, и мало кто на это согласится, все же мечтают стать гениями и обеспечить себя сверхприбылями (даже несмотря на осознание маловероятности этого события). Поэтому ничего не изменится. Скорее всего, со временем, вектор продолжит сдвигаться в сторону большинства, то есть, потребителей. А гениям и издателям останутся большие, но не сверхбольшие прибыли.
В очередной раз ковыряясь с CSS-ужасом, задумывались ли вы о том, что всё это можно было бы сделать гораздо проще ? Простой пример. Есть div, занимающий некоторое пространство. Внутри него нужно разместить 2 div’a так, чтобы первый занимал по высоте столько, сколько нужно его содержимому, а второй – всё оставшееся пространство. Если вы полезли в гугл и стекофервлоу, могу вам сразу сказать – это невозможно. Да, вы не ослышались, нельзя никак этого добиться. Вы можете указывать абсолютное значение высоты первого div’a, можете использовать трюки с overflow:hidden (правда, почему-то советующие это забывают указать, что если ваше содержимое не влезет в блок, то вы его уже не увидите), можете пытаться что-то сделать с абсолютным позиционированием (тут скорее всего у вас отвалится скроллинг), можете играться с padding-top: -30000; margin-top: 30000. Но всегда будете сталкиваться с проблемами. Потому что по-нормальному это сделать вообще никак нельзя. В CSS3 появилась возможность определить размеры используя вычисления типа 100% – 25px. Но чтобы вычесть что-то, нужно это что-то знать, а узнать размер заголовка или другого блока можно только из джаваскрипта. То есть, в 21 веке в 2013 году HTML стал настолько крут, что в нём нельзя описать простейший случай размещения. Facepalm.
Ещё один пример (из недавнего). Есть div, плавающий слева. Есть плавающий справа. Тот, который слева, занимает чуть больше места по высоте, а правый выровнен с ним по верхней границе. А хочется, чтобы они были на одной линии снизу. Опять же, после получаса поисков по stackoverflow приходим к выводу, что этого тоже нельзя сделать! Ни vertical-align, ни различные комбинации вложенных блоков не спасают отца русской демократии. Самым лучшим способом, который работает, опять же становится явное задание line-height в пикселях. Я не знаю, чем думали проектировщики CSS и HTML, но это просто феерия абсурда. Расскажите об этом любому человеку, кто имел дело с WPF, и он будет смеяться гомерическим хохотом.
В общем, я тут подумываю над тем, как можно эту ситуацию исправить, и пока что не нашел более разумного решения, чем написание джаваскриптового движка, который бы поддерживал “Advanced” сценарии размещения, активизируясь при загрузке страницы. Сами правила задавались бы либо атрибутами DOM-элементов, либо как-то отдельно через js. Поискал в интернете что-то подобное, пока ничего не нашел. Как я понимаю, сейчас народ предпочитает продолжать обниматься с кактусом, в лучшем случае используя CSS-фреймворки с сеточной версткой. Но если вы случайно наткнётесь на что-то в этом роде, дайте знать.

0