1 điểm bởi GN⁺ 3 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Emacs không hẳn là bản thân hệ điều hành, mà điều phối các ứng dụng và tiện ích trên kernel, đồng thời tận dụng hệ thống tệp, mạng và các chương trình bên ngoài để trở thành client của nhiều dịch vụ khác nhau
  • Có thể xây dựng UI, tầng giao tiếp và kho dữ liệu cục bộ cần cho client bằng các thư viện tích hợp như minibuffer, buffer, URL, TCP/UDP, JSON, SQLite
  • Emacs Lisp (Elisp), một ngôn ngữ động, kết hợp các hàm Elisp và lệnh shell trong lúc chạy, linh hoạt điều phối những chức năng mà Emacs có thể truy cập
  • Lệnh ví dụ wttr nhận vị trí, gửi yêu cầu HTTP đến wttr.in, trích xuất khu vực, nhiệt độ và thời tiết từ JSON, hiển thị trong minibuffer rồi lưu cả vào kill ring
  • Toàn bộ wttr.el dài 67 dòng theo cloc; nếu giao việc yêu cầu mạng và xử lý JSON cho công cụ dòng lệnh như Python, cũng có thể tạo một client Elisp ngắn hơn xem chính lệnh shell như một dịch vụ

Emacs điều phối dịch vụ trên hệ điều hành

  • Gọi Emacs là hệ điều hành không thật chính xác, nhưng phép so sánh này xuất phát từ khả năng điều phối ứng dụng và tiện ích trên kernel của hệ điều hành
  • Vì có thể truy cập các dịch vụ hệ điều hành như hệ thống tệp và mạng bằng chức năng tích hợp, cũng như chạy các chương trình khác, nên rất dễ cấu hình nhanh hành vi client bên trong Emacs
  • Do có thể xử lý nhiều tác vụ điện toán bằng nhiều chế độ client, ý tưởng người dùng “sống hoàn toàn trong Emacs” cũng có cơ sở

Mô hình client-server nhìn từ yêu cầu và phản hồi

  • Mô hình client-server là một mẫu tương tác phân chia công việc giữa dịch vụ cung cấp tài nguyên và client yêu cầu tài nguyên đó
    • Client gửi yêu cầu
    • Server xử lý yêu cầu rồi trả về phản hồi
  • Giao dịch gồm yêu cầu và phản hồi có thể diễn ra qua mạng hoặc cục bộ trong một hệ thống
  • Mô hình dựa trên mạng đã phát triển rộng rãi trong kiến trúc phần mềm phong cách REST

Ba phần tạo nên một client Emacs

  • Một client thông thường đảm nhiệm ba phần sau
    • UI: Xử lý đầu vào và đầu ra của người dùng khi cần
    • Ranh giới client (Client Edge): Giao tiếp với dịch vụ; trong client mạng, hệ thống con mạng đảm nhận vai trò này
    • Cơ sở dữ liệu cục bộ: Biểu diễn dữ liệu sẽ trao đổi hoặc đồng bộ với server; cách quản lý cụ thể thay đổi tùy yêu cầu triển khai
  • Xây dựng giao diện người dùng

  • Giao tiếp dịch vụ và chuyển đổi dữ liệu

    • Với ranh giới client kết nối đến dịch vụ, có thể tận dụng các chức năng sau
    • Với tuần tự hóa và giải tuần tự hóa, dùng các parser tích hợp
  • Quản lý dữ liệu cục bộ

    • Có thể dùng các collection của Elisp để biểu diễn cục bộ dữ liệu server
    • Nếu cần lưu trữ cục bộ bền vững, có thể dùng SQLite
    • Độ phức tạp của client thực tế thay đổi theo yêu cầu; nếu đã có tiện ích dòng lệnh sẵn có phụ trách xử lý nặng, có thể tái cấu trúc nó thành dịch vụ được truy cập bằng lời gọi shell

Cách kết hợp chức năng bằng Elisp

  • Tất cả các thư viện phía trên đều có thể được truy cập từ Emacs Lisp (Elisp)
  • Elisp là ngôn ngữ lập trình động cho phép cấu hình ứng biến ở mức cao trong lúc chạy
  • Có thể điều phối các luồng phức tạp bằng cách kết hợp những hành vi Emacs có thể dùng, từ hàm Elisp đến lệnh shell

Triển khai client thời tiết wttr.in

  • wttr.in là dịch vụ web dự báo thời tiết hướng đến console và hỗ trợ xuất JSON
  • Lệnh wttr cho Emacs hoạt động theo trình tự sau
    1. Nhận vị trí từ người dùng
    2. Tạo URL yêu cầu wttr.in
    3. Gửi yêu cầu HTTP
    4. Xử lý phản hồi JSON
    5. Hiển thị kết quả trong minibuffer và lưu vào kill ring
    6. Nếu có lỗi trong quá trình xử lý, hiển thị thông báo lỗi trong minibuffer
  • Tạo URL yêu cầu

    • wttr--request-url dùng https://wttr.in làm URL cơ sở
    • Thay khoảng trắng trong vị trí đã nhập bằng + và tạo truy vấn dạng /<location>?0&format=j1
    • URL hoàn chỉnh sau đó được chuyển cho hàm lấy JSON
  • Yêu cầu HTTP và phân tích JSON

    • fetch-json-as-hash-table lấy URL một cách đồng bộ bằng url-retrieve-synchronously
    • Nếu không nhận được dữ liệu, nó phát sinh lỗi Failed to fetch data from <URL>
    • Trong buffer phản hồi, sau khi di chuyển qua phần header siêu dữ liệu HTTP, nó dùng json-parse-buffer để chuyển phần nội dung còn lại thành hash-table của Elisp
    • Khi xử lý xong, buffer mạng đã tải xuống luôn được xóa để tránh rò rỉ bộ nhớ
  • Ghép thông điệp thời tiết

    • wttr--report-message trích xuất các giá trị sau từ dữ liệu JSON
      • Tên khu vực gần nhất
      • Vùng
      • Quốc gia
      • Nhiệt độ Celsius hiện tại temp_C
      • Nhiệt độ Fahrenheit hiện tại temp_F
      • Mô tả thời tiết weatherDesc
    • Nối các thành phần vị trí không rỗng bằng dấu phẩy và tạo kết quả theo định dạng vị trí: Celsius, Fahrenheit mô tả thời tiết
    • Có thể xem toàn bộ phần triển khai trong mã nguồn wttr.el

Tận dụng cả công cụ dòng lệnh như dịch vụ

  • API của Emacs cung cấp mức trừu tượng cao, và ngay cả wttr.el tự triển khai yêu cầu HTTP và xử lý JSON cũng chỉ dài 67 dòng theo phép đo cloc
  • Một lựa chọn đơn giản hơn là giao yêu cầu mạng thực tế và xử lý JSON cho một script Python tên weather
    • Lệnh weather của Elisp nhận vị trí từ người dùng
    • Gắn vị trí làm đối số để tạo lệnh shell weather
    • Chạy lệnh bằng shell-command-to-string
    • Lưu kết quả trả về vào kill ring và hiển thị trong minibuffer
  • Trong cấu hình này, lệnh shell trở thành dịch vụ nhận yêu cầu, còn hàm Elisp đóng vai trò client
  • Nhờ đặc tính động của Elisp, có thể kết hợp các thư viện Elisp và tiện ích dòng lệnh khi cần; chính khả năng tích hợp này giúp có thể xem mọi thứ trong Emacs như một dịch vụ

1 bình luận

 
Ý kiến trên Hacker News
  • Emacs chỉ trông giống như một hệ điều hành vì dòng Lisp Machine đã không trở thành xu hướng chủ đạo
    “Symbolics Lisp Machine demo”
    https://www.youtube.com/watch?v=o4-YnLpLgtk
    “Emacs and Lisp”
    https://funcall.blogspot.com/2025/04/emacs-and-lisp.html
    Lucid đã fork Emacs thành XEmacs để cố triển khai một trong những ý tưởng LSP ban đầu, và phần lớn các tính năng khi đó nay đã được tích hợp trở lại vào Emacs
    https://dreamsongs.com/Cadillac.html
    “Lucid Energize Demo”
    https://www.youtube.com/watch?v=pQQTScuApWk

    • Hệ điều hành là một máy ảo được tạo ra để nhiều chương trình cùng chia sẻ. Thường thì nó phơi bày phần lớn kiến trúc tập lệnh (ISA) mà nó chạy trên đó, nhưng cũng có các ngoại lệ như Inferno, Taos, AS/400
    • Ngay cả khi LISP machine thành công, trình soạn thảo chạy trên đó cũng không trở thành hệ điều hành. Nếu nhầm lẫn giữa nền tảng và hệ điều hành, ta có thể gọi cả trình duyệt web, thậm chí Roblox, là hệ điều hành
  • Nếu định nghĩa client, server, request đủ rộng, bất cứ thứ gì cũng có thể bị ép vào kiến trúc client/server. Điều này giống như việc cố gắng lập luận rằng Emacs tuân theo triết lý Unix chỉ vì hàm LISP làm tốt một việc
    Hầu hết mọi người có thể đồng ý rằng Emacs đi theo ý tưởng của LISP machine, và trên đó về cơ bản có thể triển khai bất cứ thứ gì bạn muốn. Nó tích hợp rất tốt với các công cụ CLI, nhưng không rõ ta được gì khi định nghĩa điều đó là client/server
    Trong nhiều thập kỷ, nó đã hấp thụ tính năng qua nhiều trào lưu khác nhau, và bên trong còn có bộ máy phân tích ngữ nghĩa CEDET hiện gần như không còn được dùng. Sau đó LSP xuất hiện, và giờ là thời đại agent; Emacs cũng khá ổn với vai trò front-end cho agent

    • Emacs là một người tị nạn LISP chạy sang thế giới Unix. Nó không theo triết lý Unix mà theo triết lý LISP, nhưng tích hợp tốt với Unix
    • Trước đây, việc hầu hết IDE có bộ máy phân tích ngữ nghĩa riêng là chuyện phổ biến. Tôi nhớ language server Java đầu tiên cũng được tách ra từ bộ máy phân tích ngữ nghĩa Java của Eclipse
  • Tôi đã dùng Emacs hơn 25 năm, nhưng công ty tôi chuyển sang năm ngoái không cho dùng Emacs, kể cả cho những công việc mà Emacs đặc biệt phù hợp. Lý do là mọi thành viên trong nhóm phải dùng cùng một công cụ, và tôi đã thất bại trong việc thuyết phục người khác chuyển sang Emacs
    Giờ tôi đang dùng các công cụ đơn mục đích riêng cho từng việc theo cách kém hiệu quả hơn nhiều, đồng thời còn phải liên tục học UI và key mapping mới

    • Khi công ty lớn lên, họ bắt đầu kiểm soát phần mềm được cài đặt, và có vẻ đang quản lý việc cho phép/chặn cài đặt bằng Microsoft Intune. Tôi thậm chí còn trì hoãn cập nhật hoặc thay laptop vì sợ không còn dùng được Emacs
      Quản lý có thể sẽ bảo mọi người dùng Visual Studio Code trong dự án mới, nhưng mô hình tiêu thụ đang dùng thì VSCode cũng không hỗ trợ. Miễn Git và quy trình triển khai khớp nhau, mỗi người nên được chọn trình soạn thảo mình dùng tốt; nhưng tôi đoán câu trả lời sẽ là vì đó là mã nguồn mở không được Microsoft hỗ trợ nên rủi ro, và là phần mềm chưa được công ty thẩm định
      Emacs là công cụ cốt lõi tôi dùng hằng ngày, nên nếu bị cấm tôi sẽ nghĩ đến chuyện nghỉ việc. Quản lý không cố hiểu hay phán xét theo logic, mà chỉ làm theo chỉ đạo từ một bộ phận IT khác
    • Nếu bắt mọi thành viên trong nhóm dùng telnet và cấm ssh, liệu như vậy cũng được coi là hợp lý sao? Điều quan trọng là đừng hỏi xin phép dùng Emacs, cứ dùng thôi
      Nếu công ty đã chỉ định trình soạn thảo văn bản đa dụng, cũng đáng kiểm tra xem chạy Notepad có bị coi là vấn đề không, và liệu họ có chỉ định cả công cụ quản lý việc cần làm cá nhân hay không. Hãy tìm một hạng mục mà Emacs có thể làm nhưng công ty chưa chỉ định công cụ, rồi cài nó cho mục đích đó
    • Lập luận đó giống như nói rằng để quản lý các kiểu tính cách khác nhau thì phải đối xử khác nhau với từng người, quá kém hiệu quả, nên đã thực hiện phẫu thuật cắt thùy trán cho toàn bộ thành viên nhóm
    • Nếu các công cụ khác cũng có mức tự do và khả năng tùy biến như Emacs, người dùng Emacs có lẽ đã không cố nhồi mọi công việc vào trong đó. Không hẳn Emacs luôn vượt trội, mà là các công cụ khác bị hạn chế hơn và thiếu khả năng tự ghi tài liệu
    • Tôi thắc mắc vì sao lập luận rằng mọi thành viên trong nhóm phải dùng cùng một công cụ lại hợp lý
  • Emacs là một nền tảng, và hệ điều hành cũng chỉ là một trong nhiều nền tảng. Nền tảng là một lớp phần mềm được thiết kế để có thể tạo ra thứ mới bên trên nó, nên cần hỏi nền tảng X nào phù hợp với Y mà ta muốn tạo
    Với tôi, X thường là Emacs, nhưng cũng có thể là Racket hoặc Rust. Nếu một công cụ vừa là ứng dụng vừa là nền tảng tốt, nó đáng để đầu tư học nhiều hơn một ứng dụng đơn thuần

  • Khoảnh khắc dùng Emacs đủ nhiều để hiểu câu “Emacs là một hệ điều hành” không phải như một trò đùa mà như một khái niệm thực sự có thể tin được đã trở thành bước ngoặt quan trọng trong sự nghiệp của tôi

    • Vốn đã có hệ điều hành và cũng đã có thể lập trình, nên tôi nghi ngờ liệu Emacs có thật sự đem lại năng lực mới không. Emacs là trình soạn thảo văn bản, không phải IDE hay môi trường chạy tự động hóa đa dụng; tôi khó hiểu lập luận rằng chỉ cần thêm Lisp vào MSPaint thì nó đột nhiên trở thành công cụ tuyệt vời
  • Tôi bắt đầu dùng Emacs vài năm trước để thử org mode, và tiếp tục dùng vì độ linh hoạt cực cao của nó

    • Tôi đã dùng Spacemacs một thời gian, nhưng giờ có Keychron G6 Pro có thể lập trình lại Caps Lock, nên tôi định nghiêm túc tự cấu hình init.el
  • Emacs gần với một môi trường lập trình có tích hợp trình soạn thảo văn bản hơn. Nếu xem nó tương tự một số image Smalltalk thì nó là một công cụ khá thú vị

  • Emacs không phải hệ điều hành mà gần với shell hơn, nhưng bản thân khái niệm shell lại không được hiểu rộng rãi

    • Nếu xem shell là phương tiện để dùng các công cụ khác, thì vi còn gần với shell hơn. Vì nhiều chức năng phải giao cho các chương trình Unix chuẩn khác thông qua :.!
      Ngược lại, Emacs giống hệ điều hành ở chỗ đưa đủ loại chức năng vào một bản phân phối khổng lồ duy nhất
  • Gần đây tôi tìm thấy một video nhập môn ngắn rất hợp để cho người không dùng Emacs xem
    https://www.youtube.com/watch?v=mJZDmO5yOxE

    • Tôi thật sự tò mò về init.el của Anon Emoose
  • Bản thân Emacs có thể chạy dưới dạng client và server. Sau khi khởi động server bằng emacs --daemon, kết nối bằng emacsclient thì mọi instance trên terminal và GUI đều dùng cùng một server, chia sẻ các file và buffer đang mở
    Đáng tiếc là nó chỉ hoạt động cục bộ; tôi đã thử chuyển tiếp socket server Emacs qua ssh để kết nối từ client từ xa nhưng thất bại

    • Nhìn lại thì cái tên emacsclient không hay lắm. Người lần đầu tiếp xúc với Emacs vào năm 2026 dễ kỳ vọng rằng nó đồng bộ trạng thái chạy của client và server qua mạng như một REST client
      Ở đây client và server nghĩa là cấu trúc trong đó client gửi các lệnh điều khiển đơn giản qua Unix local domain, tức socket hệ thống tệp. Về sau nó cũng hỗ trợ socket mạng, nhưng thứ client gửi vẫn chỉ là các lệnh điều khiển đơn giản
    • Không chuyển tiếp socket được, nhưng nếu dùng X11 thì có thể dùng ssh -X để hiển thị frame của Emacs từ xa lên X server cục bộ. Tuy nhiên, cần chú ý rằng với bản build GTK không phải PGTK, Emacs từ xa có thể bị crash khi đóng frame mới
    • Tôi tò mò liệu bạn đã kiểm tra nguyên nhân khiến chuyển tiếp socket thất bại chưa