- Gooey เปลี่ยนแอปพลิเคชันคอนโซล Python 3 ให้เป็นแอปพลิเคชัน GUI ที่ผู้ใช้ปลายทางใช้งานได้ง่าย โดยทำงานด้วยการใส่ decorator เพียงบรรทัดเดียวให้กับฟังก์ชันที่มีการประกาศ
argparse
- การติดตั้งพื้นฐานทำได้ด้วย
pip install Gooey และเมื่อใช้ decorator @Gooey ร่วมกับ ArgumentParser Gooey จะอ่านอาร์กิวเมนต์และประกอบ UI บนพื้นฐาน WX components
- เมื่อการเลือกวิดเจ็ตพื้นฐานยังไม่พอ สามารถใช้
GooeyParser แทน ArgumentParser แบบ drop-in แล้วระบุอาร์กิวเมนต์ widget เพื่อเลือก custom widgets เช่น FileChooser, DateChooser, PasswordField, Slider ได้
- กลุ่มผู้ใช้เป้าหมายไม่ใช่เครื่องมือสำหรับนักพัฒนาที่ใช้งาน CLI โดยตรง แต่เป็นสคริปต์แบบ “รันแล้วเสร็จ” สำหรับงานสำนักงานหรือเครื่องมือสำหรับผู้ที่ไม่ใช่โปรแกรมเมอร์ โดยรองรับโหมดรันแบบขั้นสูง/พื้นฐาน/ไม่มีการตั้งค่า เมนู การแสดงความคืบหน้า การทำ internationalization การเปลี่ยนไอคอน และการแพ็กเกจ
- Dynamic validation และ lifecycle events ถูกระบุว่าเป็นฟีเจอร์ทดลอง โดยปัจจุบันยังไม่รองรับ
optparse และตั้งอยู่บนโค้ดที่ใช้ ArgumentParser พร้อมการสมัครรับ event แบบเลือกใช้
วิธีเปลี่ยนโปรแกรมคอนโซลเป็น GUI
- Gooey แปลงแอปพลิเคชันคอนโซลให้เป็นแอปพลิเคชัน GUI ที่ผู้ใช้ปลายทางใช้งานได้ง่าย
- วิธีใช้หลักคือการใส่ decorator
@Gooey ให้กับฟังก์ชันที่มีการประกาศ argparse
from gooey import Gooey
@Gooey
def main():
parser = ArgumentParser(...)
# rest of code
- สไตล์และพฤติกรรมสามารถปรับได้ผ่านอาร์กิวเมนต์ของ decorator
advanced: จะแสดงหน้าจอตั้งค่าขั้นสูงหรือไม่
language: เลือกคำแปลที่อิง JSON
auto_start: ข้ามหน้าจอตั้งค่าและเริ่มรันทันที
target: ระบุคำสั่งที่จะรันเป็น subprocess
program_name, program_description: ชื่อและคำอธิบายที่แสดงใน GUI
default_size: ขนาดเริ่มต้นของ GUI
dump_build_config, load_build_config: บันทึก/โหลดการตั้งค่า build ของ Gooey เป็น JSON
monospace_display: ใช้ฟอนต์ความกว้างคงที่ในหน้าจอ output
การติดตั้งและตัวอย่าง
- วิธีติดตั้งที่ง่ายที่สุดคือใช้ pip
pip install Gooey
- สามารถ clone repository แล้วรัน
setup.py เพื่อติดตั้งได้เช่นกัน
git clone https://github.com/chriskiehl/Gooey.git
python setup.py install
- สคริปต์ตัวอย่างที่เตรียมไว้สามารถรับได้จาก repository Gooey Examples
- repository ตัวอย่างมีไว้สำหรับสำรวจ layout, widget และฟีเจอร์ต่าง ๆ ของ Gooey
ทำไมจึงจำเป็น
- Gooey ถูกสร้างขึ้นเพื่อลดปัญหาการต้องแสดง command prompt ให้ผู้ใช้ที่ไม่คุ้นเคยเห็น
- หากโปรแกรมต้องทำงานมากกว่าหนึ่งแบบก็จำเป็นต้องรับ option และเดิมทีต้องสร้าง GUI เอง หรืออธิบายวิธีส่งอาร์กิวเมนต์ให้แอปพลิเคชันคอนโซล
- Gooey ช่วยให้นักพัฒนาสร้างโปรแกรมที่กำหนดค่าได้ในรูปแบบที่คุ้นเคย พร้อมนำเสนอการแสดงผลและการโต้ตอบเป็น GUI
ผู้ใช้ที่เหมาะสมและกรณีที่ไม่เหมาะ
- Gooey อาจไม่เหมาะกับ utility สำหรับตัวเองหรือนักพัฒนาโปรแกรมคนอื่น ๆ หรือเครื่องมือที่สร้างผลลัพธ์เพื่อนำไป pipe เข้ากับแอปพลิเคชันคอนโซลอื่น
- เหมาะกับ สคริปต์รันงานสำนักงาน, เครื่องมือย้ายข้อมูลจากจุด A ไปยัง B และโปรแกรมสำหรับผู้ที่ไม่ใช่โปรแกรมเมอร์
- เป้าหมายคือการสร้างแอปพลิเคชันที่ซับซ้อน พร้อมได้ส่วน GUI เพิ่มมาโดยไม่มีต้นทุนเพิ่มเติม
การทำงานภายในและการแมป argparse
- Gooey จะ parse reference ของ
ArgumentParser จากสคริปต์ Python ในช่วง runtime
- ปัจจุบันยังไม่รองรับ
optparse
- อาร์กิวเมนต์ที่ดึงออกมาจะได้รับการกำหนด component type ตาม
action ที่ให้มา และถูกใช้สร้าง GUI
- โดยพื้นฐานแล้ว
ArgumentParser._actions จะถูกแมปกับ WX components ดังนี้
store: TextCtrl
store_const, store_true, store_False, version: CheckBox
append: TextCtrl
count: DropDown
Mutually Exclusive Group: RadioGroup
choice: DropDown
GooeyParser และ custom widgets
- หากการเลือก widget พื้นฐานยังไม่เพียงพอ สามารถใช้ GooeyParser ซึ่งเป็นตัวแทนแบบ drop-in ของ
ArgumentParser ได้
GooeyParser ให้อาร์กิวเมนต์ keyword เพิ่มเติมคือ widget เพื่อระบุชื่อ component ที่จะแสดง
from gooey import Gooey, GooeyParser
@Gooey
def main():
parser = GooeyParser(description="My Cool GUI Program!")
parser.add_argument('Filename', widget="FileChooser")
parser.add_argument('Date', widget="DateChooser")
- custom widgets ที่รองรับมีดังนี้
DirChooser, FileChooser, MultiFileChooser
FileSaver, MultiFileSaver
DateChooser, TimeChooser
PasswordField
Listbox
BlockCheckbox
ColourChooser
FilterableDropdown
IntegerField, DecimalField
Slider
- ค่าที่
DateChooser และ TimeChooser ส่งให้แอปพลิเคชันจะเป็น ISO format เสมอ ขณะที่บางส่วนของ GUI อาจแสดงค่าที่ localize ตามการตั้งค่าของผู้ใช้ปลายทาง
BlockCheckbox จะย้ายบล็อกข้อความไปยังตำแหน่งปกติและแสดง block_label สั้น ๆ ข้าง control เพื่อให้ดูดีกว่า checkbox แบบ inline พื้นฐานเมื่อมีข้อความช่วยเหลือยาว ๆ
Internationalization
- Gooey เลือกภาษาที่แสดงผลผ่านอาร์กิวเมนต์
language ของ decorator
@Gooey(language='russian')
def main():
...
- ข้อความทั้งหมดของโปรแกรมถูกเก็บไว้ใน ไฟล์ JSON ภายนอก
- การรองรับภาษาใหม่ทำได้โดยเพิ่ม key/value ในไดเรกทอรี
gooey/languages/
- ปัจจุบันมีคำแปลมากกว่า 18 ภาษาให้มาในตัว
การตั้งค่าทั่วไปและการจัดองค์ประกอบ UI
- รูปลักษณ์และพฤติกรรมโดยรวมของ Gooey ปรับได้ผ่านอาร์กิวเมนต์ของ decorator
- การตั้งค่าหลักมีดังนี้
encoding: encoding ของตัวอักษรที่แสดง ค่าเริ่มต้นคือ utf-8
advanced: เลือกหน้าจอตั้งค่าเต็มรูปแบบหรือหน้าจอแบบย่อ
auto_start: รันทันทีโดยไม่ต้องตั้งค่า
target: ระบุวิธีที่ Gooey จะรันตัวเองอีกครั้ง
suppress_gooey_flag: ป้องกันการฉีดพารามิเตอร์ CLI เพิ่มเติมเมื่อใช้ target แบบ custom
fullscreen: เริ่มต้นแบบเต็มหน้าจอ
image_dir: ไดเรกทอรีรูป/ไอคอน custom
language_dir: ไดเรกทอรีไฟล์ภาษา custom
disable_stop_button, show_stop_warning: ควบคุมปุ่มหยุดและคำเตือนระหว่างรัน
show_success_modal, show_failure_modal: จะแสดง modal สรุปผลสำเร็จ/ล้มเหลวหรือไม่
run_validators: จะทำ validation ก่อนเรียกโปรแกรมหรือไม่
progress_regex, progress_expr: parse และแปลงข้อความความคืบหน้า
navigation: TABBED หรือ SIDEBAR
body_bg_color, header_bg_color, footer_bg_color, sidebar_bg_color: การตั้งค่าสี
terminal_font_family, terminal_font_size, terminal_font_color: การตั้งค่าฟอนต์สำหรับแสดง terminal
menus: กลุ่มและรายการเมนู custom
clear_before_run: ลบ output เดิมเมื่อรันซ้ำ
Layout และโหมดการรัน
- โดยพื้นฐานแล้ว Gooey จะแบ่ง input ออกเป็นสองกลุ่มคือ
positional และ optional
- เมื่อใช้
add_argument_group() ของ argparse จะสามารถจัด input เป็นกลุ่มเชิงตรรกะและปรับ layout ของแต่ละกลุ่มได้
parser = ArgumentParser()
search_group = parser.add_argument_group(
"Search Options",
"Customize the search options"
)
search_group.add_argument(
'--query',
help='Base search string'
)
ฟีเจอร์เมนู
- ตั้งแต่ Gooey 1.0.2 เป็นต้นมา สามารถเพิ่ม Menu Bar ด้านบนได้
- เมนูกำหนดเป็นรายการของ map ในรูปแบบ
@Gooey(menu=[{}, {}, ...])
- แต่ละกลุ่มเมนูมี
name และ items
- แต่ละรายการเมนูต้องมี
type และ menuTitle เสมอ
- ประเภทรายการเมนูที่รองรับมีดังนี้
AboutDialog: แสดงข้อมูลโปรแกรม เช่น ชื่อ เวอร์ชัน ใบอนุญาต
MessageDialog: แสดงข้อความให้ข้อมูลแก่ผู้ใช้
Link: เปิด URL ที่ระบุใน browser เริ่มต้น
HtmlDialog: แสดง dialog โดยใช้ subset ของ HTML ที่จำกัด
Dynamic Validation
- Dynamic Validation เป็นฟีเจอร์ทดลอง และ API อาจเปลี่ยนแปลงหรือถูกนำออกได้
- Gooey สามารถทำ pre-validation กับ input ของผู้ใช้ก่อนส่งให้โปรแกรมได้แบบเลือกใช้
- ฟีเจอร์นี้ใช้ประโยชน์จากพารามิเตอร์
type ที่ใช้ได้กับอาร์กิวเมนต์ Argparse ส่วนใหญ่
def must_be_exactly_ten(value):
number = int(value)
if number == 10:
return number
else:
raise TypeError("Hey! you need to provide exactly the number 10!")
- โดยพื้นฐานแล้ว validation จะไม่ถูกเรียกใช้
- หากต้องการเปิดใช้งาน ต้อง subscribe event
VALIDATE_FORM
from gooey import Gooey, Events
@Gooey(use_events=[Events.VALIDATE_FORM])
def main():
...
- ฟีเจอร์นี้ใช้ Monkey Patching อย่างหนักภายใน จึงเป็นแบบ opt-in ในปัจจุบัน
Lifecycle events และการควบคุม UI
- ตั้งแต่ Gooey 1.2.0 เป็นต้นมา มีการเปิดเผย lifecycle hooks ให้โปรแกรมใช้
- ฟีเจอร์นี้ก็เป็นแบบทดลองเช่นกัน และ API อาจเปลี่ยนแปลงหรือถูกนำออกได้
- hook หลักในปัจจุบันมีสองรายการ
- hook ทั้งสองจะถูกรันหลัง process เสร็จสิ้น
- handler จะได้รับ object Argparse ที่ parse แล้วและสถานะ UI ปัจจุบันของ Gooey และหากส่งคืนสถานะที่อัปเดตแล้วก็สามารถนำไปสะท้อนใน UI ได้
- handler เชื่อมต่อเมื่อสร้าง
GooeyParser
parser = GooeyParser(
on_success=my_success_handler,
on_failure=my_failure_handler)
- หากต้องการใช้ ต้อง subscribe event อย่างชัดเจน
from gooey import Gooey, Events
@Gooey(use_events=[Events.ON_SUCCESS, Events.ON_ERROR])
def main():
...
การแสดงความคืบหน้าและเวลา
- Gooey สามารถอ่าน output ความคืบหน้าแบบข้อความเดิมเพื่อขับ Progress Bar ได้
- ในกรณีง่าย ๆ จะแปลงเป็นความคืบหน้าด้วยการ match string อย่าง
Progress 83% ด้วย regular expression
@Gooey(progress_regex=r"^progress: (\d+)%$")
- output ที่ซับซ้อนกว่าสามารถใช้
progress_expr เพื่อแปลงผลการ match ของ regular expression ได้
@Gooey(progress_regex=r"^progress: (?P<current>\d+)/(?P<total>\d+)$",
progress_expr="current / total * 100")
- หากระบุ
hide_progress_msg=True จะสามารถซ่อนข้อความ output ที่ match กับความคืบหน้าจาก console ได้
- เมื่อใช้
timing_options สามารถแสดงเวลาที่ผ่านไปและเวลาที่เหลือได้
- การแสดงเวลาจะทำงานเฉพาะเมื่อใช้
progress_regex และ progress_expr เท่านั้น
ไอคอนและการแพ็กเกจ
- Gooey มีไอคอนพื้นฐานให้ 6 รายการ และสามารถระบุไดเรกทอรีรูป custom ด้วยอาร์กิวเมนต์
image_dir เพื่อเขียนทับได้
- ค้นหารูปตามชื่อไฟล์ โดยชื่อไฟล์ที่เขียนทับได้มีดังนี้
program_icon.png
success_icon.png
running_icon.png
loading_icon.gif
config_icon.png
error_icon.png
- การแพ็กเกจไฟล์ executable มีตัวอย่างการใช้ PyInstaller ให้
- ขั้นตอนโดยสรุปคือวาง
build.spec ไว้ที่ root ของแอปพลิเคชัน ปรับค่า APPPNAME, name, pathex ให้ตรงกับโปรเจกต์ แล้วรัน
pyinstaller -F --windowed build.spec
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
เอ่อ นี่โปรเจกต์ของผมเอง ^_^ ทำไมถึงขึ้นไปอยู่บนสุดของ HN ได้เนี่ย?
ขอตอบสั้น ๆ เรื่องคอมเมนต์เกี่ยวกับ
argparse: Gooey เป็นโปรเจกต์ที่ค่อนข้างเก่าแล้ว และตอนเริ่มทำargparseก็เป็นตัวเลือกที่แข็งแรงดีทุกวันนี้ตัว Gooey เองทำงานด้วย JSON และแยกออกจาก
argparseแล้ว แต่แทบไม่มีใครทำอินเทอร์เฟซอื่นขึ้นมา ดังนั้นargparseจึงยังคงเป็นอินเทอร์เฟซ “ทางการ” หลักอยู่จุดที่น่าสนใจคือมันเรียกใช้ได้ไม่ใช่แค่ Python แต่รวมถึง ไฟล์ปฏิบัติการใด ๆ ด้วย จึงมีประโยชน์ทีเดียว: https://chriskiehl.com/article/gooey-as-a-universal-frontend
ส่วนเรื่องที่คอมมิตล่าสุดเมื่อ 2 ปีก่อนนั้น พออายุมากขึ้นและลำดับความสำคัญเปลี่ยนไป ก็ยากที่จะหาเหตุผลมาดูแลซอฟต์แวร์เฉพาะทางเล็ก ๆ ต่อไปฟรี ๆ :( ไม่รู้ว่าจะช่วยปลอบใจได้ไหม แต่ผมรู้สึกผิดอยู่เสมอ
แปลกดีที่แถว ๆ เมืองที่ผมอยู่มีกราฟฟิตี้คำว่า “GOOEY” อยู่หลายจุด มันเลยเหมือนตัวเตือนถาวรที่คอยทำให้นึกถึง issue tracker ที่ถูกทิ้งค้างไว้ haha
argparseยังเป็นตัวเลือกที่ค่อนข้างดีอยู่ มันถูกใช้แพร่หลายมาก เอกสารก็ดี และค่อนข้างง่ายTyper กับ Click ก็ใช้งานดี แต่ผมรู้สึกว่าเอกสารแบบ “ทูตอเรียล” ของ Typer ค้นหาคำตอบอย่างเช่น
Typer.App()รับอาร์กิวเมนต์อะไรบ้างได้ค่อนข้างยากโปรแกรมที่ผมกำลังทำอยู่เป็นโครงสร้างที่ให้ผู้ใช้เริ่มการ parse อาร์กิวเมนต์เอง ดังนั้น
argparseจึงเหมาะดี ผมอยากให้ผู้ใช้มี UI แบบข้อความเป็นตัวเลือก แต่จำได้ว่า Textualize ต้องใช้ Click และพอพยายามเอา Textual มาต่อเข้ากับโค้ดโดยตรงเพื่อทำ UI ใช้เวลาไปหลายชั่วโมงแล้วยังเริ่มไม่ได้ด้วยซ้ำทุกวันนี้มีเรื่องน่าหงุดหงิดมากมายเพราะเราไม่สามารถควบคุมแอปพลิเคชันด้วยการเขียนโปรแกรมได้ พูดตรง ๆ ผมอยากให้มีกฎหมายว่าฟีเจอร์ทุกอย่างของแอปพลิเคชันต้องมี API
sys.argvไปเป็นไฟล์ local ในไดเรกทอรีทำงานปัจจุบันครับ? https://github.com/chriskiehl/Gooey/blob/be4b11b8f27f500e732...tmp.txtดูห่างไกลจากชื่อที่ไม่ซ้ำกันมาก เลยสงสัยว่าผมพลาดอะไรไปหรือเปล่าargparseแล้ว” นั้นเจ๋งดีตอนเห็นแค่ชื่อเรื่อง ก่อนคลิกเข้ามา ผมนึกว่า “ต้องพึ่ง
argparseหนักแน่ ๆ” แต่ก็ประหลาดใจในทางที่ดีผมเป็นแฟนตัวยงของ
getoptเพราะมองว่าความสะดวกของผู้ใช้สำคัญกว่าความสะดวกของนักพัฒนามาก ผู้ใช้ไม่ควรต้องสนใจว่านักพัฒนาเลือกภาษาโปรแกรมหรือไลบรารี parse ออปชันอะไรไลบรารีจำนวนมาก เช่น
argparse, Click,flagของ Go/สไตล์ X11 ฯลฯ ทำลายธรรมเนียมที่ฝังอยู่ในความจำกล้ามเนื้อร่วมกันตลอดครึ่งศตวรรษที่ผ่านมา แต่ถ้ามีเลเยอร์คั่นกลาง ก็ดูเหมือนจะ ได้ทั้งสองอย่างที่แย่กว่านั้นคือยังไม่มีทางเลือกอื่นที่ใช้แทนได้จริงออกมา และ fork ทั้งสองตัวก็ไม่มีตัวไหนได้รับแรงส่งเลย
อันนี้ไม่ควรระบุให้ชัดว่าเป็น “บนพื้นฐาน
argparse” เหรอ?argparseดีสำหรับงานง่าย ๆ แต่ก็มี CLI จำนวนมากที่ใช้ Click และไลบรารี CLI ยอดนิยมจำนวนไม่น้อยก็สร้างอยู่บน Click มีเครื่องมือ CLI ของ Python ที่ไม่ใช่ทั้งargparseหรือ Click ด้วย แต่สองตัวนี้ก็น่าจะอยู่ในกลุ่มที่นิยมที่สุดยืนยันแล้วหรือยังว่าทำงานกับ Click ได้? ตอนนี้เห็นแต่เนื้อหาเกี่ยวกับ
argparseถ้าคำตอบคือไม่ คำว่า “เกือบทุก” ก็เป็นเท็จอย่างชัดเจน และชื่อที่แม่นกว่าคือ “เปลี่ยนโปรแกรมบรรทัดคำสั่ง Python ที่ใช้argparseเกือบทุกตัวให้เป็นแอปพลิเคชัน GUI เต็มรูปแบบ”อีกอย่างคือคอมมิตที่มีนัยสำคัญครั้งล่าสุดก็เกิน 2 ปีมาแล้ว ตัวมันเองไม่ได้แย่ แต่พอดูจำนวน issue ที่เปิดอยู่ ก็ไม่ได้ทำให้เกิดความเชื่อมั่นต่อโปรเจกต์มากนัก
ถึงอย่างนั้นก็เป็นโปรเจกต์ที่เจ๋ง อยากเห็นอะไรแบบนี้มากขึ้น ตามที่ README บอก มันเป็น เครื่องมือทวีพลัง ทำให้ใครสักคนสร้างระบบอัตโนมัติด้วย CLI แล้วแชร์ให้คนในออฟฟิศสายงานที่ไม่ใช่เทคนิคใช้งานได้ง่าย คล้ายกับบทบาทที่ Access เคยทำให้กับฐานข้อมูล
เหมือนกับ Access พอเริ่มมีขนาดหรือความซับซ้อนก็จะชนข้อจำกัด แต่สำหรับงานในออฟฟิศขนาดเล็ก มันอาจ “ดีพอ” ได้เลย
argparseขาดอะไรไป แนวทางของผมคือ ลด dependency ภายนอกให้เหลือน้อยที่สุดargparseไม่ได้จริง ๆ?บทความที่เกี่ยวข้อง:
Gooey: Turn almost any Python command line program into a GUI application - https://news.ycombinator.com/item?id=27490291 - มิถุนายน 2021, 115 ความคิดเห็น
Gooey: Turn command line programs into GUI applications - https://news.ycombinator.com/item?id=8218785 - สิงหาคม 2014, 74 ความคิดเห็น
คงจะดีถ้าระบบปฏิบัติการและเชลล์เข้าใจวิธีรันโปรแกรมได้ดีขึ้น โดยไม่ต้องพึ่งพาไลบรารีสำหรับ parsing เฉพาะตัว
คงจะดีถ้าโปรแกรมต่าง ๆ สื่อสารกันด้วย รูปแบบ JSON/proto ที่มี type และแค่ตรวจดู type ของอินพุต/เอาต์พุตที่คาดหวัง ก็ได้โครงสร้างคำสั่งเชลล์กับการเติมคำอัตโนมัติ หรือแม้แต่ GUI เต็มรูปแบบ
ตอนนี้สิ่งที่ดีที่สุดดูเหมือนทำได้แค่ระดับค่อย ๆ เอาหลอดเสียบเข้าไป โปรแกรมแต่ละตัวต้องส่งออกไฟล์ autocomplete สำหรับเชลล์หลายแบบ ไลบรารี parsing กับโปรแกรมแต่ละตัวก็มีสไตล์ flag ต่างกันมาก และแน่นอนว่าไม่มี GUI
แต่ปัญหาหลักของ gRPC คงเป็นว่า developer จำนวนมาก รวมถึงผมเอง รู้สึกว่ามันใช้งานเกะกะกว่าวิธีแก้ที่ใช้ได้เป็นธรรมชาติภายในภาษา
ไม่แน่ใจว่า PowerShell ใช้ประโยชน์จาก static type ที่เป็นแกนหลักได้เต็มที่หรือไม่ แต่ความสามารถในการส่ง object ไปมาบน command line นั้นแทบไม่มีใครเทียบ
บน Linux สามารถต่อ command line เข้าด้วยกันโดยใช้
jc(https://github.com/kellyjonbrazil/jc) ร่วมกับjq(https://jqlang.github.io/jq/) ได้ แต่เมื่อเทียบกับฟีเจอร์ที่มีในตัวของ PowerShell แล้ว ก็ยังต้องประมวลผลเพิ่มอีกสองขั้นอยู่ดีGUI บางครั้งให้ความรู้สึกเหมือน comfort food เพราะสามารถเปิดดู อินเทอร์เฟซ GUI ได้เลย โดยไม่มีภาระทางความคิดที่อาจเกิดขึ้นกับ CLI ที่ใช้นาน ๆ ครั้ง
ออกนอกเรื่องนิดหน่อย เมื่อไม่กี่เดือนก่อนผมได้รู้จักเอดิเตอร์ CUDATEXT จากที่นี่ ซึ่งให้ใช้ element ของ GUI แบบใดก็ได้ เช่น MENU, INPUTS ผ่าน Python API ไฟล์เดียว element เหล่านี้เป็นตัวเดียวกับที่เอดิเตอร์เองก็ใช้
ตอนนี้ผมใช้ element ของ GUI แบบง่าย ๆ เหล่านั้นสำหรับตั้งค่า และสร้างบล็อกได้โดยตรงในเอดิเตอร์
สิ่งที่น่าดูควบคู่กัน:
“Textual: เฟรมเวิร์กแอปพลิเคชันน้ำหนักเบาสำหรับ Python สร้างอินเทอร์เฟซผู้ใช้ที่ประณีตด้วย Python API ที่เรียบง่าย และรันแอปได้ทั้งในเทอร์มินัลและเว็บเบราว์เซอร์” https://github.com/textualize/textual/
camply: https://juftin.com/camply/
อยากบอกว่าขอบคุณที่สร้างซอฟต์แวร์ยอดเยี่ยมนี้ขึ้นมา ผมชอบ Gooey และใช้มันมาเยอะในหลายโปรแกรม
สำหรับผม มันพอดีกับพื้นที่นั้นเป๊ะ ๆ คือสคริปต์ Python กำลังทำงานสำคัญบางอย่างอยู่ และตอนนี้ต้องทำให้ คนที่ไม่ใช่โปรแกรมเมอร์ก็ใช้ได้
สิ่งนี้ทำให้นึกถึง naked objects แนวคิดคือแค่กำหนด annotation กับ theme บางอย่างในคลาส Java ก็จะสร้าง GUI ทั้งชุด หรือแอปพลิเคชัน web frontend ให้
เป็นไอเดียที่เจ๋งมาก แต่เท่าที่ผมรู้ สุดท้ายก็ไม่ได้ไปได้สวยนัก
ในความเห็นผม ปัญหาคือ ข้อกังวลแนวตั้ง อย่าง presentation, domain และ infrastructure ถูกผูกเข้าด้วยกัน ถ้าการแสดงผลบนหน้าจอและการแทนค่าในฐานข้อมูลของ domain model เรียบง่ายก็ยังโอเค
แต่ถ้าอยากทำอินเทอร์เฟซซับซ้อนที่มีฟีเจอร์อำนวยความสะดวกเยอะ ๆ ความต้องการเหล่านั้นก็ต้องรั่วไหลเข้าไปในชั้น domain ในทางกลับกัน ถ้าอยากทำ domain model ที่ซับซ้อน ก็แทบเป็นไปไม่ได้ที่จะบังคับ invariant ในระดับภาษา เพราะโค้ดใด ๆ ที่มี reference ไปยัง
Modelก็แตะต้องมันได้ตามใจคงจะดีถ้ามีสิ่งที่ทำกลับกันได้ด้วย
argparseแล้วแปลงกลับเป็น shell script ที่รันและบันทึกผลลัพธ์ได้อย่างเหมาะสมMacintosh Programmer's Workshop รุ่นเก่า หรือ MPW ซึ่งเป็นเชลล์แบบข้อความสำหรับ Mac OS ยุค 80–90 มีฟีเจอร์คล้าย ๆ กันชื่อ Commando สำหรับแทบทุกคำสั่ง
ข้อมูล Commando ถูกเก็บไว้ใน resource
cmdoถ้าการรองรับ extended attribute ไม่ได้กระท่อนกระแท่นแบบนี้ ทุกวันนี้ก็น่าจะทำอะไรคล้าย ๆ กันได้ลองค้นดูแล้ว A/UX ก็มี Commando ด้วย ถ้าดับเบิลคลิกคำสั่งเทอร์มินัลใน Finder จะมีกล่อง Commando โผล่มาให้เลือก option ของ CLI แล้วจากนั้นจึงรันในหน้าต่างเชลล์ ทุกวันนี้ถ้ารันคำสั่งเทอร์มินัลจาก Finder มันก็แค่รันในหน้าต่างเชลล์โดยไม่มี argument
https://cohost.org/boredzo/post/804893-i-still-want-a-moder
http://toastytech.com/guis/aux3.html