Saat mengembangkan aplikasi saya mulai bertanya-tanya - Bagaimana saya harus merancang argumen baris perintah?
Banyak program menggunakan rumus seperti ini -argument value
atau /argument value
. Solusi yang muncul di benak saya adalah argument:value
. Saya pikir itu baik karena tanpa spasi putih tidak ada cara yang bisa mengacaukan nilai dan argumen. Juga mudah untuk membagi string menjadi dua pada karakter pertama dari :
karakter kiri .
Pertanyaan saya adalah:
- Apakah
-argument value
formula populer lebih baik daripadaargument:value
(lebih mudah dibaca, lebih mudah ditulis, bebas bug, lebih mudah dipahami oleh pengembang ahli)? - Apakah ada beberapa aturan umum yang harus saya ikuti saat mendesain argumen baris perintah (selain jika berfungsi, itu OK)?
Diminta beberapa detail lagi saya akan berikan. Namun saya pikir mereka seharusnya tidak mempengaruhi jawaban. Pertanyaannya adalah tentang kebiasaan yang baik secara umum. Saya pikir mereka semua sama untuk semua jenis aplikasi.
Kami sedang mengerjakan aplikasi yang akan digunakan di tempat umum (sentuh totem, tabel). Aplikasi ditulis menggunakan Qt Quick 5 (C ++, QML, JS). Perangkat akan menginstal Windows 8.1 / 10. Kami akan menyediakan antarmuka ujung depan untuk mengelola perangkat. Namun beberapa administrator tingkat lanjut mungkin ingin mengkonfigurasi aplikasi sendiri. Ini tidak terlalu penting dari sisi bisnis tetapi karena saya setuju dengan apa yang dikatakan Kilian Foth , saya tidak ingin aplikasi saya menjadi masalah bagi pengguna. Tidak menemukan di internet apa yang saya inginkan, saya bertanya di sini.
Untuk pengguna Stack Exchange yang lebih maju: Saya ingin pertanyaan ini bersifat umum. Mungkin itu memenuhi syarat untuk komunitas wiki (saya tidak tahu apakah pertanyaan yang ada dapat dikonversi dengan jawaban). Karena saya ingin pertanyaan ini menjadi sistem operasi dan bahasa pemrograman independen jawaban yang muncul di sini bisa menjadi pelajaran berharga bagi pengembang lain.
sumber
ls -ltr
untuk menggabungkan opsi-l
,-t
dan-r
. Program gaya GNU juga biasanya memungkinkan opsi berbasis kata dengan tanda hubung ganda--reverse
sebagai ganti-r
. Ada konvensi populer lainnya seperti-h
menunjukkan bantuan,--
memberi tanda pada akhir opsi, menetapkan-
sebagai nama file untuk memungkinkan membaca dari stdin, dll.-argument value
tidak-argument:value
biasa. Umum adalah-a value
,-avalue
, dan--argument=value
.getopt(s)
) di mana Anda bisa.Jawaban:
Pada sistem POSIX (mis. Linux, MacOSX), setidaknya untuk program yang mungkin dimulai pada terminal shell (mis. Sebagian besar dari mereka), saya akan merekomendasikan menggunakan konvensi pengkodean GNU (yang juga mencantumkan nama argumen umum) dan melihat ke dalam pedoman utilitas POSIX , bahkan untuk perangkat lunak berpemilik:
selalu menangani
--version
dan--help
(bahkan/bin/true
menerimanya !!). Saya mengutuk penulis perangkat lunak tidak mengerti--help
, saya benci mereka (karenaprog --help
adalah perintah pertama yang saya coba pada program baru)! Seringkali--help
dapat disingkat-h
Minta
--help
pesan mencantumkan semua opsi (kecuali Anda memiliki terlalu banyak di antaranya ... dalam hal ini cantumkan yang paling umum dan secara eksplisit merujuk ke beberapaman
halaman atau beberapa URL) dan nilai default opsi, dan mungkin penting (dan spesifik program) ) variabel lingkungan. Tampilkan daftar opsi ini pada kesalahan argumen opsi.menerima
-a
argumen singkat (huruf) dan memiliki beberapa setara--long-argument
, jadi-a2
--long-argument=2
,--long-argument 2
; tentu saja Anda dapat memiliki (untuk opsi yang jarang digunakan) beberapa--only-long-argument
nama; untuk argumen modal tanpa opsi tambahan-cf
umumnya ditangani sebagai-c -f
, dll. jadi-argument:value
proposal Anda aneh, dan saya tidak menyarankan melakukan itu.gunakan GLIBC getopt_long atau lebih baik (mis. argp_parse , di OCaml
Arg
modulnya , ...)sering digunakan
-
untuk input atau output standar (jika Anda tidak dapat melakukannya, pegang/dev/stdin
&/dev/stdout
bahkan pada beberapa sistem operasi yang tidak memilikinya)meniru perilaku program serupa dengan menggunakan kembali sebagian besar konvensi opsi mereka; khususnya
-n
untuk dry run (à lamake
),-h
untuk bantuan,-v
untuk kata kerja, dll ...gunakan
--
sebagai pemisah antara opsi & file atau argumen lainnyajika program Anda menggunakan
isatty
untuk menguji daripada stdin adalah terminal (dan berperilaku "interaktif" dalam kasus itu), berikan opsi untuk memaksakan mode non-interaktif, juga jika program Anda memiliki antarmuka GUI (dan tesgetenv("DISPLAY")
pada desktop X11) tetapi juga bisa digunakan dalam batch atau command line.Beberapa program (misalnya
gcc
) menerima daftar argumen tidak langsung, demikian@somefile.txt
juga artinya membaca argumen program darisomefile.txt
; ini bisa berguna ketika program Anda mungkin menerima banyak argumen (lebih banyak dari kernel AndaARG_MAX
)BTW, Anda bahkan dapat menambahkan beberapa fasilitas lengkapi-otomatis untuk program Anda dan shell yang biasa (seperti
bash
atauzsh
)Beberapa perintah Unix lama (misalnya
dd
, atau bahkansed
) memiliki argumen perintah aneh untuk kompatibilitas historis. Saya akan merekomendasikan untuk tidak mengikuti kebiasaan buruk mereka (kecuali jika Anda membuat varian yang lebih baik dari mereka).Jika perangkat lunak Anda adalah serangkaian program baris perintah terkait, mengambil inspirasi dari git (yang pasti Anda gunakan sebagai alat pembangunan), yang menerima
git help
dangit --help
dan memiliki banyakgit
subcommand
dangit
subcommand
--help
Dalam kasus yang jarang terjadi, Anda mungkin juga menggunakan
argv[0]
(dengan menggunakan symlink pada program Anda), misalnyabash
dipanggil karenarbash
memiliki perilaku yang berbeda ( shell terbatas ). Tetapi saya biasanya tidak merekomendasikan melakukan itu; mungkin masuk akal jika program Anda dapat digunakan sebagai penerjemah skrip menggunakan shebang yaitu#!
pada baris pertama yang ditafsirkan oleh exec (2) . Jika Anda melakukan trik semacam itu, pastikan untuk mendokumentasikannya, termasuk dalam--help
pesan.Ingat bahwa pada POSIX shell adalah globbing argumen ( sebelum menjalankan program Anda!), Jadi hindari meminta karakter (seperti
*
atau$
atau~
) dalam opsi yang perlu shell-melarikan diri.Dalam beberapa kasus, Anda dapat menyematkan juru bahasa seperti GNU Chile atau Lua di perangkat lunak Anda (hindari menciptakan bahasa skrip lengkap Turing sendiri jika Anda tidak ahli dalam bahasa pemrograman). Ini memiliki konsekuensi mendalam pada desain perangkat lunak Anda (jadi harus dipikirkan sejak dini!). Anda kemudian dapat dengan mudah memberikan beberapa skrip atau ekspresi kepada penerjemah itu. Jika Anda mengambil pendekatan yang menarik, rancang perangkat lunak Anda dan primitifnya yang ditafsirkan dengan hati-hati; Anda bisa memiliki beberapa pengguna aneh yang mengkodekan skrip besar untuk hal Anda.
Dalam kasus lain, Anda mungkin ingin membiarkan pengguna tingkat lanjut memuat plugin mereka ke perangkat lunak Anda (menggunakan teknik pemuatan dinamis à la
dlopen
&dlsym
). Sekali lagi, ini adalah keputusan desain yang sangat penting (jadi tentukan dan dokumentasikan antarmuka plugin dengan hati-hati), dan Anda harus menentukan konvensi untuk meneruskan opsi program ke plugin ini.Jika perangkat lunak Anda adalah hal yang rumit, buat ia menerima beberapa file konfigurasi (sebagai tambahan atau penggantian argumen program) dan mungkin memiliki beberapa cara untuk menguji (atau hanya menguraikan) file-file konfigurasi ini tanpa menjalankan semua kode. Sebagai contoh, agen transfer surat (seperti Exim atau Postfix) cukup kompleks, dan berguna untuk dapat "setengah kering" menjalankannya (misalnya mengamati bagaimana ia menangani beberapa alamat email yang diberikan tanpa benar-benar mengirim email).
Perhatikan bahwa
/option
ini adalah hal Windows atau VMS. Ini akan menjadi gila pada sistem POSIX (karena hirarki file digunakan/
sebagai pemisah direktori, dan karena shell melakukan globbing). Semua jawaban saya sebagian besar untuk Linux (dan POSIX).PS Jika memungkinkan, jadikan program Anda perangkat lunak gratis , Anda akan mendapatkan peningkatan dari beberapa pengguna & pengembang (dan menambahkan opsi program baru sering kali merupakan salah satu hal termudah untuk ditambahkan ke perangkat lunak gratis yang ada). Juga, pertanyaan Anda tergantung banyak pada penonton dimaksudkan : permainan untuk remaja atau browser untuk nenek mungkin tidak perlu jenis yang sama dan jumlah pilihan dari compiler, atau seorang inspektur jaringan untuk sysadmin datacenter, atau perangkat lunak CAD untuk mikroprosesor arsitek atau desainer jembatan. Seorang insinyur yang akrab dengan pemrograman & skrip mungkin lebih suka memiliki banyak opsi merdu dari nenek Anda, dan mungkin ingin menjalankan aplikasi Anda tanpa X11 (mungkin dalam
crontab
pekerjaan).sumber
git
merupakan contoh yang lebih baik. Saya tidak akan merekomendasikan bahkan melihat kecvs
dalam 2016.dd -h
.--help
sebagai aturan tetapi seringkali tidak mengenali-h
mana yang menjengkelkan. Saya biasanya mengetik -h ketika saya lupa opsi untuk suatu program, itu mengganggu harus mengetik ulang perintah dengan opsi yang lebih panjang--help
. Lagi pula, saya mengetik -h karena saya lupa sesuatu. Mengapa pengguna harus mengingat program mana yang membutuhkan '--help' dan program mana yang membutuhkan '-h' untuk menampilkan layar bantuan? Cukup sertakan opsi untuk -h dan --help.Fakta bahwa konvensi format data populer adalah keuntungannya.
Anda dapat dengan mudah melihat bahwa menggunakan = atau: atau bahkan '' sebagai pemisah adalah perbedaan sepele yang dapat dikonversi satu sama lain oleh komputer dengan sedikit usaha. Apa yang akan menjadi upaya besar bagi manusia untuk mengingat "Sekarang lihat, apakah program yang jarang digunakan ini membatasi hal-hal dengan
:
atau dengan=
? Hmmm ..."Dengan kata lain, untuk cinta tuhan, jangan menyimpang dari konvensi yang sangat mengakar tanpa alasan kuat. Orang akan mengingat program Anda sebagai "yang dengan sintaks cmdline yang aneh dan menjengkelkan" alih-alih "yang menyelamatkan esai kuliah saya".
sumber
dd
menggunakankey=value
sintaksis. Alasan untuk keputusan desain ini adalah bahwa alat ini (nama panggilan: d ata d estroyer) dapat menyebabkan banyak kerusakan ketika digunakan secara tidak benar. Dengan memaksa pengguna untuk meninggalkan kebiasaan mereka yang biasa, mereka memaksa pengguna untuk berpikir lebih dekat tentang apa yang mereka lakukan.dd
? Saya percaya bahwa itu hanya diberi kode pada suatu waktu (1970-an?) Ketika ARG_MAX kernel kecil, shell tidak memiliki pelengkapan otomatis, dan--long-arguments
tidak ada. Sejak itu lebih baikdd
tetap kompatibel ke belakangdd
berasal dari OS lain (dari UNIX) - bahasa scripting (JCL) pada IBM OS / 360 - di mana konvensi berbeda, sebelum porting lebih atau kurang tidak berubah ke UNIX - sebagian karena mereka yang cenderung menggunakannya, mengetahuinya dari sistem sebelumnya.Dalam istilah awam
Ketika di Roma, lakukan seperti yang dilakukan orang Romawi.
-p value
atau--parameter value
konvensi. Linux memiliki alat untuk parsing parameter dan flag tersebut dengan cara yang mudah.Saya biasanya melakukan sesuatu seperti ini:
Jika aplikasi CLI Anda ditujukan untuk Windows, maka gunakan
/flag
dan/flag:value
konvensi.Beberapa aplikasi seperti Oracle tidak menggunakan keduanya. Utilitas Oracle digunakan
PARAMETER=VALUE
.Satu hal yang ingin saya lakukan adalah, selain menerima parameter di baris perintah, menyediakan opsi untuk menggunakan parfile , yang merupakan file pasangan nilai-kunci untuk menghindari rantai parameter yang panjang. Untuk itu Anda harus memberikan
--parfile mifile.par
parameter tambahan . Tentunya jika--parfile
digunakan, semua parameter lainnya dibuang demi apa yang ada di dalam parfile.Saran tambahan memungkinkan penggunaan beberapa variabel lingkungan kustom , misalnya, pengaturan variabel lingkungan
MYAPP_WRKSPACE=/tmp
akan membuatnya tidak perlu untuk selalu ditetapkan--wrkspace /tmp
.TAB
dan kemudian shell akan menyelesaikannya untuk mereka.sumber
gcc
) Menangani@mifile.par
seperti--parfile mifile.par
saran Anda .fooCmd -opt1 -opt2 $(cat more_options.opts)
. Oleh karena itu saya akan mengharapkan opsi "config file parameter", jika disediakan, pada dasarnya harus bekerja dengan cara yang sama.Satu hal yang belum muncul:
Cobalah untuk merancang perangkat lunak Anda dari argumen baris perintah ke atas. Berarti:
Sebelum merancang fungsionalitas, desain antarmuka pengguna.
Ini akan memungkinkan Anda untuk menelusuri kasus tepi dan kasus umum di awal. Tentu saja Anda masih akan mengabstraksi bagian luar dan bagian dalam, tetapi ini akan memberikan hasil yang jauh lebih baik daripada hanya menulis semua kode dan kemudian membanting sebuah CLI ke dalamnya.
Selanjutnya, lihat docopt ( http://docopt.org/ ).
docopt sangat membantu dengan itu dalam banyak bahasa, terutama untuk python di mana Anda sangat terbatas, parser argumen yang merugikan pengguna seperti argparse masih dianggap sebagai "OK". Alih-alih memiliki parser dan subparser dan dicts kondisional, Anda hanya mendefinisikan bantuan sintaks dan ia melakukan sisanya.
sumber
argparse
karena tidak ada programmer, antarmuka pengguna atau ramah pengguna.Beberapa komentar berharga sudah disediakan (@Florian, Basile), tapi izinkan saya menambahkan ... OP mengatakan,
Tetapi juga berkomentar:
Anda harus mempertimbangkan audiens target Anda - administrator tingkat lanjut . Platform apa yang biasanya mereka kerjakan - Win / Unix / Mac? Dan pada platform apa Anda menjalankan aplikasi? Ikuti konvensi CLI apa pun yang telah ditetapkan untuk platform itu. Apakah admin "mahir" Anda menginginkan / memerlukan alat berbasis GUI?
Anda ingin antarmuka konsisten secara internal dan dengan alat admin lainnya. Saya tidak ingin berhenti dan berpikir apakah itu
cmd -p <arg>
ataucmd -p:<arg>
ataucmd /p <arg>
. Apakah saya perlu mengutip karena ada spasi? Bisakah sayacmd -p <val1> <val2>
ataucmd -p <val1> -p <val2>
banyak target? Apakah mereka memesan khusus? Overloadable? Apakahcmd -p2 <arg> -p1 <arg>
bekerja juga? Apakahls -l -r -t dir1 dir2
==ls -trl dir1 dir2
?Untuk alat admin Unix saya, saya selalu mengingat panduan yang diberikan oleh Heiner 's Shelldorado bersama dengan referensi lain yang disebutkan.
Sama pentingnya dengan merancang CLI adalah untuk memastikan aplikasi Anda dirancang untuk bekerja dengan argumen baris perintah sama dengan dari GUI - yaitu: tidak ada logika bisnis di GUI atau gunakan perintah umum yang disebut dari kedua GUI dan CLI.
Sebagian besar alat administratif berbasis UNIX sebenarnya dirancang terlebih dahulu sebagai alat baris perintah dan GUI yang disediakan hanya memfasilitasi "mengisi" opsi untuk baris perintah. Pendekatan itu memungkinkan untuk otomatisasi, penggunaan file respons, dll. Dan manajemen langsung (lebih sedikit pekerjaan untuk saya!)
Sebagai toolset klasik yang digunakan dengan pendekatan ini adalah Tcl / Tk . Tidak menyarankan Anda mengganti alat; cukup pertimbangkan pendekatan desain mulai dari menulis aplikasi administratif berbasis GUI ke aplikasi sebagai alat baris perintah terlebih dahulu; lalu lapisan GUI di atas untuk kenyamanan. Pada titik tertentu Anda mungkin akan menemukan bahwa GUI itu menyakitkan (dan rawan kesalahan) jika Anda harus melakukan banyak konfigurasi dan memasukkan kembali secara umum opsi yang sama berulang-ulang dan Anda akan mencari pendekatan otomatis.
Ingat admin Anda kemungkinan harus mengetikkan nilai yang benar di kotak yang benar, jadi berapa banyak usaha yang Anda hilangkan dengan GUI?
sumber