📌 置頂: 請把任何比你弱勢的用路人當作你的至親對待。跟前車保持安全車距 (2秒以上)。

如何 (濫用) prompt_toolkit 的自動補齊功能做到互動式命令列工具

In

Tags:



by

Figure 1. 使用 prompt_toolkit multi column autocompletion 功能做出 interactive command line tool.

目標與結論

本文的目標是想要在 command line 做到可以互動式選擇、展開有階層關係的文字列表工具。

使用 prompt_toolkit 的 autocompletion 功能,以及 prompt_toolkit.shortcuts.prompt 的 pre_run hook 達到互動式列表選擇的功能。

動機

寫好 awesome-cli 之後,覺得全部一次顯示的話會花很多時間在滾動捲軸上面 (因為有太多 list item),用 grep 沒有辦法展開一個 section 裡面的東西 (-A -B 的數量很不一致)、然後用 pipe head/less 會出現 BrokenPipelineError。

覺得 tui 太 heavy,因此想要做一個可以簡單選單互動、展開內容的 interactive command line tool.

實做選擇

PyInquirer

首先看到的是 CITGuru/PyInquirer,在範例上 list 的作法符合我想要達成的目標,但是因為 awesome-cli-apps 的表單光是 level 1/2 的 title 就會滿出一般的 terminal 高度,便想要做成 multi column 的形式。

PyInquirer 的 list example

查詢了一下發現這個問題有人在 2019 年提到卻一直沒有實做,且今年 (2021) 四月的時候 maintainer 宣佈不再繼續維護 PyInquirer,因此轉往尋找其他解法。

prompt_toolkit

在放棄 PyInquirer 之前,有去他的 code base 看一下實做,發現主要是用 prompt_toolkit 做成,便嘗試使用 prompt_toolkit 實做。prompt_toolkit 是一個 Python 非常成熟的一個套件,可以解決許多 command line I/O 的問題,在 prompt_toolkit examples 很詳盡的範例 (甚至有一個 full screen editor)。

在 examples 中搜尋到 multi column autocompletion 使用後發現就是需要這個,唯一需要解決的問題就是要如何讓他一打開就跳出,而不是使用者輸入 space 或是 TAB 之後才跳出這個清單。

prompt_toolkit multi column autocompletion example

開發者是可以透過 get_app() 來取得 current_buffer,接著把 autocompletion list 叫出來,只是因為 prompt() 呼叫後會 block,我們必須要有方法可以做到上面的事情。應該會有一些 callback hook 可以讓使用者 inject 想要做的事情,回頭去 prompt_toolkit.shortscut.prompt 的 source code 查看後,發現確實有一個 pre_run hook 可以用。

因此只要在 pre_run hook 讓 current_buffer.start_autocompltion() 便可以讓使用者不必敲入任何按鍵就顯示出 autocompletion list。

Using pre_run hook to make prompt_toolkit show autocompletion list when prompt

我們接著只要讓程式在選擇後顯示相對映的內容就完成了一個不用 tui 的輕量化互動式命令列工具。

Reference


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.