🔬 Nghiên cứu 🌱 Mới trồng 31 tháng 7, 2026 Trồng 31 thg 7

peterh/liner

📦 peterh/liner ⭐ 1.1k Mở trên GitHub ↗

peterh/liner là thư viện Go cung cấp line editor cho CLI: nhập lệnh tương tác, history, auto-completion và xử lý phím giống readline / linenoise . Phù hợp khi cần nâng cấp UX cho công cụ terminal viết…

Kết luận: partial · Công nghệ: go · cli · line-editor · readline · terminal-ui

peterh/liner là thư viện Go cung cấp line editor cho CLI: nhập lệnh tương tác, history, auto-completion và xử lý phím giống readline/linenoise. Phù hợp khi cần nâng cấp UX cho công cụ terminal viết bằng Go mà không phải tự xử lý raw input; dự án đã có ~1.1k stars nên đủ tin cậy để dùng ngay ở mức utility library.

📖 Giới thiệu chi tiết

🧩 Nó là gì?

peterh/liner là một thư viện Go giúp bạn tạo ô nhập lệnh tương tác trong terminal, giống kiểu người dùng gõ lệnh trong shell. Nó hỗ trợ chỉnh sửa dòng đang nhập, lưu lịch sử nhập, gợi ý tự động và chạy được đa nền tảng.

🎯 Giải quyết vấn đề gì? Dành cho ai?

Khi viết công cụ CLI bằng Go, nếu chỉ dùng fmt.Scanln hoặc đọc input thủ công, trải nghiệm nhập liệu thường khá “thô”: không có lịch sử, không dùng phím mũi tên tốt, không có gợi ý, khó xử lý Ctrl-C.

peterh/liner giải quyết phần đó cho bạn.

Dự án này phù hợp với:

  • Người viết CLI bằng Go cần prompt tương tác, ví dụ: console quản trị, REPL, shell nhỏ, công cụ nội bộ.
  • Người muốn có trải nghiệm gần giống readline hoặc linenoise nhưng dùng thư viện thuần Go.
  • Dự án cần build đa nền tảng, kể cả Unix-like và Windows.
  • Người không muốn tự xử lý raw terminal input, phím đặc biệt, history và completion.

⚙️ Hoạt động ra sao?

  • liner.NewLiner() tạo một line editor, tức là bộ xử lý nhập một dòng trong terminal.
  • Prompt("...") hiển thị câu hỏi hoặc dấu nhắc, rồi chờ người dùng nhập.
  • Người dùng có thể dùng các phím quen thuộc như Left, Right, Home, End, Backspace, Ctrl-A, Ctrl-E, Ctrl-R.
  • History cho phép lưu và đọc lại các dòng đã nhập trước đó, thường bằng phím UpDown.
  • Completion cho phép gợi ý khi người dùng nhấn Tab.
  • SetCompleter nhận một hàm tự viết để quyết định danh sách gợi ý.
  • AppendHistory thêm dòng vừa nhập vào lịch sử.
  • ReadHistoryWriteHistory giúp đọc/ghi lịch sử từ file.
  • Thư viện được viết bằng pure Go, nghĩa là không cần cgo, dễ cross-compile sang nhiều hệ điều hành.

🆚 Khi nào nên dùng / không nên

Nên dùng peterh/liner khi:

  • Bạn viết ứng dụng terminal bằng Go và muốn người dùng nhập lệnh thoải mái hơn.
  • Bạn cần history, auto-completion, xử lý phím mũi tên, Ctrl-C, Ctrl-D.
  • Bạn muốn một thư viện gọn, thực dụng, dễ nhúng vào dự án.
  • Bạn cần chạy đa nền tảng mà không muốn phụ thuộc vào thư viện C.

Không nên dùng khi:

  • CLI của bạn chỉ nhận tham số qua command line, ví dụ mytool --name bob, không cần nhập tương tác.
  • Bạn cần giao diện terminal phức tạp kiểu full-screen UI, nhiều panel, bảng, form; khi đó nên xem các thư viện TUI khác.
  • Bạn cần đầy đủ mọi hành vi nâng cao giống GNU readline; liner cố tình bỏ một số tính năng chỉ có trên vài nền tảng để giữ hành vi nhất quán.

So sánh nhanh:

  • fmt.Scanln: đơn giản hơn, nhưng gần như không có trải nghiệm chỉnh sửa dòng.
  • readline: mạnh và quen thuộc, nhưng có thể kéo theo phụ thuộc nền tảng hoặc thư viện C.
  • linenoise: nhẹ, là nguồn cảm hứng của liner, nhưng peterh/liner được viết cho Go và tiện dùng trực tiếp trong dự án Go.

🚀 Bắt đầu nhanh

Cài thư viện:

go get github.com/peterh/liner

Ví dụ tối thiểu:

package main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"

	"github.com/peterh/liner"
)

var (
	historyFile = filepath.Join(os.TempDir(), ".liner_example_history")
	names       = []string{"john", "james", "mary", "nancy"}
)

func main() {
	line := liner.NewLiner()
	defer line.Close()

	line.SetCtrlCAborts(true)

	line.SetCompleter(func(input string) []string {
		var suggestions []string

		for _, name := range names {
			if strings.HasPrefix(name, strings.ToLower(input)) {
				suggestions = append(suggestions, name)
			}
		}

		return suggestions
	})

	if file, err := os.Open(historyFile); err == nil {
		line.ReadHistory(file)
		file.Close()
	}

	input, err := line.Prompt("What is your name? ")
	if err == nil {
		fmt.Println("Hello,", input)
		line.AppendHistory(input)
	} else if err == liner.ErrPromptAborted {
		log.Println("Aborted")
	} else {
	 log.Println("Error reading line:", err)
	}

	if file, err := os.Create(historyFile); err == nil {
		line.WriteHistory(file)
		file.Close()
	}
}

Chạy thử:

go run main.go

Khi chạy, bạn có thể:

  • Nhập tên rồi nhấn Enter.
  • Nhấn Tab để thử gợi ý từ danh sách john, james, mary, nancy.
  • Dùng phím Up để lấy lại lịch sử đã nhập.
  • Nhấn Ctrl-C để hủy prompt nếu đã bật SetCtrlCAborts(true).

✅ Điểm mạnh & ⚠️ Hạn chế

✅ Điểm mạnh:

  • Thuần Go, không cần cgo, dễ build và cross-compile.
  • Có sẵn history, auto-completion và nhiều phím chỉnh sửa dòng quen thuộc.
  • Hỗ trợ cả Unix-like và Windows.
  • Dễ tích hợp vào CLI Go hiện có.
  • Phù hợp để nâng cấp trải nghiệm nhập liệu mà không phải tự xử lý terminal phức tạp.
  • Dự án có khoảng 1.1k stars, đủ tin cậy để dùng như một utility library.

⚠️ Hạn chế:

  • Không phải thư viện dựng giao diện terminal đầy đủ.
  • Một số tính năng đặc thù nền tảng bị bỏ qua để giữ hành vi nhất quán.
  • Không nhằm thay thế hoàn toàn GNU readline trong các ca sử dụng rất nâng cao.
  • Bạn vẫn cần tự thiết kế logic lệnh, parse input và xử lý nghiệp vụ của ứng dụng.