Quantcast
Channel: 簡睿隨筆
Viewing all articles
Browse latest Browse all 897

打破Windows與UNIX的藩籬:nyagos-介於UNIX跟DOS之間的混血的CommandLine Shell

$
0
0

經常透過Windows命令提示字元(cmd.exe)操作Windows命令時,可以安裝clink來擴充命令編輯功能以達到與Linux BASH相同的操作方法,但因為clink是採用「注入cmd.exe」的方法來達到擴充目的,會安裝一些DLL到系統裡,並且會變更登錄(Registry),因此我不是太喜歡使用它。

最近發現了來自日本的nyagos,不僅功能類似、不需要安裝DLL也不會動到登錄,也能使用Lua來擴充自訂功能,使用起來非常簡便,而且原有的內部命令、批次檔也都能繼續使用。如果你也習慣命令行操作的話,強力推薦試試nyagos。

[!tip] What is nyagos?

  • nyagos是 Nihongo Yet Another GOing Shell 的縮寫
  • "NYAGOS - The hybrid Commandline Shell between UNIX & DOS"
  • 最早的Release日期是2014/09/27,目前版本是4.4.15_0
  • 1.0到3.x以C++撰寫(NAYOS,「にゃおす」と発音する),4.0開始用Go語言撰寫(NYAGOS,多了一個G)

1. 安裝

  • https://github.com/nyaosorg/nyagos/releases 下載.zip檔後解壓縮
  • 執行 安裝資料夾\makeicon.cmd,會以PowerShell在桌面新增圖示並設定啟動熱鍵Ctrl+Alt+N
  • 預設設定檔:C:\Users\使用者\.nyagos,是Lua語言的腳本檔
  • 建議移除C:\Users\使用者\.nyagos而直接使用安裝資料夾裡的.nyagos檔案,修改前先備份(可攜性考量)

1.1. 啟動執行順序

  1. nyagos安裝資料夾\.nyagos (lua-script)
  2. nyagos安裝資料夾\nyagos.d\*.lua (lua-script)
  3. %USERPROFILE%\.nyagos (lua-script)
  4. %APPDATA%\NYAOS_ORG\nyagos.d\*.lua (lua-script)

2. 用法示範

2.1. ls (list)

  • 參考:ls--option-files

    ls test*
    ls -a -ltr
    c:\util\npp\notepad++ $(ls test*)
    c:\util\npp\notepad++ `ls test*`
    emeditor $(ls test* | fzf -m)
    cd `ls -d | box`
  • lsll定義在 安裝資料夾\nyagos\nyagos.d\aliases.lua

  • 如果沒寫過Lua的話,可閱讀安裝資料夾\nyagos\nyagos.d\*.lua體驗一下

  • box是nyagos的內建命令,可建立選單

2.2. 自訂代名

  • 建立腳本檔 安裝資料夾\nyagos\nyagos.d\my_aliases.lua,內容如下:
nyagos.alias.cat="type"
nyagos.alias["cd.."]="cd .."
nyagos.alias["cd..."]="cd ../.."
nyagos.alias["cd2"]="cd ../.."
nyagos.alias["cd3"]="cd ../../.."
nyagos.alias["cd?"]="cd ?"

if nyagos.env.OS == "Windows_NT" then
  -- 由舊到新排序
  nyagos.alias.ll="__ls__ -olFh -ltr $*"
end

2.3. 變更提示字串

  • 建立腳本檔 安裝資料夾\nyagos\nyagos.d\my_prompt.lua,內容如下
  • 若為Git工作目錄則再輸出分支名稱

gh|700

-- Source: https://qiita.com/suisui/items/b6469ce91f01a83b599b
-- Reference: [【NYAGOS】プロンプトで使える特殊文字と ANSI エスケープシーケンスを Lua でラップする - Tumbling Dice](https://outofmem.hatenablog.com/entry/2016/01/27/014920)
share.org_prompter = nyagos.prompt
nyagos.prompt = function(this)
  local oPrompt = share.prompt
  local oEsc = share.escape_sequence

  -- add dir name (with drive letter)
  -- bg.default (=49) だけでいい気もしますが、追加で bg.trans (=60) も足してます
  local sEscStart = oEsc.create_sequence(oEsc.bg.default, oEsc.bg.trans)
  local sEscEnd = oEsc.create_sequence(oEsc.fg.white, oEsc.bg.trans)
  --print("sEscStart=" .. sEscStart)
  --print("sEscEnd=" .. sEscEnd)
  local prompt_message = string.format('%s[%s]%s', sEscStart, oPrompt.path, sEscEnd)

  -- check git branch
  local sGitBranchName = nyagos.eval('git rev-parse --abbrev-ref HEAD 2>nul')
  --print("branch=" .. sGitBranchName)

  if (sGitBranchName ~= '') then
    -- add git branch name
    sEscStart = oEsc.create_sequence(oEsc.fg.red, oEsc.bg.trans)
    sEscEnd = oEsc.create_sequence(oEsc.fg.default, oEsc.bg.trans)
    --print("sEscStart=" .. sEscStart)
    --print("sEscEnd=" .. sEscEnd)

    prompt_message = string.format(prompt_message .. ' [%s%s%s]', sEscStart, sGitBranchName, sEscEnd)
  end

  -- add line break
  prompt_message = prompt_message .. " "  -- oPrompt.crlf

  -- add dollar
  prompt_message = prompt_message .. oPrompt.dollar .. ' '

  return share.org_prompter(prompt_message)
end

share.prompt = {
  eq = '$q', -- equal '='
  dollar = '$$', -- dollar '$'
  time = '$t', -- current time
  date = '$d', -- current date
  path = '$p', -- current path (with drive letter)
  ver = '$v', -- windows version
  drive = '$n', -- current drive letter
  gt = '$g', -- greater than '>'
  lt = '$l', -- less than '<'
  pipe = '$b', -- pipe '|'
  crlf = '$_', -- line break
  esc = '$e', -- escape
  bs = '$h', -- backspace
  amp = '$a', -- ampersand '&'
  l_par = '$c', -- left parenthesis '('
  r_par = '$f', -- right parenthesis ')'
  space = '$s' -- space
}

share.escape_sequence = {
  -- attribute
  attr = {
    off = '0',
    bold = '1',
    bold_off = '21',
    underline = '4',
    underline_off = '24',
    blink = '5',
    blink_off = '25'
  },

  -- foreground
  fg = {
    black = '30',
    red = '31',
    green = '32',
    yellow = '33',
    blue = '34',
    magenta = '35',
    cyan = '36',
    white = '37',
    default = '39',
    -- prefix 'l' is 'Light'
    l_gray = '90',
    l_red = '91',
    l_green = '92',
    l_yellow = '93',
    l_blue = '94',
    l_magenta = '95',
    l_cyan = '96',
    l_white = '97'
  },

  -- background
  bg = {
    black = '40',
    red = '41',
    green = '42',
    yellow = '43',
    blue = '44',
    magenta = '45',
    cyan = '46',
    white = '47',
    default = '49',
    trans = '60',
    -- prefix 'l' is 'Light'
    l_gray = '100',
    l_red = '101',
    l_green = '102',
    l_yellow = '103',
    l_blue = '104',
    l_magenta = '105',
    l_cyan = '106',
    l_white = '107'
  },

  -- create_sequence(fg, bg, attr) 參數順序不必固定
  create_sequence = function(...)
    local prompt = share.prompt
    local attrs = {...}
    local joined_attrs = ''

    for n, v in pairs(attrs) do
      local val = tostring(v)
      if val ~= nil then
        joined_attrs = joined_attrs ~= '' and joined_attrs .. ';' .. val or val
      end
    end
    return string.format('%s[%sm', prompt.esc, joined_attrs)
  end
}

2.4. 快速切換目錄

  • z 資料夾部份字串快速切換目錄(jump)
  • 安裝 zoxide
  • 變更目錄的歷程在cd命令執行時以nyagos.postexechook()調用 zoxide 寫入,再新增 z 代名查詢後快速切換
  • 建立腳本檔 安裝資料夾\nyagos\nyagos.d\my_z.lua,內容如下
-- source: [nyagos增加zoxide的支持 – wentao's blog](https://wentao.org/post/2023-04-27-zoxide-with-nyagos/)
-- 2024/04/09 Jerry modified no args handling.
-- [ajeetdsouza/zoxide: A smarter cd command. Supports all major shells.](https://github.com/ajeetdsouza/zoxide)
nyagos.alias.z = function (args)
  local path
  if (#args >= 1) then
    local rest = args[1]
    path = rest
    path = nyagos.eval("zoxide query --exclude '".. (nyagos.getwd()) .."' -- " .. rest)
  else
    path = nyagos.eval("zoxide query -i")
  end
  nyagos.chdir(path)
end
nyagos.alias.zi=function(args)
  if (#args == 0) then
    print("zi need a path.")
    return
  end

  local rest = args[1]
  path = nyagos.eval("zoxide query -- " .. rest .. "| fzf" )
  nyagos.chdir(path)
end

-- 利用 postexechook 功能,实现了自动更新 zoxide 数据.
-- 另有 nyagos.preexechook
nyagos.postexechook = function(args)
  if "cd" == args[1] then
      nyagos.eval("zoxide add -- " .. nyagos.getwd())
  end
end

▼ 使用 z 範例

rem z 顯示目錄歷程選單,可用上下鍵移動,也可輸入過濾文字
z
z test

gh|700

2.5. 執行命令歷史

rem 預設顯示最後10個命令
history
rem 再執行第123個命令
!123

修改腳本檔 安裝資料夾\nyagos\nyagos.d\my_aliases.lua加入自訂代名hist,不傳參數預設顯示20筆資料:

nyagos.alias.hist=function(args)
  if (#args <= 0) then 
    iCount = 20
  else
    -- print("args=" .. args[1])
    iCount = args[1]
  end
  nyagos.exec("history " .. iCount)
end

2.6. 自動補全

  • 安裝資料夾\nyagos\nyagos.d\catalog\git.lua複製到安裝資料夾\nyagos\nyagos.d\
  • 安裝資料夾\nyagos\nyagos.d\catalog\subcomplete.lua複製到安裝資料夾\nyagos\
  • 在命令行輸入 git re Tab即會出現Git re開頭的命令

2.7. 選單熱鍵

  • 安裝資料夾\nyagos\nyagos.d\box.lua提供下列熱鍵:
按鍵 功能
Ctrl+O 當前資料夾檔案選單
Ctrl+X r: 命令歷史選單
h: cd歷史選單
g: Git log選單
Alt+R 命令歷史選單。命令含有空白會加雙引號
Alt+H cd歷史選單
Alt+G Git log選單
Alt+O 取回.lnk捷徑的原有路徑
  • 建立捷徑
    lnk 目錄或含路徑檔名 存放的.lnk檔
    lnk c:/util/nyagos\nyagos.d j:/test/nyad.lnk
    cd j:/test/nyad.lnk

2.8. foreach

cd /d j:/test/nyagos
foreach f *.txt ; echo move %f% %f:txt=ttt% ; end

gh|700

3. 問題

3.1. bindkey

想將 Ctrl+End設定成刪除游標右側文字(如Ctrl+K ),但似乎無法達成。

3.2. 控制台檔案

例如main.cplncpa.cpl等控制台檔案皆無法以openstart開啟,最後以批次檔解決:

@echo off
if "%1"=="net" ncpa.cpl
if "%1"=="fire" Firewall.cpl
if not "%1"=="" %1.cpl
if "%1"=="" dir /w c:\windows\system32\*.cpl

3.3. Microsoft Configuration (.msc)

services.msc之類的.msc檔案無法直接啟動,必須以open services.mscstart services.msc才能執行。
.msc其實是Windows的可執行檔,不加.msc的話可以直接執行,但加了.msc時nyagos無法啟動。

新增下列代名以比照cmd.exe的執行方式:

nyagos.alias.svc="start services.msc"
nyagos.alias["appwiz.cpl"]="cpl appwiz"
nyagos.alias["services.msc"]="start services.msc"

也可修改安裝資料夾\nyagos\nyagos.d\suffix.lua讓nyagos知道如何執行.msc檔案:

for key,val in pairs{
    awk={"gawk","-f"},
    js={"cscript","//nologo"},
    lua={"nyagos.exe","--norc","--lua-file"},
    pl={"perl"},
    ps1={"powershell","-ExecutionPolicy","RemoteSigned","-file"},
    rb={"ruby"},
    vbs={"cscript","//nologo"},
    wsf={"cscript","//nologo"},
    py={"python"},
    msc={"open"},
} do
    share._setsuffix( key , val )
end

4. 💡 相關鏈接

✅ nyaosorg/nyagos: NYAGOS - The hybrid Commandline Shell between UNIX & DOS
✅ zoxide手冊: zoxide man | Linux Command Library
✅參考 clink:擴充cmd.exe成為Bash readline命令行的強大編輯功能 – 簡睿隨筆
✅參考 【NYAGOS】プロンプトで使える特殊文字と ANSI エスケープシーケンスを Lua でラップする - Tumbling Dice
✅ 參考:nyagos增加zoxide的支持 – wentao's blog

5. 教學影片

##

您可能也會有興趣的類似文章


Viewing all articles
Browse latest Browse all 897

Trending Articles