Podczas tworzenia aplikacji zacząłem się zastanawiać - jak zaprojektować argumenty wiersza poleceń?
Wiele programów używa formuł takich jak ten -argument value
lub /argument value
. Rozwiązanie, które przyszło mi do głowy, to argument:value
. Pomyślałem, że to dobrze, ponieważ bez białych spacji nie ma mowy o pomyleniu wartości i argumentów. Łatwo jest również podzielić ciąg na dwa na pierwszym od lewej :
postaci.
Moje pytania to:
- Czy popularna
-argument value
formuła jest lepsza niżargument:value
(bardziej czytelna, łatwiejsza do napisania, wolna od błędów, łatwiejsza do zrozumienia przez ekspertów programistów)? - Czy są jakieś powszechnie znane reguły, których powinienem przestrzegać podczas projektowania argumentów wiersza poleceń (inne niż jeśli działa, to jest OK)?
Poprosiłem o więcej szczegółów. Podam je. Myślę jednak, że nie powinny wpływać na odpowiedzi. Pytanie dotyczy ogólnie dobrych nawyków. Myślę, że wszystkie są takie same dla wszystkich rodzajów aplikacji.
Pracujemy nad aplikacją, która będzie używana w miejscach publicznych (dotykowe totemy, tabele). Aplikacje są pisane przy użyciu Qt Quick 5 (C ++, QML, JS). Urządzenia będą miały zainstalowany system Windows 8.1 / 10. Zapewniamy interfejs front-end do zarządzania urządzeniami. Jednak niektórzy zaawansowani administratorzy mogą chcieć samodzielnie skonfigurować aplikację. Nie jest to bardzo ważne ze strony biznesu, ale ponieważ zgadzam się z tym, co powiedział Kilian Foth , nie chcę, aby moja aplikacja była uciążliwa dla użytkownika. Nie znajdując w Internecie tego, czego chcę, zapytałem tutaj.
Do bardziej zaawansowanych użytkowników stosu wymiany: chciałem, aby to pytanie było ogólne. Może kwalifikuje się do wiki społeczności (nie wiem, czy istniejące pytanie można przekonwertować za pomocą odpowiedzi). Ponieważ chcę, aby to pytanie było niezależne od systemu operacyjnego i języka programowania, pojawiające się tutaj odpowiedzi mogą być cenną lekcją dla innych programistów.
źródło
ls -ltr
aby połączyć opcje-l
,-t
i-r
. Programy w stylu GNU zazwyczaj zezwalają również na opcje oparte na słowach z podwójnym myślnikiem--reverse
zamiast-r
. Istnieją inne popularne konwencje, takie jak-h
pokazywanie pomocy,--
sygnalizowanie końca opcji, określanie-
jako nazwy pliku umożliwiającej czytanie ze standardowego wejścia itp.-argument value
nie-argument:value
są powszechne. Powszechne są-a value
,-avalue
i--argument=value
.getopt(s)
), gdzie możesz.Odpowiedzi:
W systemach POSIX (np. Linux, MacOSX), przynajmniej w przypadku programów, które mogą być uruchamiane w terminalu powłoki (np. Większość z nich), zaleciłbym użycie konwencji kodowania GNU (które również zawierają listę popularnych nazw argumentów) i przyjrzenie się wytycznym narzędzi POSIX , nawet w przypadku oprogramowania zastrzeżonego:
zawsze obsługuj
--version
i--help
(nawet/bin/true
je akceptuje !!). Przeklinam autorów oprogramowania, którzy nie rozumieją--help
, nienawidzę ich (boprog --help
to pierwsze polecenie, które próbuję na nowym programie)! Często--help
można je skrócić jako-h
Poproś, aby
--help
lista zawierała wszystkie opcje (chyba że masz ich zbyt wiele ... w takim przypadku wypisz najczęściej używane i wyraźnie odnieś się do jakiejśman
strony lub adresu URL) i wartości domyślne opcji, a być może ważne (i specyficzne dla programu ) Zmienne środowiska. Pokaż te listy opcji w przypadku błędu argumentu opcji.zaakceptować
-a
krótki argumentu (jedna litera) i mieć jakiś odpowiednik--long-argument
, tak-a2
--long-argument=2
,--long-argument 2
; oczywiście możesz mieć (dla rzadko używanych opcji) jakąś--only-long-argument
nazwę; dla argumentów modalnych bez dodatkowych opcji-cf
jest zwykle traktowany jako-c -f
itp., więc twoja-argument:value
propozycja jest dziwna i nie polecam tego robić.użyj GLIBC getopt_long lub lepszego (np. argp_parse , w OCaml jest to
Arg
moduł , ...)często wykorzystują
-
do standardowego wejścia lub wyjścia (jeśli nie można tego zrobić, uchwyt/dev/stdin
i/dev/stdout
nawet na kilka systemów operacyjnych ich nie posiadające)naśladować zachowanie podobnych programów poprzez ponowne wykorzystanie większości konwencji opcji; w szczególności
-n
na sucho (à lamake
),-h
po pomoc,-v
za gadatliwość itp.użyj
--
jako separatora między opcjami i plikiem lub innymi argumentamijeśli twój program używa
isatty
do testowania niż stdin jest terminalem (w takim przypadku zachowuje się „interaktywnie”), zapewnij opcję wymuszenia trybu nieinteraktywnego, podobnie jeśli twój program ma interfejs GUI (i testygetenv("DISPLAY")
na pulpicie X11), ale może również być używane w partii lub wierszu poleceń.Niektóre programy (np.
gcc
) Akceptują pośrednie listy argumentów, co@somefile.txt
oznacza odczyt argumentów programu zsomefile.txt
; może to być przydatne, gdy twój program może zaakceptować bardzo dużą liczbę argumentów (więcej niż jądroARG_MAX
)BTW, możesz nawet dodać funkcje automatycznego uzupełniania dla swojego programu i zwykłe powłoki (jak
bash
lubzsh
)Niektóre stare polecenia uniksowe (np.
dd
Lub nawetsed
) mają dziwne argumenty poleceń dla historycznej zgodności. Radziłbym nie podążać za ich złymi nawykami (chyba że robisz jakiś lepszy wariant).Jeśli oprogramowanie jest seria programów związanych z wiersza polecenia, czerpać inspirację z git (co na pewno użyć jako narzędzie rozwoju), która akceptuje
git help
igit --help
i mają wielegit
subcommand
igit
subcommand
--help
W rzadkich przypadkach możesz także użyć
argv[0]
(używając dowiązań symbolicznych w swoim programie), np.bash
Wywołać, ponieważrbash
ma inne zachowanie ( ograniczona powłoka). Ale zwykle nie polecam tego robić; może mieć sens, jeśli twój program może być używany jako interpreter skryptów za pomocą shebang, tj.#!
w pierwszej linii interpretowanej przez execve (2) . Jeśli wykonujesz takie sztuczki, pamiętaj o ich udokumentowaniu, w tym w--help
wiadomościach.Pamiętaj, że na POSIX powłoka jest globbing argumenty ( zanim uruchomiony program!), Więc uniknąć konieczności znaków (jak
*
lub$
czy~
) w opcji, które musiałyby być powłoki uciekł.W niektórych przypadkach możesz wbudować interpreter taki jak GNU Guile lub Lua w swoim oprogramowaniu (unikaj wymyślania własnego języka skryptowego pełnego Turinga, jeśli nie jesteś ekspertem w językach programowania). Ma to głębokie konsekwencje dla projektu twojego oprogramowania (należy o tym pomyśleć wcześnie!). Powinieneś wtedy łatwo przekazać skryptowi lub wyrażeniu temu tłumaczowi. Jeśli zastosujesz to interesujące podejście, ostrożnie zaprojektuj swoje oprogramowanie i jego interpretowane prymitywy; możesz mieć dziwnego użytkownika kodującego duże skrypty dla swojej rzeczy.
W innych przypadkach możesz pozwolić zaawansowanym użytkownikom na załadowanie wtyczki do twojego oprogramowania (przy użyciu technik dynamicznego ładowania à la
dlopen
&dlsym
). Ponownie, jest to bardzo ważna decyzja projektowa (więc ostrożnie zdefiniuj i udokumentuj interfejs wtyczki) i musisz zdefiniować konwencję, aby przekazywać opcje programu do tych wtyczek.Jeśli twoje oprogramowanie jest skomplikowane, pozwól mu akceptować niektóre pliki konfiguracyjne (oprócz lub zastępowanie argumentów programu) i prawdopodobnie masz jakiś sposób na przetestowanie (lub po prostu parsowanie) tych plików konfiguracyjnych bez uruchamiania całego kodu. Na przykład agent przesyłania poczty (taki jak Exim lub Postfix) jest dość złożony i przydatna jest możliwość „półsuchego” jego uruchomienia (np. Obserwowanie, jak obsługuje określony adres e-mail bez faktycznego wysyłania wiadomości e-mail).
Zauważ, że
/option
jest to Windows lub VMS. Byłoby to szalone w systemach POSIX (ponieważ hierarchia plików używa/
jako separatora katalogów i ponieważ powłoka wykonuje globowanie). Cała moja odpowiedź dotyczy głównie Linuksa (i POSIX).PS Jeśli to możliwe, uczyń swój program wolnym oprogramowaniem , otrzymasz ulepszenia od niektórych użytkowników i programistów (a dodanie nowej opcji programu jest często jedną z najłatwiejszych rzeczy do dodania do istniejącego bezpłatnego oprogramowania). Ponadto twoje pytanie zależy w dużej mierze od zamierzonej publiczności : gra dla nastolatków lub przeglądarka dla babci prawdopodobnie nie potrzebuje tego samego rodzaju i ilości opcji niż kompilator lub inspektor sieci dla sysadminów centrum danych lub oprogramowanie CAD dla mikroprocesora architekci lub projektanci mostów. Inżynier zaznajomiony z programowaniem i skryptami prawdopodobnie lubi dużo więcej możliwości dostrajania niż twoja babcia i prawdopodobnie może chcieć móc uruchomić twoją aplikację bez X11 (być może w
crontab
pracy).źródło
git
jest lepszym przykładem. Nie polecam nawet patrząc nacvs
w 2016 rokudd -h
.--help
z reguły obsługują, ale często nie rozpoznają,-h
co jest denerwujące. Zazwyczaj piszę -h, gdy zapominam o opcji programu, denerwujące jest ponowne wpisywanie polecenia dłuższą opcją--help
. W końcu napisałem -h, ponieważ coś zapomniałem. Dlaczego użytkownik powinien pamiętać, które programy wymagają „--help”, a które programy wymagają „-h”, aby wyświetlić ekran pomocy? Wystarczy dołączyć opcję zarówno -h, jak i --help.Zaletą jest fakt, że konwencja formatu danych jest popularna .
Łatwo zauważyć, że użycie = lub: lub nawet '' jako separatora to trywialne różnice, które można bez trudu przekonwertować na komputer. Jaki byłby wielki wysiłek jest dla człowieka, aby pamiętać „Teraz widać, zrobił to rzadko używane rzeczy z programu ograniczają
:
lub z=
? Hmmm ...”Innymi słowy, na miłość boską, nie odchodź od ekstremalnie zakorzenionych konwencji bez ważnego powodu. Ludzie zapamiętają twój program jako „ten z dziwną i irytującą składnią cmdline” zamiast „ten, który uratował mój esej z college'u”.
źródło
dd
używakey=value
składni. Powodem tej decyzji projektowej jest to, że to narzędzie (pseudonim: d ata d estroyer) może powodować duże szkody, gdy jest używane nieprawidłowo. Zmuszając użytkownika do porzucenia zwykłego nawyku, zmuszają go do dokładniejszego zastanowienia się nad tym, co robią.dd
? Uważam, że został po prostu zakodowany w czasie (lata 70.?), Kiedy ARG_MAX jądra był mały, powłoki nie miały autouzupełniania i--long-arguments
nie istniały. Od tego czasu lepiejdd
pozostawał kompatybilny wsteczdd
pochodzi z innego systemu operacyjnego (niż UNIX) - języka skryptowego (JCL) w systemie operacyjnym IBM / 360 - w którym konwencje były różne, zanim zostały przeniesione mniej lub bardziej niezmienione na system UNIX - częściowo dlatego, że osoby, które prawdopodobnie będą go używać, znały go z poprzedni system.W kategoriach laika
Jeśli wejdziesz między wrony, musisz krakać jak i one.
-p value
lub--parameter value
. Linux ma narzędzia do łatwego analizowania takich parametrów i flag.Zwykle robię coś takiego:
Jeśli aplikacja CLI jest przeznaczona dla systemu Windows, użyj jej
/flag
i/flag:value
konwencji.Jednak niektóre aplikacje, takie jak Oracle, nie korzystają z nich. Użyj narzędzi Oracle
PARAMETER=VALUE
.Jedną z rzeczy, które lubię robić, jest oprócz akceptowania parametrów w wierszu poleceń, zapewnienie opcji używania pliku parfile , który jest plikiem pary klucz-wartość, aby uniknąć długich łańcuchów parametrów. W tym celu należy podać dodatkowy
--parfile mifile.par
parametr. Oczywiście, jeśli--parfile
jest używany, wszystkie inne parametry są odrzucane na korzyść tego, co znajduje się w pliku.Dodatkową sugestią jest zezwolenie na użycie niektórych niestandardowych zmiennych środowiskowych , na przykład ustawienie zmiennej środowiskowej
MYAPP_WRKSPACE=/tmp
sprawi, że zbędne będzie zawsze ustawianie--wrkspace /tmp
.TAB
a następnie powłoka wykona je za nich.źródło
gcc
) Obsługuje@mifile.par
takie same--parfile mifile.par
sugestie.fooCmd -opt1 -opt2 $(cat more_options.opts)
. Dlatego oczekiwałbym, że opcja „parametr pliku konfiguracyjnego”, jeśli zostanie podana, powinna zasadniczo działać w ten sam sposób.Jedna rzecz, która jeszcze się nie pojawiła:
Spróbuj zaprojektować oprogramowanie od argumentów wiersza poleceń w górę. Znaczenie:
Przed zaprojektowaniem funkcjonalności należy zaprojektować interfejs użytkownika.
Pozwoli to na wcześniejsze przeanalizowanie skrzynek i typowych skrzynek. Oczywiście nadal będziesz abstrakcjonował elementy zewnętrzne i wewnętrzne, ale da to znacznie lepszy wynik niż tylko napisanie całego kodu, a następnie zatrzaśnięcie w nim CLI.
Ponadto sprawdź docopt ( http://docopt.org/ ).
docopt jest świetną pomocą w wielu językach, szczególnie w pythonie, gdzie masz poważne ograniczenia parserów argumentów niekorzystnych dla użytkownika, takich jak argparse, wciąż uważanych za „OK”. Zamiast parserów i akapitów oraz dyktandów warunkowych, wystarczy zdefiniować pomoc dotyczącą składni, a ona zajmie się resztą.
źródło
argparse
programistą, interfejsem użytkownika ani przyjazny dla użytkownika.Kilka cennych komentarzy zostało już podanych (@Florian, Basile), ale dodam ... OP mówi:
Ale także uwagi:
Musisz wziąć pod uwagę odbiorców docelowych - zaawansowanych administratorów . Na jakiej platformie normalnie działają - Win / Unix / Mac? A na jakiej platformie działa Twoja aplikacja? Postępuj zgodnie z konwencjami CLI, które zostały już ustanowione dla tej platformy. Czy twoi „zaawansowani” administratorzy chcą / potrzebują narzędzia opartego na GUI?
Chcesz, aby interfejs był spójny wewnętrznie i z innymi narzędziami administracyjnymi. Nie chcę się zatrzymywać i myślę, że to
cmd -p <arg>
lubcmd -p:<arg>
lubcmd /p <arg>
. Czy potrzebuję cytatów, bo jest miejsce? Czy mogęcmd -p <val1> <val2>
lubcmd -p <val1> -p <val2>
dla wielu celów? Czy są one specyficzne dla zamówienia? Przeciążalny? Czycmd -p2 <arg> -p1 <arg>
też działa? Czyls -l -r -t dir1 dir2
==ls -trl dir1 dir2
?W przypadku narzędzi administracyjnych dla systemu Unix zawsze pamiętałem o wskazówkach dostarczonych przez Heinera Shelldorado , a także o innych wspomnianych źródłach.
Równie ważne jak projektowanie interfejsu CLI jest upewnienie się, że aplikacja jest zaprojektowana do pracy z argumentami wiersza poleceń takimi samymi jak z GUI - tj .: brak logiki biznesowej w GUI lub użycie wspólnej komendy wywoływanej zarówno z GUI, jak i CLI.
Większość narzędzi administracyjnych opartych na systemie UNIX jest faktycznie projektowanych jako narzędzia wiersza poleceń, a udostępniony interfejs GUI po prostu ułatwia „wypełnianie” opcji wiersza poleceń. Takie podejście pozwala na automatyzację, korzystanie z plików odpowiedzi itp. Oraz zarządzanie zestawem głośnomówiącym (mniej pracy dla mnie!)
Jako klasyczny zestaw narzędzi używany w / to podejście to Tcl / Tk . Nie sugeruję zmiany narzędzi; wystarczy rozważyć podejście projektowe, pisząc najpierw aplikację administracyjną opartą na graficznym interfejsie użytkownika jako narzędzie wiersza polecenia; następnie dla wygody nałóż GUI na wierzch. W pewnym momencie prawdopodobnie odkryjesz, że GUI jest uciążliwe (i podatne na błędy), jeśli musisz wykonać wiele konfiguracji i ponownie wprowadzać ogólnie te same opcje w kółko i będziesz szukać automatycznego rozwiązania.
Pamiętaj, że administrator prawdopodobnie i tak musi wpisać poprawne wartości w odpowiednich polach, więc ile wysiłku i tak odczuwasz za pomocą graficznego interfejsu użytkownika?
źródło