qmenu는 터미널에서 문자로 된 메뉴를 띄우는 프로그램이다. 메뉴의 생김새와 각 항목이 실행할 명령은 `.mnu` 파일에 적는다. 우분투 22.04 저장소의 패키지는 5.0.2이고, 개발 저장소에 있다. 이 글은 그 버전을 실행해 확인한 내용이다.

Bash
sudo apt install qmenu
qmenu
man qmenu

인자가 없으면 사용법만 출력하고 끝난다. 메뉴 파일을 줘야 화면이 열린다. ncurses로 화면을 잡으므로 터미널에서 실행한다. 파이프에 붙여 돌리는 용도가 아니다.

시작할 때 `uuname -l`을 한 번 호출한다. 우분투에는 이 명령이 없어서 `uuname: command not found`가 한 줄 보일 수 있다. 메뉴가 실패한 것은 아니다.

작업 디렉터리

qmenu는 설정, 도움말, 입력창, 로그를 현재 디렉터리에서 찾는다. 메뉴를 둘 디렉터리로 이동한 뒤 실행한다.

Bash
mkdir -p ~/qmenu
cd ~/qmenu
qmenu -init
qmenu -model

`-init`은 `qmenu.cfg`를 만든다. 이미 있으면 그 파일을 다시 쓴다. `-model`은 `model.mnu`를 만든다. 예제 메뉴는 패키지에 들어 있다.

Bash
ls /usr/share/qmenu

`m_main.mnu`가 본 메뉴, `m_submenu.mnu`가 하위 메뉴, `m_env.mnu`가 환경 변수를 화면에 보여주는 예다.

메뉴 파일의 세 구역

메뉴 파일은 화면, 항목, 옵션 순이다. 화면과 항목 사이는 `$$`, 항목과 옵션 사이는 `%%`다.

Bash
화면
$$
항목
%%
옵션

`$$`가 없으면 `File without $$`라고 하고 메뉴를 열지 못한다. 화면은 24줄을 넘기면 안 된다. 한 줄은 80칸 안쪽으로 두는 것이 안전하다. 선택 항목은 한 메뉴에 40개까지다.

화면 그리기

`^`와 `^` 사이가 선택할 수 있는 항목이다. 첫 글자가 단축키다. 프로그램이 그 글자를 대문자로 바꾼다.

Bash
            ^1.   Show date                                          ^
            ^Q.   Quit                                               ^

화살표로 옮기고 Enter로 실행한다. 단축키를 눌러도 그 항목으로 간다.

항목이 아닌 글자 중 일부는 선으로 바뀐다. `-`는 가로선, `|`는 세로선이다. 문장 안의 빼기 기호까지 선이 되므로, 제목에는 하이픈을 쓰지 않는다. `@`는 그 뒤 글자의 반전을 켜고, 다음 `@`에서 끈다.

`&` 한 글자는 커서가 앉는 자리다. 예제 메뉴의 `Selezione..: [ &]`가 그 위치다.

변수는 정렬 글자와 이름이다. 소문자는 보통 글자, 대문자는 반전이다.

- `L`과 `l`은 그 자리에 왼쪽 정렬이다. - `C`와 `c`는 화면 가운데다. - `R`과 `r`은 오른쪽 정렬이다. - `E`와 `e`는 오른쪽 끝에 붙인다. - `B`와 `b`는 왼쪽 끝이다.

이름은 다음 여섯 가지다.

- `TIME`은 지금 시각이다. 이 변수가 있어야 시계가 갱신된다. - `TITLE`은 옵션 구역의 `TITOLO=` 값이다. 38자까지 쓴다. - `MSG`는 지금 선택된 항목의 설명 줄이다. - `MENUNAME`은 메뉴 파일 이름이다. - `INFOTERM`은 시스템 이름, 로그인 이름, 터미널, `LPDEST`를 한 줄로 보여 준다. - `MNUTRACE`는 메뉴를 따라온 경로다.

환경 변수는 `${PATH}`처럼 적는다. 중괄호가 없으면 확장되지 않는다. 값이 없으면 빈 칸이다.

화면 예는 이렇다.

Bash
운영 메뉴                                                      E[TIME]
--------------------------------------------------------------------------------
                                   C[TITLE]
            ^1.   Show date                                          ^
            ^Q.   Quit                                               ^
             선택: [ &]
                               c[MSG]
--------------------------------------------------------------------------------
 L[INFOTERM]                                                      E[MENUNAME]

`RVS_ROW=0,22`는 0번 줄과 22번 줄을 반전한다. 번호는 0부터다.

`GRAPH`는 `qmenu.cfg`의 선 모양이다. 0은 `+`, `-`, `|` 같은 일반 문자, 1은 터미널 대체 문자, 2는 ncurses 선 문자다. `-init`이 만드는 값은 2다.

항목 네 줄

`$$` 다음의 각 항목은 네 줄이다. 한 줄이라도 빠지면 그 아래가 한 칸씩 밀리고, `MANCA %% PRIMA DELL' INDICE VOCE` 경고가 난다.

1. `%`와 단축키. 화면 항목의 첫 글자와 같아야 한다. 2. 실행할 내용. 3. 설명. `MSG` 자리에 나온다. 설명이 없어도 빈 줄을 남긴다. 4. 암호. 없으면 빈 줄을 남긴다. 앞 11자만 저장되고, 메뉴 파일에 그대로 적힌다.

항목이 끝난 뒤의 `%%`는 암호 줄과 따로다. 암호 줄을 비울 거면 `%%` 위에 빈 줄이 하나 더 있어야 한다.

Bash
$$
%1
date; read a
오늘 날짜를 보여 준다

%Q
fine


%%

`%1`의 마지막 빈 줄이 암호 자리다. `%Q`는 설명이 없으므로 명령 다음에 빈 줄, 암호가 없으므로 그 다음에 빈 줄, 그 다음에 `%%`다.

실행 내용은 네 가지다.

셸 명령은 `sh -c`로 실행된다. 실행에 넘기는 버퍼가 60바이트라서 59자를 넘는 명령은 잘린다. 긴 작업은 스크립트로 만들고 메뉴에는 그 경로만 적는다. 명령이 출력한 내용은 메뉴가 바로 다시 그려지면서 사라진다. 읽게 하려면 끝에 `read a`를 붙인다.

Bash
date; read a

배포 예제의 `pause`는 qmenu 명령이 아니다. 우분투에는 없는 셸 명령인 경우가 많다.

`$`로 시작하면 하위 메뉴다. 확장자 `.mnu`는 붙이지 않는다. `$reports`는 `reports.mnu`를 연다. 파일은 `MNU_PATH` 아래이거나, 그 값이 비어 있으면 현재 디렉터리다.

예약어는 이렇다.

- `return`은 이전 메뉴다. 처음 메뉴에서 실행하면 qmenu가 끝난다. - `returnmain`은 처음 연 메뉴로 돌아간다. - `fine`은 `Confermi ?`를 묻고, `Si`를 골라야 끝난다. `No`가 기본이다. - `exit`는 묻지 않고 끝난다. - `config`는 지금 설정값을 보여 준다. F4로 닫는다. - `pruser`와 `prsuper`는 `qmenu.cfg`의 프린터 목록을 고르게 하고, 고른 이름을 `LPDEST`에 넣는다.

`*`로 시작하면 입력창이다. `*ask(echo)`는 `qmenu.frm`에서 `[ask]` 구역을 열고, 괄호 안을 실행할 명령으로 쓴다. 입력칸은 `<`와 `>` 사이다. 사용자가 넣은 값은 명령 뒤에 따옴표 인자로 붙는다. F4는 입력창을 닫는다.

Bash
[ask]
 호스트: <                >

암호 줄에 글자가 있으면 그 항목을 실행하기 전에 묻는다. 파일에 평문으로 있으므로, 메뉴 파일을 읽을 수 있는 사람과 암호를 공유하는 것과 같다.

옵션 구역

`%%` 아래에 메뉴마다 다음을 둔다. `#`으로 시작하면 그 줄은 무시된다.

Bash
TITOLO=운영 메뉴
RVS_ROW=0,22
NOKEYDISP
SHELL=sh
EDITOR=vi
FZ1=config
ET1=Config
PW1=

`NOKEYDISP`는 맨 아래 기능키 글자를 끈다. `KEYDISP`는 켠다. 기본은 켜짐이다.

`FZ1`부터 `FZ10`은 F1부터 F10에 연결할 명령이다. 항목과 같은 예약어와 셸 명령을 쓸 수 있다. `ET1`부터 `ET10`은 그 키 아래에 보여줄 짧은 글자다. `PW1`부터 `PW10`은 그 키의 암호다.

`SHELL`과 `EDITOR`는 항목 명령을 실행하는 셸이 아니다. 항목 명령은 항상 `sh -c`다. 이 두 값은 `#`으로 여는 관리 메뉴에서 셸과 편집기를 고를 때 쓴다.

설정 파일

`qmenu.cfg`가 없어도 메뉴는 열린다. 없으면 무작업 제한 900초와 로그 크기 50000이 기본이다. `-init`이 만드는 내용은 이렇다.

Bash
[Option]
MNU_TIM=1000
LOGFILE_DIM=50000
GRAPH=2
PASSWD_MODE=OFF
MENU_SUPER_PASSWD=MENU
BKS_EXIT=0

[FileName]
HLP_FILENAME=qmenu.hlp

[Printers]
PRSUPER=printer0,printer1
PRUSER=printer0,printer1

[Path]
#MNU_PATH=${HOME}/

[PassWord]
#PAROLA_CHIAVE=NOMINATIVO

`MNU_TIM`은 아무 키도 누르지 않을 때 프로그램을 끝낼 때까지의 초다. 0이면 그 제한이 없다. `-init`의 1000은 1000초다.

`LOGFILE_DIM`을 넘으면 `qmenu.log`를 `qmenu.log.bak`으로 옮기고 새로 쓴다. 로그에는 로그인 이름, 터미널, 시각, 메뉴 파일, 실행한 명령이 남는다.

`BKS_EXIT`가 0이면 처음 메뉴에서 뒤로 가려 할 때 경고만 하고 남는다. 0이 아니면 그 동작으로 종료한다. 터미널이 백스페이스를 DEL로 보내면 이 키가 먹지 않을 수 있다. 하위 메뉴에는 `return` 항목을 두는 편이 확실하다.

`MNU_PATH`는 메뉴 파일 앞에 붙는 경로다. `${HOME}`처럼 환경 변수를 쓸 수 있다. 값을 주면 `qmenu main.mnu`의 `main.mnu`도 그 경로 아래에서 찾는다.

`PASSWD_MODE=ON`이면 시작하자마자 암호를 묻는다. 입력한 문자열이 `qmenu.cfg` 어느 줄이든 `=` 왼쪽과 같아야 한다. 오른쪽 값은 로그에 사용자 이름으로 남는다. `[PassWord]`에 `입장암호=홍길동`처럼 두고, 시작할 때 `입장암호`를 입력하는 방식이 맞다.

`MENU_SUPER_PASSWD`가 있으면 `#` 키가 관리 메뉴를 연다. 먼저 이 암호를 묻는다. `-init`이 넣어 둔 값은 `MENU`다. 쓰려면 바꾼다. 관리 메뉴에서는 셸, 지금 메뉴 편집, 프린터 선택, 설정 보기, 로그 보기, `qmenu.cfg` 편집, `qmenu.frm` 편집, 도움말 파일 편집, 프로그램 정보를 고른다. 정보 창과 설정 창은 F4로 닫는다.

`PRUSER`와 `PRSUPER`는 쉼표로 프린터 이름을 나열한다. 메뉴 명령 `pruser`, `prsuper`가 이 목록을 보여 준다.

도움말

Tab은 `HLP_FILENAME` 파일을 연다. 기본 이름은 `qmenu.hlp`다. 구역 제목은 메뉴 파일 이름, 콜론, 항목 앞 두 글자다. `1.`으로 시작하는 항목은 `1.`이다.

Bash
[main.mnu:1.]
date 명령으로 오늘 날짜를 출력한다.
Enter를 누르면 메뉴로 돌아온다.

[main.mnu:Q.]
메뉴를 끝낸다.

다음 `[`가 나오기 전까지가 그 항목의 도움말이다. 파일이 없어도 메뉴는 열린다. Tab만 도움말을 찾지 못한다.

실행

현재 디렉터리에 `qmenu.cfg`와 `main.mnu`를 두고 실행한다.

Bash
cd ~/qmenu
qmenu main.mnu

세 번째 인자는 관리 메뉴가 쓸 편집기다. 메뉴 파일에 `EDITOR=`가 있으면 그 값이 이긴다.

Bash
qmenu main.mnu vim

메뉴가 바로 닫히거나 경고만 나오면 항목 네 줄과 `%%` 위치를 먼저 본다. 그다음 `MNU_PATH`가 파일을 다른 디렉터리에서 찾고 있지 않은지 확인한다.