1 điểm bởi GN⁺ 2024-05-13 | 1 bình luận | Chia sẻ qua WhatsApp
  • Quản lý cửa sổ trong Emacs dựa trên một cấu trúc linh hoạt tách biệt giữa buffer và window, nhưng các thao tác mặc định lại hơi thô, nên người dùng phải tự kết hợp công cụ và thói quen để tạo ra quy trình làm việc phù hợp
  • Trọng tâm của bài viết không phải là quy tắc display-buffer hay workspace dựa trên tab, mà là các thao tác thủ công trong một frame Emacs như di chuyển focus, sắp xếp buffer, chia/xóa cửa sổ và xử lý các tác vụ tạm thời
  • other-window, windmove, winum, ace-window, chuột, transpose-frame, window-prefix-map, other-window-prefix, winner-mode lần lượt đảm nhiệm việc di chuyển tuần hoàn, di chuyển theo hướng, chọn theo số, chọn bằng gợi ý, biến đổi bố cục và khôi phục
  • Kết hợp ace-window với Avy cho phép chọn một cửa sổ cụ thể rồi chạy lệnh, hoặc nhảy thẳng tới vị trí văn bản để giảm bớt chính việc chuyển cửa sổ
  • Quản lý cửa sổ trong Emacs gần với một bài toán còn bỏ ngỏ hơn là một hệ thống cố định phức tạp; display-buffer-alist, Popper·Popwin, thao tác cây cửa sổ và tích hợp với tiling WM đều rất mạnh, nhưng cũng tốn công cấu hình và vẫn có khoảng trống

Quản lý cửa sổ theo cách Emacs định nghĩa

  • Window trong Emacs là viewport hay panel bên trong một frame, còn buffer là một khối văn bản liên tục, có thể là nội dung tệp hoặc không
  • Nhiều IDE và trình biên tập gần như gộp chung khái niệm window và buffer để giảm gánh nặng nhận thức, nhưng Emacs tách hai khái niệm này ra để cho phép bố trí linh hoạt hơn
    • Xem cùng một tệp hai lần là việc rất đơn giản
    • Các buffer không tương ứng trực tiếp với tệp cũng có thể được xử lý tự nhiên
    • indirect buffers của Emacs gần giống với một bản sao “live” của toàn bộ buffer
  • Cấu trúc tách biệt này cũng tạo ra chi phí cho người mới
    • Phải đặt cửa sổ vào đúng vị trí mong muốn trong frame
    • Phải đưa đúng buffer vào đúng cửa sổ mong muốn
    • Ở giai đoạn đầu, gánh nặng thao tác thường lộ ra trước cả những lợi ích mà cấu trúc tách biệt mang lại

Những gì bài này không đề cập

  • Quy tắc hiển thị buffer tự động để kiểm soát hoàn toàn display-buffer không phải chủ đề trung tâm
  • Tab, workspace, cách ly buffer và duy trì phiên làm việc cũng nằm ngoài phạm vi chính
  • Các lựa chọn thay thế triệt để hoạt động như một window manager riêng bên trong Emacs cũng không nằm trong bài
    • Edwina áp đặt bố cục auto-tiling kiểu master-and-stack theo phong cách DWM
    • HyControl cung cấp bảng điều khiển hành động bố cục cửa sổ cùng các tính năng như hiển thị lưới đồng đều
  • Trọng tâm thực sự là các thao tác thủ công thường nhật
    • Chuyển focus giữa các cửa sổ
    • Di chuyển buffer giữa các cửa sổ
    • Chia và xóa cửa sổ
    • Kiểm soát cửa sổ đích khi hiển thị trong lúc chạy lệnh

Di chuyển cơ bản: other-window và “cửa sổ tiếp theo”

  • other-window là lệnh chuyển cửa sổ cơ bản được học trong hướng dẫn Emacs, với phím mặc định là C-x o
  • Thứ tự chọn nhìn chung xoay vòng theo chiều kim đồng hồ trong frame
    • Khi có ít cửa sổ, cách này đơn giản và đủ dùng
    • Càng nhiều cửa sổ, càng phải gọi lệnh nhiều lần để tới đúng vị trí mong muốn
  • Cũng có những cách điều chỉnh thực dụng
    • Có thể gán nó vào một phím dễ bấm hơn như M-o
    • Có thể dùng đối số số để nhảy qua nhiều bước hoặc di chuyển ngược chiều
    • Bật repeat-mode sẽ cho phép lặp như C-x o o o... hoặc M-o o o...
  • Nếu đặt tham số cửa sổ no-other-window, other-window sẽ bỏ qua một số cửa sổ nhất định
    • Đây là lý do các cửa sổ phụ kiểu trình quản lý tệp như dired-sidebar hay dirvish-side bị loại khỏi đối tượng của other-window
  • Khái niệm “cửa sổ tiếp theo” cũng là đích mặc định của các lệnh tác động lên cửa sổ khác, như scroll-other-window

Di chuyển theo hướng: windmove

  • windmove là một thư viện tích hợp sẵn để di chuyển focus cửa sổ theo hướng
    • Nó gần với cách di chuyển trái/phải/lên/xuống mà người dùng Vim mong đợi
    • Người dùng evil-mode cũng đang dùng Windmove ở bên trong
  • Có thể gán windmove-left, windmove-right, windmove-up, windmove-down vào WASD, HJKL, phím mũi tên, v.v.
  • Các lệnh windmove-swap-states-left/right/up/down dùng hướng để hoán đổi buffer giữa các cửa sổ
    • Khi đó focus sẽ di chuyển theo buffer
  • Cũng có thể xóa cửa sổ theo hướng bằng nhóm windmove-delete-*, nhưng phần dưới của bài viết sẽ bàn thêm những cách khác
  • Trong môi trường tiling WM, có thể tích hợp để dùng cùng một bộ phím di chuyển giữa cửa sổ nội bộ Emacs và cửa sổ hệ điều hành

Giao cửa sổ Emacs cho cửa sổ hệ điều hành quản lý

  • frames-only-mode mở mọi buffer thành frame mới thay vì dùng Emacs window, để window manager của hệ điều hành quản lý
  • Cách này đưa buffer Emacs lên cùng một tầng với cửa sổ hệ điều hành, giúp có thể quản lý cả hai bằng cùng một bộ phím
  • Các công cụ như Avy, winum, ace-window, scroll-other-window có thể áp dụng không chỉ cho window mà còn cho cả frame
  • Một số lệnh Emacs giả định rằng chúng có thể tùy ý chia frame, nên có thể phát sinh ngoại lệ
    • Đặc biệt các lệnh của org-mode có xu hướng như vậy
  • Chưa có trải nghiệm sử dụng frames-only-mode trên compositor Wayland

Chọn ngay bằng số và gợi ý

  • winum hiển thị số cửa sổ trên mode line và cho phép chọn cửa sổ bằng số
    • Nếu other-window gần với O(n) và windmove phụ thuộc vào cách bố trí không gian, thì winum gần với truy cập O(1) khi đã biết số
    • Nếu gọi lệnh chọn với đối số prefix âm thì cửa sổ tương ứng sẽ bị xóa
    • Khi minibuffer được kích hoạt, nó luôn nhận số 0
    • Hoạt động xuyên suốt các frame của Emacs
  • Phím mặc định C-x w <n> có thể khá dài, nên có ví dụ cấu hình dùng M-0 đến M-9 để chọn cửa sổ
  • ace-window được xem là công cụ mạnh mẽ để điều khiển cửa sổ Emacs bằng bàn phím
    • Hiển thị gợi ý trên từng cửa sổ và chọn bằng cách nhấn phím tương ứng
    • Nếu bật ace-window-display-mode thì có thể luôn hiển thị gợi ý trên mode line như winum
    • Nhấn ? sẽ mở menu dispatch
  • Điểm mạnh của ace-window không chỉ là chọn đơn thuần mà là chọn cửa sổ rồi thực hiện hành động
    • Xóa cửa sổ
    • Di chuyển và hoán đổi cửa sổ
    • Chia cửa sổ
    • Hiển thị buffer cụ thể
    • Áp dụng thao tác lên cửa sổ khác mà không rời khỏi cửa sổ đang chọn

Chuột và chuyển đổi bố cục

  • Trong Emacs, chuột rất phù hợp một cách tự nhiên cho việc chọn cửa sổ, thay đổi kích thước, menu ngữ cảnh và kéo thả
    • context-menu-mode và thanh menu giúp tăng khả năng khám phá
  • Nếu tay đã rời khỏi bàn phím thì thao tác Emacs bằng chuột có thể là con đường ít cản trở nhất
  • Cũng có những thao tác thực hiện được bằng cử chỉ chuột
    • Chia frame theo chiều dọc hoặc chiều ngang
    • Xóa cửa sổ
    • Luân chuyển các buffer trong cửa sổ
    • Hoán đổi cửa sổ sang phải hoặc trái
    • Chuyển đổi giữa hai buffer gần nhất trong một cửa sổ
  • Có thể bật hành vi focus-follows-mouse bằng cách thiết lập mouse-autoselect-window
  • transpose-frame cung cấp các lệnh xoay hoặc lật bố cục cửa sổ của frame
    • rotate-frame, flip-frame, flop-frame được xem là những lệnh thường đáng dùng
    • Bản thân transpose-frame là phép chuyển vị theo đường chéo chính nên được đánh giá là ít hữu dụng trong thực tế

window-prefix-map và cây cửa sổ

  • window-prefix-map là tập hợp lệnh quản lý cửa sổ được gắn với phím mặc định C-x w của Emacs
  • split-root-window-rightsplit-root-window-below chia cửa sổ gốc của frame
    • Được bind lần lượt vào C-x w 3, C-x w 2
    • Khác với các lệnh chia thông thường là tiếp tục chia nhỏ cửa sổ hiện tại, các lệnh này hữu ích khi muốn tạo không gian làm việc riêng biệt
  • Các cửa sổ của Emacs được sắp xếp theo cấu trúc cây
    • Cửa sổ thực tế là các nút lá
    • Một thao tác chia sẽ biến nút lá thành nút cha của hai cửa sổ
    • Cách bố trí này giống với các trình quản lý cửa sổ xếp ô thủ công như i3 hay bspwm
  • tab-window-detachtear-off-window chuyển cửa sổ hiện tại sang tab mới hoặc frame mới
    • Phím mặc định được đánh giá là khá dài: C-x w ^ t, C-x w ^ f
    • Có thể thay thế bằng hành động dispatch của ace-window hoặc binding chuột

other-window-prefix: đổi nơi hiển thị của lệnh tiếp theo

  • other-window-prefix là lệnh tích hợp được gắn với C-x 4 4, khiến buffer mà lệnh tiếp theo hiển thị sẽ xuất hiện ở cửa sổ kế tiếp
  • Lệnh này tách việc hiển thị buffer của các lệnh như mở file, chuyển buffer, nhảy bookmark khỏi việc chọn cửa sổ đích để hiển thị
    • Giảm nhu cầu phải nhớ riêng các nhóm lệnh như find-file-other-window, find-file-other-tab, find-file-other-frame
    • Có thể thêm prefix trước các lệnh cơ bản như find-file, find-file-read-only, switch-to-buffer để chỉ thay đổi nơi hiển thị
  • Trong ví dụ với Forge, có thể tránh việc cửa sổ hiện tại bị ghi đè khi nhấn RET trong danh sách issue bằng other-window-prefix
  • Nó cũng cung cấp hành vi thống nhất khi mỗi gói như Magit, Org mode, Notmuch, Elfeed, EWW có cách “mở ở cửa sổ khác” khác nhau
  • Cũng có các prefix liên quan
    • same-window-prefix buộc buffer của lệnh tiếp theo hiển thị trong cửa sổ hiện tại
    • other-frame-prefix mở trong frame mới
    • other-tab-prefix mở trong tab mới

Lưu và hoàn tác cấu hình cửa sổ

  • window-configuration-to-register là lệnh tích hợp để lưu cấu hình cửa sổ hiện tại vào register, với phím mặc định là C-x r w
  • jump-to-register khôi phục cấu hình đã lưu, với phím mặc định là C-x r j
  • Ở mức Elisp, có thể lưu kết quả của current-window-configuration vào biến và áp dụng bằng set-window-configuration
    • Nếu lưu ra đĩa bằng các cách như prin1, persist, multisession thì đó có thể là nền tảng cho tính năng khôi phục qua nhiều phiên
    • Tuy vậy, việc cả vị trí con trỏ trong từng cửa sổ cũng được khôi phục có thể là hành vi thường không mong muốn
  • Cũng có các tùy chọn “oops” tự động tích lũy cấu hình cũ
    • winner-mode: khi không dùng tab, có thể hoàn tác hoặc áp dụng lại thay đổi cấu hình cửa sổ bằng winner-undo, winner-redo
    • tab-bar-history-mode: cung cấp ngăn xếp lịch sử riêng cho từng tab
    • undelete-frame-modetab-undo: khôi phục frame hoặc tab đã vô tình đóng
  • Dùng winner-undo như cách chữa cháy mỗi khi Emacs hiển thị buffer ở chỗ không mong muốn chỉ là giải pháp tạm thời
    • Vấn đề gốc là các quy tắc hiển thị buffer chưa được thiết lập đúng như mong muốn

Tối ưu cho hai cửa sổ thường xuyên qua lại

  • Trong công việc thực tế, dù trên màn hình có nhiều cửa sổ thì phần lớn thời gian vẫn thường xuyên qua lại giữa hai cửa sổ
    • Code & REPL
    • Code & Grep
    • Prose & Notes
    • Listing & Item
  • Các cửa sổ khác có thể là vùng tham chiếu thường xuyên nhìn tới nhưng hiếm khi chuyển sang, như tài liệu, thông tin gỡ lỗi, log, đầu ra lệnh, mục lục, trình duyệt file, bản xem trước
  • Có ví dụ other-window-mru dùng get-mru-window để chuyển sang cửa sổ được dùng gần đây nhất
    • Dù chọn cửa sổ thứ hai bằng chuột, ace-window, winum hay cách nào khác thì sau đó vẫn có thể qua lại rất nhanh
  • Cũng có cách cải thiện chính other-window
    • Tự động chia khi chỉ có một cửa sổ
    • Luân chuyển theo thứ tự dùng gần đây như switchy-window
    • Như other-window-alternating, đảo hướng mỗi khi không phải là lần gọi liên tiếp để việc qua lại giữa hai cửa sổ trở nên tự nhiên hơn

Mở rộng ace-window theo kiểu thực thi lệnh

  • ace-window có thể dùng riêng bước chọn một cửa sổ cụ thể thông qua aw-select
  • Nếu thực hiện thao tác mong muốn trên cửa sổ mà aw-select trả về thì có thể tạo ra mẫu “chọn cửa sổ → thực thi thao tác → giữ nguyên cửa sổ ban đầu”
  • Các lệnh ví dụ như sau
    • ace-tear-off-window: tách cửa sổ được chọn bằng ace-window thành frame mới
    • ace-tab-window-detach: chuyển cửa sổ đã chọn sang tab mới
  • ace-window-one-command cho phép thực thi một lệnh đơn bất kỳ trên cửa sổ đã chọn
    • Trước tiên chọn cửa sổ bằng ace-window
    • Đọc chuỗi phím rồi thực thi lệnh tương ứng
    • Có thể áp dụng thao tác lên cửa sổ khác mà không thay đổi cửa sổ đang được chọn ban đầu
  • ace-window-prefix hoạt động như phiên bản trực tiếp hơn của other-window-prefix
    • Chọn trực tiếp cửa sổ đích cho buffer mà lệnh tiếp theo sẽ hiển thị bằng ace-window
    • Nếu cần, có thể tạo cửa sổ mới ngay tại chỗ bằng hành động của ace-window rồi hiển thị vào đó
    • Binding phím được đề xuất là C-x 4 o

Có nhất thiết phải chuyển cửa sổ không

  • Mục đích của việc chuyển cửa sổ có thể chia lớn thành hai loại
    • Switch and stay: tiếp tục chỉnh sửa hoặc làm việc ở cửa sổ đích
    • Switch and return: tạm thời làm việc như cuộn, tìm kiếm, sao chép, xóa rồi quay lại vị trí ban đầu
  • Trong trường hợp thứ nhất, Avy có thể gộp việc chuyển cửa sổ và di chuyển con trỏ thành một
    • avy-goto-char-timer xem nhiều cửa sổ và frame Emacs đang hiển thị trên màn hình như một tập ứng viên nhảy chung
    • Khi nhảy tới vị trí của một ký tự hoặc chuỗi nhất định, cửa sổ cũng tự động được chuyển
    • Nếu Avy không đi qua các cửa sổ và frame, cần kiểm tra thiết lập avy-all-windows
  • pop-global-mark là cách để quay lại vị trí trước đó, và nếu cần thì việc chuyển cửa sổ cũng có thể xảy ra cùng lúc
    • Mặc định nó chuyển buffer trong cửa sổ hiện tại, nên có advice để buộc dùng pop-to-buffer
  • Trong trường hợp thứ hai, có thể tự động hóa luồng “chuyển → hành động → quay lại” bằng cách bọc nó thành lệnh
    • ace-window-one-command là một cách dùng chung cho mục đích này
    • Các thao tác cụ thể có thể được tạo thành lệnh chuyên dụng hoặc macro

Cuộn·tìm kiếm·chuyển buffer ở cửa sổ khác

  • scroll-other-windowscroll-other-window-down cuộn cửa sổ khác mà không rời khỏi cửa sổ hiện tại
    • Đích mặc định là “cửa sổ tiếp theo” theo chiều kim đồng hồ tính từ cửa sổ hiện tại
    • Nếu có từ ba cửa sổ trở lên, cửa sổ được cuộn có thể không phải cửa sổ tham chiếu như mong đợi mà là một cửa sổ khác
  • Có thể thay đổi quy tắc chọn đích cuộn bằng cách cấu hình other-window-scroll-default
    • Dùng get-lru-window thì sẽ cuộn cửa sổ ít được dùng gần đây nhất
    • Dùng get-mru-window thì có thể nhắm tới cửa sổ được dùng gần đây nhất
  • Nếu đặt other-window-scroll-buffer, có thể chỉ định cửa sổ đang hiển thị một buffer cụ thể làm đích cuộn
    • Đây chủ yếu được xem là một tùy chọn hữu ích cho tác giả package
  • Ví dụ isearch-other-window hoạt động bằng cách bắt đầu tìm kiếm ở cửa sổ đích cuộn, rồi quay lại cửa sổ ban đầu sau khi kết thúc tìm kiếm
    • Có ví dụ dùng cùng shell và buffer Man
  • next-buffer, previous-buffer, switch-to-buffer cũng có thể được mở rộng để chạy ở cửa sổ khác bằng cách kết hợp đối số prefix với other-window-for-scrolling
    • Nếu tạo keymap cho repeat-mode, có thể dùng n, p, b để tuần tự chuyển hoặc chọn buffer của cửa sổ khác

master-mode, scroll-all-mode, with-other-window

  • master-mode chỉ định buffer hiện tại là “master”, các buffer khác là “slave”, để gửi hành động tới buffer slave mà không rời vị trí hiện tại
    • Theo mặc định, nó được đánh giá là một lựa chọn thay thế kém minh bạch hơn so với cách other-window-scroll-default ở trên
    • Thông qua master-says, có thể tạo phím để thực hiện các hành động tùy ý như recenter trong buffer slave
  • scroll-all-mode liên kết thao tác cuộn của mọi cửa sổ trong frame
    • Hữu ích khi muốn xem đồng bộ nhiều góc nhìn cửa sổ
  • Macro with-other-window là helper Elisp để chạy phần thân mã trong cửa sổ do other-window-for-scrolling chọn
    • Có thể tạo đơn giản các lệnh như isearch-other-window, isearch-other-window-backwards
    • Nó được dùng như bản tương ứng Elisp của ace-window-one-command dạng tương tác

Chiến lược giảm số lượng cửa sổ

  • UI trình soạn thảo hiện đại nhìn chung hội tụ về một cửa sổ chính, thanh tab phía trên, sidebar thư mục hoặc mục lục bên trái, panel tùy chọn bên phải và terminal phía dưới
  • Trong Emacs cũng có thể tạo bố cục như vậy, nhưng cũng có thể tập trung màn hình vào một buffer và thay việc chuyển cửa sổ bằng chuyển buffer
  • Chỉ cần nới lỏng tới tối đa hai cửa sổ thì vẫn giữ được phần lớn sự đơn giản, đồng thời dùng cửa sổ thứ hai làm tài liệu tham chiếu trực tiếp
    • Cấu hình mặc định của Emacs hỗ trợ kiểu này khá tốt thông qua các lệnh như scroll-other-window
  • Cũng có chiến lược xem cửa sổ chỉ là container văn bản rồi bỏ qua chúng
    • Dùng Avy để nhảy thẳng tới vị trí văn bản trên màn hình
    • Lần theo các vị trí trước đó bằng mark-ring, global-mark-ring
    • dogears có thể cung cấp UI truy vết chi tiết hơn
  • Để cố định vị trí thủ công có thể dùng point-to-registerjump-to-register, còn để lưu vết bền hơn có thể dùng bookmark-setbookmark-jump

Quy tắc hiển thị tự động và quản lý popup

  • display-buffer-alist là biến dùng để khớp buffer với quy tắc và quyết định cách hiển thị khi mã Elisp muốn hiển thị một buffer
  • Về lý thuyết, nếu tạo quy tắc về kích thước, vị trí, vai trò và focus cho từng kiểu buffer thường gặp hằng ngày thì có thể giải quyết được phần lớn việc quản lý cửa sổ
  • Vấn đề là chi phí cấu hình
    • Predicate của buffer và mode
    • Kiểu cửa sổ và slot
    • Hàm action của display-buffer
    • Tham số cửa sổ
    • Khó biểu đạt dễ dàng những ý định đơn giản như “đừng đụng vào bố cục cửa sổ của tôi”
  • Cũng có các công cụ hỗ trợ
    • Shackle che bớt độ phức tạp của display-buffer-alist và cung cấp giao diện Elisp đơn giản hơn
    • Doom Emacs cung cấp các lệnh tiện ích như set-popup-rule!
  • PopwinPopper bắt đầu từ nhận định rằng không phải mọi buffer đều giống nhau
    • Phân biệt buffer làm việc chính với buffer popup tạm thời
    • Hiển thị tài liệu, shell, trạng thái tác vụ, kết quả biên dịch, kết quả tìm kiếm, tin nhắn... trong các cửa sổ phụ nhỏ để dễ đóng hoặc chuyển vòng
    • Popper tập trung vào việc bật/tắt các buffer popup đã chỉ định chỉ bằng một phím
    • Popwin là triển khai cũ hơn và toàn diện hơn, nhưng cũng gộp cả thiết lập display-buffer riêng của nó
    • Nếu chỉ muốn mở/đóng shell thật nhanh thì shell-pop hoặc vterm-toggle có thể là đủ

Mảnh ghép còn thiếu: thao tác cây cửa sổ

  • Emacs biểu diễn các cửa sổ trong frame dưới dạng cây, nhưng phần lớn lệnh người dùng lại hoạt động dựa trên vị trí không gian chứ không phải cấu trúc cây
  • Sự lệch pha này khiến thao tác chia/xóa đôi khi cho kết quả khác kỳ vọng, hoặc làm nảy sinh giới hạn trong các cấu trúc chia có thể tạo ra
  • Nếu có một package giả định như window-tree, việc thao tác theo đơn vị nút bên trong có thể trở nên khả thi
    • Chỉ chia/hoán vị/soi gương một phần của frame
    • Chọn nhiều cửa sổ như một cấu hình con
    • Chuyển phần đã chọn sang tab hoặc frame
    • Sao chép hoặc lưu cấu hình con
    • Bảo vệ một nhánh cây cụ thể khỏi các lệnh thuộc họ display-buffer
  • Elisp hiện có cũng đã có một số thành phần
    • window-tree trả về chính cây đó
    • frame-root-window trả về nút gốc
    • window-parent, window-child, window-*-sibling
    • Có thể duyệt bằng walk-window-tree, walk-windows
  • Những điểm còn thiếu cũng khá rõ
    • Không có hàm nền tảng để biến đổi cây ngoài split/delete thông thường
    • Không có khái niệm chọn cửa sổ bên trong, nên phải mô phỏng nó qua UI

Mảnh ghép còn thiếu: tích hợp với WM xếp ô

  • Mô hình cây cửa sổ của Emacs rất giống với các trình quản lý cửa sổ xếp ô thủ công như i3 hay bspwm
  • Nếu dùng Emacs bên trong i3, bspwm hoặc tmux, bạn sẽ muốn di chuyển qua lại một cách tự nhiên giữa các cửa sổ bên trong và bên ngoài Emacs bằng cùng một tổ hợp phím
  • Các ví dụ hiện có gồm i3-integration của Pavel Korytov và emacs-wm.el cho qtile
  • Một giao diện tích hợp gọn gàng hơn cần có các yếu tố sau
    • Trình quản lý cửa sổ phải nhận diện được lớp của cửa sổ đang hoạt động, đồng thời cung cấp khả năng di chuyển và thao tác cửa sổ theo cách lập trình được
    • Cách thức giao tiếp có thể là lệnh shell, socket, IPC dựa trên máy chủ, hoặc D-Bus của Linux
    • Ở phía Emacs, cần một giao diện độc lập với phương thức giao tiếp để mô phỏng các thao tác kiểu trình quản lý cửa sổ
    • Khi chuyển đổi giữa các cửa sổ của hệ điều hành, cần kiểm tra xem cửa sổ đang hoạt động có phải là Emacs hay không, và nếu cần thì Emacs sẽ xử lý thao tác trong frame nội bộ

Kết luận

  • Quản lý cửa sổ trong Emacs cung cấp nhiều lớp lựa chọn, từ other-window đến ace-window, Avy, Popper và display-buffer-alist
  • Không cần phải dùng mọi cách, vì có nhiều phương án thay thế để giải quyết cùng một vấn đề, nên bạn có thể chọn một cách rồi bỏ qua phần còn lại
  • Các công cụ tích hợp sẵn cơ bản có khả năng được duy trì lâu dài, nhưng trạng thái của các gói bên thứ ba có thể thay đổi tùy theo việc được phát triển tiếp, bị bỏ mặc hay trở thành dự án mồ côi
  • Quản lý cửa sổ của Emacs gần với một cấu trúc mở cung cấp nguyên liệu và công thức hơn là một hệ thống cố định phức tạp
  • Chỉ với ít cấu hình, bạn đã có thể có một bữa ăn cơ bản, và với một chút kết hợp cùng điều chỉnh Elisp, bạn có thể tạo ra quy trình làm việc được tùy biến hơn rất nhiều

1 bình luận

 
GN⁺ 2024-05-13
Ý kiến trên Hacker News
  • Bài viết hay, phần giải thích và hướng dẫn cũng rất tuyệt. Đôi khi chỉ chia cửa sổ đều nhau là chưa đủ, nên tôi thêm hàm dưới đây vào init.el và gán vào C-x 7 để chỉnh cửa sổ hiện tại và cửa sổ ghép cặp theo chiều dọc thành kích thước 70%/30%
    Chiều ngang cũng xử lý tương tự bằng phím gán C-x 8

    (defun partial-size-window ()
    "Set the two split windows to 70% and 30% vertically."
    (interactive)
    (let ((size (- (truncate (* .70 (frame-height))) (window-height))))
    (if (> size 0)
    (enlarge-window size))))

    (defun partial-size-window-h ()
    "Set the two split windows to 70% and 30% horizontally."
    (interactive)
    (let ((size (- (truncate (* .70 (frame-width))) (window-width))))
    (if (> size 0)
    (enlarge-window-horizontally size))))

    • golden-ratio cũng có thể dùng cho mục đích này
  • Một bài khảo sát rất hay. Hiện tôi đang dùng di động nên chưa thử ngay được, nhưng rất muốn nhanh chóng thử ace-window, ace-window-display-mode, frames-only-mode
    Thú thật là dù đã dùng Emacs khoảng 40 năm, phần lớn tôi vẫn chỉ dùng next-window, tạo cửa sổ mới bên dưới hoặc bên cạnh, và dựa vào tmux khi làm việc trên máy chủ từ xa

    • Tôi cũng tương tự. Suốt 30 năm, hầu như tất cả chỉ là C-x 1/2/3, C-x o
      Dù vậy thực ra nó khá mạnh và đủ cho nhu cầu của tôi, nên tôi cảm thấy ước gì nhiều trình quản lý cửa sổ dạng tiling cũng chỉ cần được đến mức đó
    • Tôi cũng vậy. C-x o hơi phiền nên tôi đã đặt cấu hình dưới đây, nhưng không cảm thấy các gói bổ sung kiểu này là thật sự cần thiết
      (global-set-key (kbd "M-o") #'other-window)
      Dù vậy, thật tốt khi có một bài tham khảo sâu như thế này, và các bài viết của Karthik lúc nào cũng mang tính giáo dục và thú vị
  • Bổ sung vào ghi chú của Karthink về windmove-mode, có thể thiết lập windmove-default-keybindings để di chuyển giữa các cửa sổ bằng Ctrl-<phím mũi tên>
    (windmove-default-keybindings 'control)
    Tôi cũng đã đưa vào cấu hình của mình, và cả trong bộ starter kit tối giản; nó thật sự là một game changer
    https://codeberg.org/ashton314/emacs-bedrock

    • Kiểm tra .emacs của tôi thì thấy mình đang dùng đúng y như vậy. Tôi thích cách này hơn vì ít hơn C-x O một lần nhấn phím và linh hoạt hơn
  • Tôi cấu hình để Emacs không chia frame thành nhiều cửa sổ. Tương tự cách trình duyệt web không tách cửa sổ trình duyệt thành nhiều viewport
    Emacs của tôi cũng không tạo frame thứ hai. Cách triển khai thay đổi qua từng năm khi cách cũ không còn hoạt động nữa
    Với cách hiện tại, trong một số tình huống frame vẫn bị chia, chẳng hạn khi Emacs hiển thị buffer *Completions*, nhưng nếu nhớ không nhầm thì tôi không cần gọi thủ công delete-window để xóa cửa sổ thứ hai, và nó luôn tự biến mất

    • Trình duyệt web cũng có thể thực sự chia cửa sổ như vậy nếu là trình duyệt cho phép xem nhiều trang cùng lúc, như Vivaldi
    • Tôi tò mò liệu việc không cho chia frame thành nhiều cửa sổ có nhằm giải quyết một vấn đề cụ thể nào không
      Tôi dùng frame nhiều cửa sổ khá nhiều. Trên macOS mới nhất và Emacs mới nhất, thỉnh thoảng frame nhiều cửa sổ dường như bị treo, không phản hồi với bàn phím hoặc trackpad, và nhiều lần nhấn Ctrl-G cũng không có tác dụng
      Nhưng tạo frame mới bằng C-x 5 2 thì hoạt động, rồi tôi có thể quay lại frame bị treo và đóng frame đó bằng C-x 5 0
  • Bài viết rất có chiều sâu, và tôi thật sự thích việc tác giả đã dành thời gian vẽ các sơ đồ đẹp

  • Bài viết hay, và tôi muốn chia sẻ một gói rất tuyệt để dùng kèm. Với tôi, zygospore là công cụ không thể thiếu
    “zygospore cho phép hoàn tác C-x 1 (delete-other-window) bằng cách nhấn lại C-x 1
    https://github.com/LouisKottmann/zygospore.el

    • Nếu muốn làm lại hoặc hoàn tác mọi thay đổi cấu hình cửa sổ, đáng để xem winner mode
      https://www.emacswiki.org/emacs/WinnerMode
    • Lý tưởng thì chẳng phải nên là undo sao
      Có thể hơi kỳ, nhưng C-u C-x 1 thì trông có vẻ nhất quán
  • Nếu tác giả đọc được điều này, tôi muốn nói rằng tôi rất vui khi thấy một nhắc đến nhỏ về Acme editor

  • Khi gọi hledger-balance-sheet, tôi muốn nó mở ở bên phải với độ rộng 30%, thay vì thay thế .hledger.journal hiện có
    Tôi muốn .hledger.journal vẫn được mở nguyên ở bên trái và vẫn ở trạng thái được chọn