iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 13
1

前言

Day10Day11 中我們使用了 Go 提供的 os.Setenvos.Unsetenvos.ExpandEnv 完成存取環境變數,因為 環境變數是系統提供的功能 ,所以系統會提供這三個 System Call

alias 也是類似的做法,但因為 alias 不是系統的功能,所以系統不會提供類似的 SetAliasUnsetAliasExpandAlias 給我們用,這些都要自己實作才行,今天就要使用 Map 來實作這三個 function

Alias Table

為了要做到把 gst 替換成 git status,Shell 必須自己維護一個 Alias Table 來記錄指令間的對應關係,如下圖 gst 對應到 git statusla 對應到 ls -la

如果使用者下 ls -hexpandAlias 就要負責把 ls 展開成 ls -l,所以最後會變成 ls -l -h

實作

如果對於 Map 的語法不太熟悉的話,建議先到我去年的 Day06-Go 語法 II 了解一下 Map,才能看懂下面的實作

set & unset

// 初始化一個空的 alias table
// 型別是 string 對應到 string
var aliasTable = map[string]string{}

func setAlias(key, value string) {
    // 把 key 跟對應的 value 丟到 alias table 裡面去
    // Ex: aliasTable["ls"] = "ls -l"
    aliasTable[key] = value
}

func unsetAlias(key string) {
    // 把 table 中的某個 key 刪掉
    // Ex: delete(aliasTable, "ls")
    delete(aliasTable, key)
}

expandAlias

func expandAlias(input string) string {
    // 把 input 的指令跟參數切開
    // input = "ls -h"
    // args = ["ls", "-h"]
    args := strings.SplitN(input, " ", 2)
    
    // 拿出指令部分,cmd = "ls"
    cmd := args[0]

    // 如果這個指令有在 alias table 裡面
    // 就會得到一個 expandedCmd(展開過後的指令) 
    // 再用新的指令取代舊的指令
    if expandedCmd, ok := aliasTable[cmd]; ok {
        // cmd = "ls"  ->  expandedCmd = "ls -l"
        // 把第一個出現的 "ls" 替換成 "ls -l" 就大功告成了
        return strings.Replace(input, cmd, expandedCmd, 1)
    }

    // 如果指令不在 alias table 裡面
    // 就什麼都不做,回傳原本的 input
    return input
}

測試

因為今天也沒有可以 Demo 的新 feature,所以寫個測試來測一下 expandAlias 有沒有正常運作

// alias_test.go

func TestExpandAlias(t *testing.T) {
    // case1: 試試看 "ls -h" 有沒有被展開成 "ls -l -h"
    setAlias("ls", "ls -l")
    input, ans := "ls -h", "ls -l -h"

    if expandAlias(input) != ans {
        t.Fail()
    }

    // case2: 試試看 "gst" 有沒有被展開成 "git status"
    setAlias("gst", "git status")
    input, ans = "gst", "git status"

    if expandAlias(input) != ans {
        t.Fail()
    }
}

看起來是沒什麼問題呢 ?

小結

View commit on Github

今天寫的扣也滿多的,而且 expandAlias 的邏輯有點複雜,對 Go 不太熟的人可能要花點時間看。如果有什麼問題的話歡迎在下方提問,沒問題的話就明天見囉


上一篇
Day12-alias 指令別名(一)
下一篇
Day14-alias 指令別名(三)
系列文
Gosh!原來用 Go 寫一個 Unix Shell 這麼簡單30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言