Различия между версиями 3 и 4
Версия 3 от 2022-09-27 17:24:40
Размер: 10593
Редактор: FrBrGeorge
Комментарий:
Версия 4 от 2022-10-01 20:33:22
Размер: 10947
Редактор: FrBrGeorge
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 43: Строка 43:
 * [[http://dkhramov.dp.ua/Comp.NcursesTutorial|простая методичка]]
 * (кому интересно) [[http://grep.cs.msu.ru/BESTA/ruprog/curter.doc.txt|Учебник на русском]]
 * [[http://dkhramov.dp.ua/Comp.NcursesTutorial.html|простая методичка]]
 * (кому интересно) [[http://grep.cs.msu.ru/BESTA/ruprog/curter.doc.txt|Учебник на русском]] (по старому curses, но зато простой)
Строка 46: Строка 46:
 * (кому интересно) [[https://invisible-island.net/ncurses/ncurses-intro.html|Учебник от автора ncurses]]  * (кому интересно) [[https://invisible-island.net/ncurses/ncurses-intro.html|Учебник от автора ncurses]] (изначально — от самого [[RW:Реймонд,_Эрик_Стивен|ESR]]а ☺)
  * [[http://www.steppe-rain.ru/sites/default/files/linux/linux/ncurses.html|перевод]] (на всякий случай спас его [[http://grep.cs.msu.ru/ncurses.html|тут]])

Работа с терминалом; пример простого проекта

Терминал

TODO перенести в первую лекцию, здесь только упомянуть:

  • В/В байтов
  • Управление со стороны ОС (сигналы с клавиатуры),
    • stty

  • Преобразование B/B в cooked mode vs raw mode
    • Игрища с переводом строки
    • Примитивное редактирование В/В

Управление выводом со стороны приложения, ESC-последовательности

  • Немного истории
  • Изменение атрибутов текста
    • xterm:

      $ echo -e '\e[44;36m'; cat; echo -e '\e[m'
      • В конце команды — Enter + ^D

  • Позиционирование курсора
    • xterm:

      $ echo -e '\e[2J\e[10;10HЭто 10:10\e[2;20HЭто 2:20\e[20;5HЭто 20:5'
  • дополнительные устройства ввода (например, мышь) — имитация ввода с клавиатуры (обычно включается особой ESC-последовательностью)
    • xterm:

      • $ echo -e '\e[?1002h'; cat; echo -e '\e[?1002l'
        
      • или 1003

terminfo(/termcap); tput/infocmp

  • Унификация управляющих последовательностей
  • Проблемы с неправильным $TERM

Неожиданный бонус Tektronix_4010:

  • если вы используете xterm, просто скачайте этот файл и скажите ему cat:

    •   $ cat map.tek.xterm
      • Хуже не будет :)

  • Для пользователей xterm в дистрибутивах линейки ALT (возможно, и для других тоже) — сценарий на shell, который показывает все .tek-файлы в заданном каталоге (по умолчанию — в документации по xterm).

Curses

NCurses — свободная (на сегодняшний день, главная) реализация Curses

  • Curses: библиотека работы с произвольным терминалом
    • Независимость от типа терминала
    • Экран = матрица символов (а не телетайп)
    • Важно — функции вывода заполняют эту воображаемую матрицу (а не настоящий экран), экран обновляется отдельной командой.

  • Простой пример:
       1 #include <curses.h>
       2 
       3 main ()
       4 {
       5         initscr ();
       6         move (LINES/2 - 1, COLS/2 - 4);
       7         addstr ("Hello, World!");
       8         getch ();
       9         endwin ();
      10 }
    
    • Сборка: cc Hello.c -lcurses -o Hello

    • initscr() / endwin() — инициализация и останов движка curses

    • move() — перемещение курсора, LINES/COLS — размер экрана

    • addstr() — аналог puts()

    • (никогда больше не используем -lcurses)

  • Если надо по-русски, программа должна установить локаль:
       1 #include <curses.h>
       2 #include <locale.h>
       3 
       4 main ()
       5 {
       6         setlocale(LC_ALL, "");
       7         initscr ();
       8         move (LINES/2 - 1, COLS/2 - 4);
       9         addstr ("Привет, мир!");
      10         getch ();
      11         endwin ();
      12 }
    
    • Сборка — с libncursesw: cc Hello.c -lncursesw -o Hello

  • Пример с окном
       1 #include <ncurses.h>
       2 
       3 #define DX 3
       4 
       5 void main() {
       6         WINDOW *win;
       7         int c = 0;
       8 
       9         initscr();
      10         noecho();
      11         cbreak();
      12         printw("Window:");
      13         refresh();
      14 
      15         win = newwin(LINES-2*DX, COLS-2*DX, DX, DX);
      16         keypad(win, TRUE);
      17         scrollok (win, TRUE);
      18         box(win, 0, 0); 
      19         wmove(win, 1, 0); 
      20         while((c = wgetch(win)) != 27) {
      21                 wprintw(win, "  Key: %d, Name: %s\n", c, keyname(c));
      22                 box(win, 0, 0); 
      23                 wrefresh(win);
      24         }
      25         endwin();
      26 }
    
    • Поэкспериментируйте: попробуйте закомментировать refresh(), вместо noecho() вызвать echo(), вместо cbreak()nocbreak(), а в keypad() и scrollok() указать FALSE. Что делают эти функции?

      • В виртуалке практикума есть man-страницы на всё))

    • Функция  wrefresh(win) в этом коде не нужна, потому что curses обновляет содержимое соответствующего окна перед тем, как вводить из него

Примитивный Makefile:

  • Make (очень коротко): цели и рецепты
  • Синтаксис: обязательный символ табуляции в рецептах

  • Задача — запуск команд пересборки, когда это надо
  • Цели могут быть, а могут не быть файлами
  • Пример:
       1 Window: Window.c
       2         cc Window.c -o Window -lncursesw
       3 
       4 clean:
       5         rm -f *~ *.o Window a.out
    
  • Использование:
       1 $ make
       2 cc Window.c -o Window -lncursesw
       3 $ ls
       4 a.out    Hello.c~  Makefile~  win.c   Window.c   WindowEx.c
       5 Hello.c  Makefile  simple.c   Window  Window.c~
       6 $ make
       7 make: «Window» не требует обновления.
       8 $ make clean
       9 rm -f *~ *.o Window a.out
      10 $ ls
      11 Hello.c  Makefile  simple.c  win.c  Window.c  WindowEx.c
      12 $ make
      13 cc Window.c -o Window -lncursesw
      14 $ ls
      15 Hello.c  Makefile  simple.c  win.c  Window  Window.c  WindowEx.c
      16 
    

Tab hell. Again.

  • Что такое символ табуляции
  • Как распознать табуляцию
    • hexdump -C файл

    • vim :set list

    • mcedit

  • Если ничего не помогает, в Makefile можно переопределить символ, с которого начинаются строчки с «рецептами» (но, к сожалению, не в пробел ☹)

    .RECIPEPREFIX=:
    Window: Window.c
    :       cc Window.c -o Window -lncursesw
    
    clean:
    :       rm -f *~ *.o Window a.out

Д/З

Предполагается, что на спецкурс вы записались

  1. Сделать в репозитории подкаталог, совпадающий с именем данной страницы (02_TerminalProject, и поместить в него решение следующей задачи.

  2. С помощью интернета и здравого смысла написать на ncurses программу Show.c, которая постранично просматривает файл (слишком длинные строки усекаются или переносятся — как вам удобнее).

    • Имя файла передавать параметром командной строки.
    • Файл должен показываться в окне, а в первой строке экрана должно содержаться его имя.
    • Весь файл допустимо хранить в памяти, например, одним куском или в виде списка строк.

    • При нажатии пробела файл прокручивается дальше (если есть такая возможность), при нажатии ESC программа завершается.

      • Имеет смысл очищать окно при помощи werase(), а потом всё заново на нём выводить.

    • Многобайтовую кодировку можно не поддерживать
  3. Сделать Makefile и добиться работоспособности make (обратите внимание на использование табуляций; понадобится на следующей лекции)

  4. Не забыть опубликовать решение в репозитории!
  5. (!) Дополнительно, для тех, кому стало интересно:

    • При нажатии стрелки вправо выводить строки файла, начиная со следующей колонки (так можно посмотреть урезанные длинные строки; начала строк при этом не видны). Стрелку влево обработать так же.
    • Реализовать обработку PgUp, PgDown и стрелок вверх/вниз — прокрутка на один экран вперёд/назад, на одну строку вперёд-назад, остальные клавиши игнорировать

    • … (далее везде)

Вот так как-то это выглядело два года назад :)

  • LecturesCMC/LinuxApplicationDevelopment2021/02_TerminalProject/o.gif

Так это выглядело год назад (я сделал поддержку wide characters и цвет)

  • LecturesCMC/LinuxApplicationDevelopment2021/02_TerminalProject/o.mp4

LecturesCMC/LinuxApplicationDevelopment2022/02_TerminalProject (последним исправлял пользователь FrBrGeorge 2022-10-01 20:33:22)