17  سطر الأوامر

واجهة سطر الأوامر (Command-line Interface) هي واجهة نصية تُستخدم للتفاعل مع نظام التشغيل بكتابة أوامر مباشرة، بدلاً مما يظهر على الشاشة من تطبيقات ونوافذ.

وهي صالحة للمبرمج أو التقني الذي ألِف استعمال الشاشة السوداء.

ومن ميزاتها أنها لا تتطلَّب جهدًا كبيرًا في صناعتها مقارنة بالواجهة الرسومية لذا فإن كثيرًا من البرمجيات المفيدة تبدأ بهذا الشكل. وبعضها لا يفيد المستخدم العادي لأنها أدوات مخصوصة في البرمجة أو البرمجيات فتبقى هكذا.

المبرمج (يمين) يكتب البرنامج ويقدمه للمستفيد التقني (يسار)

وفيها مسلكان:

الأول: واجهة نصية؛ ولها مكتبة أساسية في بايثون هي argparse ومكتبات خارجية أسهل في التعبير منها مثل: typer المبنية على click.

صورة توضح الواجهة النصية باستعمال المكتبة الخارجية Typer

الثاني: واجهة رسوميَّة على شكل واجهة نصية (Terminal User Interface - TUI) وهي أجمل. ومن أشهر مكتباتها Textualize، وقد تكون أصعب من مكتبات الواجهة النصية.

صورة توضح واجهة نافذة الأوامر باستعمال المكتبة الخارجية Textualize

مكتبة (typer)

تعتبر Typer مكتبة لبناء تطبيقات سطر الأوامر (CLI) بطريقة مناسبة، تعتمد على ميزة التصريح بالأنواع في بايثون.

  • يحب المستخدمون استعمالها ويستمتع المطورون بإنشائها.
  • سهلة الاستخدام: سهلة على المستخدم بتوليد تلقائي لنص المساعدة، وإكمال تلقائي للأوامر في جميع نوافذ سطر الأوامر.
  • تستوعب التعقيد: حيث تنمو حتى مع التطبيقات المعقدة بمزايا مثل شجرة الأوامر والمجموعات.

أولا تثبيت المكتبة باستعمال uv على النحو التالي:

uv add typer

أبسط برنامج

import typer


def main(name: str):
    print(f"Hello {name}")


if __name__ == "__main__":
    typer.run(main)

ثم نشغل الوحدة البرمجية باستعمال بايثون:

python main.py Pythonia

برنامج بأمريْن

وهذا برنامج يحتوي على أمرين:

  1. hello
  2. goodbye

وهكذا نكتبه:

import typer

app = typer.Typer()


@app.command()
def hello(name: str):
    print(f"Hello {name}")


@app.command()
def goodbye(name: str, formal: bool = False):
    """Says goodbay to the person either formally or informally"""
    if formal:
        print(f"Goodbye Mr. {name}. Have a good day.")
    else:
        print(f"Bye {name}!")


if __name__ == "__main__":
    app()

ويمكننا الآن أن نطلب المساعدة --help من البرنامج على النحو التالي:

python main.py --help

فيخرج لنا التالي ..

الشكل العام للاستعمال، وهو: اسم البرنامج متبوعًا بالخيارات ثم الأمر ثم العوامل:

Usage: main.py [OPTIONS] COMMAND [ARGS]...

الخيارات (Options) تتميز بعلامة الشرطتين (--) قبل اسمها، وهي ليست بلازمة

╭─ Options ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --install-completion          Install completion for the current shell.                                                           │
│ --show-completion             Show completion for the current shell, to copy it or customize the installation.                    │
│ --help                        Show this message and exit.                                                                         │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

الأوامر (Commands) مجردة عن الشرطات ويلزم تحديدها.

╭─ Commands ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ hello                                                                                                                             │
│ goodbye   Says goodbay to the person either formally or informally                                                                                                                           │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

وقد استعملنا خيار المساعدة --help بعد اسم البرنامج. والآن نستعمل أمر goodbye ونضع له هو خيار المساعدة --help:

python main goodbye --help

فيخرج لنا التالي ..

الشكل العام للاستخدام، وهو اسم البرنامج متبوعًا باسم الأمر مبتوعًا بالخيارات وبعدها الاسم NAME وهو العامل الوحيد:

Usage: app.py goodbye [OPTIONS] NAME

Says goodbay to the person either formally or informally

العوامل (Arguments) مثل NAME فهي موضعيَّة ولازمة: يجب الإتيان بها ولابد أن يكون في ترتيبه الصحيح.

╭─ Arguments ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ *    name      TEXT  [default: None] [required]                                                                                   │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

الخيارات (Options) هنا هي للأمر نفسه لا للبرنامج ككل.

╭─ Options ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --formal    --no-formal      [default: no-formal]                                                                                 │
│ --help                       Show this message and exit.                                                                          │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

لاحظ أننا في الحد الذي يعرِّف الإجراء عرَّفنا العامل formal: bool = False وهذا جعله:

  1. من النوع المنطقي (bool) فاستفاد بذلك أن يكون له خياران متضادان:
    • --formal وهو اسم العامل
    • --no-formal وهو كلمة no- قبل اسم العامل
  2. واستفاد بتعيين القيمة الافتراضية عند التعريف False أنه:
    • يندرج تحت الخيارات لا العوامل

فلك أن تكتب الأمر بهذا الشكل:

python main.py goodbye Hani --formal

أو بتقديم الخيار على العامل:

python main.py goodbye --formal Hani

لترى:

Goodbye Mr. Hani. Have a good day.

مزايا أخرى لطبقة العرض عن طريق (typer)

للمزيد انظر في صفحات المكتبة:

…إلخ.

بناء الحزمة

وأما لتغليف البرنامج حتى يكون صالحًا للتثبيت، فراجع: بناء الحزمة