All GTK 3 Style Properties
【摘要】提供一個能將所有 GTK 3 style properties 收集成一個檔案的 BASH 指令,並詳細解析之。
【目錄】
【前言】【指令解析】
A. 基本設定
B. 主要指令
C. 加入 html5 檔尾並結束程式
【後語】
【附錄】
【前言】
一、設定 GTK 3 的樣式時,一定會用到 CSS nodes 和 style properties。但這些資料分散在各個 widget 的說明中,不利查詢。如果集中到一個檔案裡,會比較方便。本文敘述收集 style properties 的方法,另一篇敘述收集 CSS nodes 的方法。
二、本文約半年前曾在 Google 的 Blogger 發表過,近日再度檢視,更新後發表於此。
三、來源資料是官網的 “GTK 3 Reference Manual“,目前的版本是 3.24.13。下載的檔案應是 gtk3-html-3.24.13.tar.gz,以下假設解開在自家的 $HOME/Documents/gtk3-html-3.24.13/ 目錄中。
四、收集的方法是用常見的 BASH 和 Linux 指令,作業系統是 Debian GNU/Linux 10。
五、輸出的資料不含過時不用的 (deprecated) 項目。
六、最後的【附錄】有完整的指令,可以複製到一個空白檔案中;假設檔名是 get_style_prop.sh
,執行 bash get_style_prop.sh
即可。
【指令解析】
仔細觀察參考手冊 widget 的說明,可以知道每個都是 .html 檔,而且語法結構相當規律。html 文件有固定的 tags (標籤),我們就利用這些特性,搜尋各個 html 文件中的某些特定標籤,將相關的內容輸出到一個檔案裡。以下依序說明每個指令。
A. 基本設定
⒈ 指定參考手冊所在的目錄
PathIn=$HOME/Documents/gtk3-html-3.24.13
⒉ 指定輸出檔的目錄和檔名
假設是自己的 Documents 目錄,檔名可以自訂。
PathOut=$HOME/Documents FileOut=GTK3-style_prop.html
提醒:若已有此檔,會被覆寫。
⒊ 複製樣式檔
官方參考手冊中,每個 widget 的 html 檔都使用同一個 CSS 樣式檔。我們從這些 html 檔取出資料,也要用這個樣式檔,才能正確顯示結果。
cp ${PathIn}/style.css ${PathOut}
⒋ 新增或清空輸出檔
: > ${PathOut}/${FileOut}
⒌ 加入 html5 檔頭
因為輸出的檔案也是 html 格式,所以頭尾要有基本的 elements。
echo '<!DOCTYPE html>' >> ${PathOut}/${FileOut} echo '<html>' >> ${PathOut}/${FileOut} echo '<head>' >> ${PathOut}/${FileOut} echo ' <title>Style Properties</title>' >> ${PathOut}/${FileOut} echo ' <meta charset="UTF-8">' >> ${PathOut}/${FileOut} echo ' <link rel="stylesheet" href="style.css" type="text/css">' >> ${PathOut}/${FileOut} echo '</head>' >> ${PathOut}/${FileOut} echo '<body>' >> ${PathOut}/${FileOut}
B. 主要指令
⒈ 每個 widget 的 html 檔名都是以 Gtk
開頭,所以可以很容易地找出來。
for FileIn in $(ls ${PathIn}/Gtk*.html) do
⒉ 這些說明檔在敘述 style properties 時,都分在 “Style Property Details" 一節中,所以逐行讀入時,就檢查是否有此內容。一開始還沒有時,先將標記設為 0。
Flag1=0
⒊ “Style Property Details" 一節的內容是由 <div class="refsect2″> 開始;這也要有個標記,才知道內容的開始與結束。
Flag2=0
⒋ 因為要去除過時的項目,而一個項目是否過時並不是標在內容的第一行,所以必需把一個樣式的內容先儲存起來,再來檢查。若非過時,便將內容輸出;若已過時,則清除之。一開始先設為空字串。
Content=""
⒌ 逐行讀入。
while read do
⒍ 檢查所需資料是否開始。
if [[ ${REPLY} =~ .*\>Style\ Property\ Details\<.* ]]
${REPLY}
就是剛讀入的那一行。但其他地方也可能有 “Style Property Details",所以連前後的角括號(<h2>Style Property Details</h2>)也包括在內。
⒎ 若是,表示所需內容開始。
then Flag1=1
⒏ 取出 Widget 名稱;先從全路徑中取出檔名,再去掉副檔名。
FileIn=`basename ${FileIn}` && WidgetName=${FileIn::(-5)}
⒐ 輸出 Widget 名稱並設為標題放大字體,以便區別各個 widget。
echo "<h3>${WidgetName}</h3>" >> ${PathOut}/${FileOut}
⒑ 去讀下一行。
continue fi
⒒ 以上的 if
是找到開頭處,以下收集內容,並看內容是否結束。
if [[ ${Flag1} -eq 1 ]] then
⒓ 若欲收集的資料已開始,會有多種狀況,一一處理。這些狀況全憑多次試驗而來。
第一種狀況:若開始一個 <div class="refsect2″>,要加以標記,因為 “Style Property Details" 一節的內容由此開始。
if [[ ${REPLY} =~ .*class=\"refsect2.* ]] then Flag2=1
⒔ 既然所需資料已經開始,就開始收集內容。
Content="${REPLY}"
⒕ 去讀下一行。
continue fi
⒖ 第二種狀況:若是一個樣式的下一行,就繼續累積內容。
if [[ ${Flag2} -eq 1 ]] then Content="${Content}\n${REPLY}"
⒗ 第三種狀況:若是一個樣式的結束,就先做記號,再輸出累積的內容。資料輸出後,清除內容,才繼續。
if [[ ${REPLY} =~ .*\</div.* ]] then Flag2=0 echo -e "${Content}" >> ${PathOut}/${FileOut} Content="" continue fi
⒘ 第四種狀況:是否過時?若是,就先做記號,再清除已累積的過時內容,才繼續。
if [[ ${REPLY} =~ .*been\ deprecated.* ]] then Flag2=0 Content="" continue fi fi
⒙ 第五種狀況:下一節開始或已到頁腳,表示所需資料結束。畫一條線隔開不同的 widget,以利閱讀,並結束此檔。
if [[ ${REPLY} =~ .*class=\"refsect1.* || ${REPLY} =~ .*class=\"footer.* ]] then echo "<hr>" >> ${PathOut}/${FileOut} break fi fi
done < ${FileIn}
這是讀入某一檔。
done
這是結束讀入所有 Gtk*.html。
C. 加入 html5 檔尾並結束程式
echo '</body>' >> ${PathOut}/${FileOut} echo '</html>' >> ${PathOut}/${FileOut} exit
【後語】
從上述的內容可知,指令決定於官方參考手冊的 html 語法。所以,可以預見的是當這些語法改變時,指令可能也要修正。
【附錄】
#!/usr/bin/bash PathIn=$HOME/Documents/gtk3-html-3.24.13 PathOut=$HOME/Documents FileOut=GTK3-style_prop.html cp ${PathIn}/style.css ${PathOut} : > ${PathOut}/${FileOut} echo '<!DOCTYPE html>' >> ${PathOut}/${FileOut} echo '<html>' >> ${PathOut}/${FileOut} echo '<head>' >> ${PathOut}/${FileOut} echo ' <title>Style Properties</title>' >> ${PathOut}/${FileOut} echo ' <meta charset="UTF-8">' >> ${PathOut}/${FileOut} echo ' <link rel="stylesheet" href="style.css" type="text/css">' >> ${PathOut}/${FileOut} echo '</head>' >> ${PathOut}/${FileOut} echo '<body>' >> ${PathOut}/${FileOut} for FileIn in $(ls ${PathIn}/Gtk*.html) do Flag1=0 Flag2=0 Content="" while read do if [[ ${REPLY} =~ .*\>Style\ Property\ Details\<.* ]] then Flag1=1 FileIn=`basename ${FileIn}` && WidgetName=${FileIn::(-5)} echo "<h3>${WidgetName}</h3>" >> ${PathOut}/${FileOut} continue fi if [[ ${Flag1} -eq 1 ]] then if [[ ${REPLY} =~ .*class=\"refsect2.* ]] then Flag2=1 Content="${REPLY}" continue fi if [[ ${Flag2} -eq 1 ]] then Content="${Content}\n${REPLY}" if [[ ${REPLY} =~ .*\</div.* ]] then Flag2=0 echo -e "${Content}" >> ${PathOut}/${FileOut} Content="" continue fi if [[ ${REPLY} =~ .*been\ deprecated.* ]] then Flag2=0 Content="" continue fi fi if [[ ${REPLY} =~ .*class=\"refsect1.* || ${REPLY} =~ .*class=\"footer.* ]] then echo "<hr>" >> ${PathOut}/${FileOut} break fi fi done < ${FileIn} done echo '</body>' >> ${PathOut}/${FileOut} echo '</html>' >> ${PathOut}/${FileOut} exit