Emacs can be the best editor for Python?

Posted in General on December 08, 2015 by manhhomienbienthuy Comments
Emacs can be the best editor for Python?

Trong bài viết này, tôi sẽ giới thiệu một editor rất mạnh mẽ cho việc phát triển với Python, đó là Emacs. Thế giới vẫn còn nhiều tranh luận xung quanh việc Emacs hay Vim, đâu là editor tốt nhất. Ở trong bài viết này, tôi sẽ không tham gia vào việc đó. Tôi sẽ giữ một cái nhìn khách quan nhất có thể và bài viết chỉ đơn giản là giới thiệu các bước cần thiết để cấu hình Emacs cho phù hợp với công việc phát triển bằng ngôn ngữ Python. Và bạn có thêm 1 lựa chọn nữa cho editor nào mình thích.

Python là ngôn ngữ mà tôi làm việc nhiều nhất với Emacs nên bài viết này tôi chỉ tập trung cấu hình Emacs cho Python mà thôi. Tuy nhiên Emacs rất mạnh mẽ và có thể phù hợp với bất kỳ ngôn ngữ nào.

Cài đặt và sử dụng cơ bản

Cài đặt

Việc cài đặt Emacs không phải là vấn đề chính của bài viết này, nên tôi sẽ không đi vào chi tiết. Bạn có thể tìm thấy nhiều hướng dẫn để cài đặt Emacs trên hệ thống của mình.

Tôi sử dụng Ubuntu và tôi cài Emacs với lệnh sau:

$ sudo apt-get install emacs

Lưu ý là bạn cần sử dụng Emacs 24 để sử dụng các package vì Emacs 23 trở xuống không hỗ trợ việc này, bạn sẽ cần phải cấu hình thêm một chút.

Để cài đặt Emacs 24 nếu mặc định máy của bạn chỉ cài Emacs 23 với lệnh sau:

$ sudo apt-get install emacs24

Với các hệ thống khác, việc cài đặt cũng không khó, bạn hãy tự làm nó. Sau khi cài đặt, Emacs khi bật lên sẽ có giao diện mặc định giống hình dưới đây.

default emacs

Sử dụng cơ bản

Việc sử dụng Emacs cũng không phải là nội dung chính của bài viết này, nên tôi không đi vào chi tiết. Bạn có thể tìm thấy hướng dẫn ở rất nhiều nơi. Cách dễ dàng nhất là bạn đọc hướng dẫn được tích hợp sẵn trong chính Emacs.

Để đọc Tutorial, bạn sử dụng phím mũi tên chuyển đến dòng "Emacs Tutorial" rồi ấn Enter hoặc click chuột thẳng vào dòng chữ đó cũng được. Tutorial khi được mở ra sẽ có nội dung như dưới đây:

Emacs commands generally involve the CONTROL key (sometimes labeled
`CTRL` or `CTL`) or the META key (sometimes labeled `EDIT` or `ALT`).  Rather
than write that in full each time, we'll use the following
abbreviations:

C-<chr>  means hold the CONTROL key while typing the character <chr>
   Thus, C-f would be: hold the CONTROL key and type f.
M-<chr>  means hold the META or EDIT or ALT key down while typing <chr>.
   If there is no META, EDIT or ALT key, instead press and release the
   ESC key and then type <chr>.  We write <ESC> for the ESC key.

Ở Tutorial có hướng dẫn rất đầy đủ về những tính năng và cách sử dụng Emacs. Một tổ hợp phím được sử dụng rất nhiều đó là C-x C-s (dùng để lưu file). Viết C-x C-s có nghĩa là để lưu được file, bạn cần ấn các phím CONTROL và X cùng một lúc, sau đó ấn tiếp phím CONTROL và S. Bạn có thể xem tutorial để biết thêm các tổ hợp phím khác. Dùng Emacs cũng không quá khó.

Cấu hình với các package

Một trong những điểm mạnh của Emacs là nó rất đơn giản mà mạnh mẽ với khả năng mở rộng cấu hình. Để cấu hình Emacs, bạn cần những tạo ra các Initialization File, có thể là .emacs, .emacs.el hoặc init.el. Ở đây tôi chọn file init.el. Tất cả các file này đều cấu hình bằng ngôn ngữ Emacs Lisp, nên nếu rảnh rỗi bạn có thể nghiên cứu ngôn ngữ này, đó cũng là một ngôn ngữ rất hay.

Trong các hệ điều hành họ Unix, file init.el nằm ở đường dẫn $HOME/.emacs.d/init.el:

$ touch ~/.emacs.d/init.el

Ở Windows, vì không có biến môi trường HOME nên file nên được đặt ở C:\.emacs.d\init.el. Bạn có thể tham khảo thêm hướng dẫn cho Windows để biết thêm thông tin. GNU Emacs FAQ for MS Windows > Where do I put my init file?

Packages được sử dụng để tùy biến Emacs, package có thể nhận được từ nhiều nguồn khác nhau. Một trong những nguồn chính của các package là MELPA. Trong bài viết này, các package đều lấy từ nguồn này.

Theme và tùy chỉnh giao diện

Bây giờ hãy bắt đầu với việc cấu hình Emacs, đoạn cấu hình dưới đây dùng để cài đặt package và cài một theme.

;; init.el --- Emacs configuration

;; INSTALL PACKAGES
;; --------------------------------------

(require 'package)

(add-to-list 'package-archives
      '("melpa" . "http://melpa.org/packages/") t)

(package-initialize)
(when (not package-archive-contents)
 (package-refresh-contents))

(defvar myPackages
 '(better-defaults
   material-theme))

(mapc #'(lambda (package)
   (unless (package-installed-p package)
     (package-install package)))
     myPackages)

;; BASIC CUSTOMIZATION
;; --------------------------------------

(setq inhibit-startup-message t) ;; hide the startup message
(load-theme 'material t) ;; load material theme
(global-linum-mode t) ;; enable line numbers globally

;; init.el ends here

Phần đầu tiên, INSTALL PACKAGES sẽ cài đặt 2 package là better-defaultsmaterial-theme. Package better-defaults là tập hợp các cấu hình của Emacs thay thế cho cấu hình mặc định, nó là một cấu hình khá tốt. Package material-theme là một theme để tùy chỉnh giao diện của Emacs.

Theme material-theme là theme tôi chọn cho mình, bạn hoàn toàn có thể dùng theme khác nếu muốn.

Phần thứ 2 BASIC CUSTOMIZATION là phần tuỳ chỉnh Emacs với những việc sau:

  1. Tắt trang khởi động của Emacs (Trang đưa ra các thông tin và Tutorial). Khi bạn đã quen với Emacs rồi thì tôi nghĩ bạn có thể bỏ qua trang này cho đỡ rối mắt.
  2. Load theme material
  3. Bật chế độ hiển thị số dòng cho toàn bộ Emacs

Khi bật một chế độ gì đó cho toàn bộ Emacs (ví dụ ở trên là hiện thị số dòng) thì nó sẽ được áp dụng cho tất cả các buffers. Vì vậy, nếu bạn đang mở Python, Ruby, text, ... thì tất cả chúng đều sẽ hiển thị số dòng. Bạn hoàn toàn có thể bật chế độ này riêng cho một ngôn ngữ, ví dụ python-mode. Bạn có thể nghiên cứu thêm chi tiết cho việc này, với tôi, tôi sẽ bật hiển thị số dòng cho toàn bộ Emacs.

Bây giờ, đã có cấu hình rồi, bạn cần tắt và bật lại Emacs để xem thay đổi. Nếu bạn đặt các file cấu hình ở đúng đường dẫn của nó, Emacs sẽ tự động đọc và sử dụng. Tuy nghiên, bạn có thể khởi động Emacs và đọc file cấu hình ở bất kỳ đâu với lệnh sau:

$ emacs -q --load <path to init.el>

Khi load xong, Emacs sẽ trông đẹp hơn như hình dưới.

emacs themed

Lưu ý rằng, lần đầu bật Emacs sau khi cấu hình, Emacs sẽ bắt đầu quá trình cài đặt các package. Tùy thuộc vào tốc độ mạng mà quá trình này sẽ mất một chút thời gian. Có nhiều trường hợp Emacs báo lỗi không thấy package, có thể do nó chưa load được hết các package, bạn có thể dùng lệnh M-x list-packages để xem trong danh sách các package đã có package cần cài chưa

Ảnh dưới đây là một số tính năng cơ bản của Emacs, bao gồm khả năng phân chia màn hình và tìm kiếm file.

emacs simple features

Một tính năng rất đơn giản những hữu ích của Emacs đó là có thể khả năng tìm kiếm nhanh trong một thư mục, gọi là recursive-grep searchM-x rgrep. Ví dụ, tôi muốn tìm tất cả các từ python trong các file .md (markdown) trong một thư mục nào đó:

emacs rgrep

Vậy là những config cơ bản đã xong, bây giờ chúng ta có thể bắt đầu với những cấu hình nâng cao cho Python.

Elpy cho việc phát triển bằng Python

Emacs đã có sẵn một python-mode (python.el), chế độ mặc định này cung cấp khả năng indent cũng như highlight cú pháp Python. Tuy nhiên, mọi tính năng vẫn chỉ ở mức cơ bản. Nếu muốn một tính năng mạnh mẽ, đầy đủ hơn cho công việc phát triển Python, chúng ta cần nhiều hơn thế. Package elpy (Emacs Lisp Python Environment) cung cấp cho chúng ta một công cụ rất đầy đủ khiến Emacs gần như một Python IDE (Integrated Development Environment) bao gồm các tính năng sau:

  • Indent tự động
  • Highlight cú pháp Python
  • Auto-Complete
  • Kiểm tra cú pháp
  • Tích hợp REPL của Python
  • Hỗ trợ môi trường ảo
  • nhiều tính năng khác

Để cài đặt và sử dụng elpy, chúng ta cần thêm một chút cấu hình. Và bạn cần cài đặt flake8jedi để có thể dùng hết các tính năng của elpy. Bạn có thể cài đặt 2 package trên bằng cách trình quản lý package của Python, ví dụng dùng pip với lệnh sau:

$ pip install flake8
$ pip install jedi

Dưới đây là cấu hình elpy cho Emacs

(defvar myPackages
 '(better-defaults
   elpy ;; add the elpy package
   material-theme))

bây giờ là kích hoạt nó

(elpy-enable)

Với cấu hình mới, bạn có thể khởi động lại Emacs và mở 1 file Python để xem kết quả

emacs elpy basic

Trong ảnh trên, bạn có thể thấy một số tính năng như:

  • Tự động indent (sau khi ấn Enter sẽ tự động được indent)
  • Highlight cú pháp Python Kiểm tra cú pháp (lỗi ở dòng 9)
  • Auto-complete (Đưa gợi ý các method ở dòng 9)

Bây giờ, nếu bạn muốn chạy đoạn code trên, một số IDE cho phép bạn chạy với 1 click, Emacs cũng tương tự như vậy, bạn có thể ấn C-c C-c và kết quả khi chạy đoạn script sẽ hiện ra

emacs elpy execute

Thông thường, những người phát triển Python đường sử dụng môi trường ảo và thực thi code trên môi trường đó. Emacs cũng cho phép làm điều này. Để sử dụng môi trường ảo trên Emacs, bạn sử dụng lệnh M-x pyvenv-activate và thực hiện theo hướng dẫn. Để thoát khỏi môi trường ảo, bạn sử dụng lệnh M-x pyvenv-deactivate. Elpy cung cấp giao diện cho phép bạn theo dõi và debug nếu gặp phải vấn đề gì đó. Bạn dùng lệnh M-x elpy-config để xem các cấu hình của elpy và có thể sẽ có nhiều thông tin giá trị.

emacs elpy config

Vậy là những cấu hình cơ bản cho một Python IDE đã hoàn thành. Dưới đây sẽ là một số cấu hình nâng cao.

Mặc định, elpy trên Emacs sẽ sử dụng Python 2. Nếu bạn muốn sử dụng Python 3 thì cần thêm config như sau:

(setq elpy-rpc-python-command "python3")
(elpy-use-cpython "python3")

Một số tính năng mở rộng cho Python

Emacs cung cấp một số tính năng mở rộng cho Python cùng với những tính năng cơ bản của một IDE ở trên. Trong nội dung bài viết này, tôi không thể viết hết các tính năng mà sẽ chỉ đi vào chi tiết một số tính năng quan trọng, các tính năng khác bạn có thể tự tìm hiểu.

Kiểm tra cú pháp tốt hơn với Flycheck

Mặc định Emacs và elpy sử dụng một package là Flymake để hỗ trợ việc kiểm tra cú pháp Python. Tuy nghiên có 1 package khác là Flycheck cung cấp khả năng kiểm tra cú pháp Python theo thời gian thực. Việc chuyển sang sử dụng Flycheck cũng rất đơn giản.

(defvar myPackages
 '(better-defaults
   elpy
   flycheck ;; add the flycheck package
   material-theme))

Và sau đó

(when (require 'flycheck nil t)
 (setq elpy-modules (delq 'elpy-module-flymake elpy-modules))
 (add-hook 'elpy-mode-hook 'flycheck-mode))

Bây giờ, bạn có thể thấy, cú pháp Python sẽ được kiểm tra theo thời gian thực, mỗi khi bạn gõ phím, Flycheck sẽ kiểm tra cú pháp cho bạn ngay lập tức.

emacs elpy flycheck

Tuân thủ PEP8 với autopep8

Dù bạn có thích nó hay không thì nó vẫn tồn tại, đó là PEP8, và nó cũng là một trong số các tiêu chuẩn mà cộng đồng Python thường sử dụng. Nếu bạn muốn tuân thủ nó, có một công cụ cho phép bạn làm việc đó hoàn toàn tự động. Đó là autopep8. Nó tích hợp với Emacs và bất cứ khi nào bạn lưu file - C-x C-s - autopep8 sẽ tự động định dạng lại file của bạn tuân thủ theo PEP 8 (bạn có thể config để tùy biến nó).

Trước hết, bạn cần cài đặt autopep8, ví dụ sử dụng pip với lệnh sau:

$ pip install autopep8

Sau đó bạn cấu hình để Emacs tính hợp autopep8.

(defvar myPackages
 '(better-defaults
   elpy
   flycheck
   material-theme
   py-autopep8)) ;; add the autopep8 package

(require 'py-autopep8)
(add-hook 'elpy-mode-hook 'py-autopep8-enable-on-save)

Dưới đây là một demo cho tính năng này, sau khi lưu file, tất cả các lỗi liên quan đến PEP8 sẽ tự động được fix.

emacs elpy autopep8

Tích hợp IPython/Jupyter

Dưới đây là một tính năng rất thú vị. Emacs tích hợp với IPython REPL và Jupyter Notebooks. Trước hết, bạn chuyển sang IPython thay vì trình thông dịch mặc định.

(elpy-use-ipython)

Bây giờ, mỗi lần bạn chạy code Python bằng C-c C-c bạn sẽ thấy kết quả được thực thi bởi IPython REPL.

emacs elpy ipython

Đó là một tính năng rất hữu ích, ít nhất là với tôi. Tuy nhiên tính năng hay thực sự tôi thấy đó là khả năng tích hợp notebook. Ở đây, tôi mặc định bạn đã biết cách sử dụng Jupyter Notebook rồi. (Nếu chưa biết bạn có thể tham khảo tài liệu này). Với Emacs, chúng ta cần thêm một chút cấu hình

(defvar myPackages
 '(better-defaults
   ein ;; add the ein package (Emacs ipython notebook)
   elpy
   flycheck
   material-theme
   py-autopep8))

Giao diện Jupyter Web tiêu chuẩn cho notebook rất đẹp nhưng yêu cầu bạn sử dụng nó riêng biệt không liên quan gì tới Emacs.

jupyter web

Tuy nhiên bạn có thể làm việc tương tự bằng cách kết nối và thao tác với server ngay trên Emacs.

emacs elpy jupyter

Một số tính năng khác của Emacs

Phần trước, tôi đã trình bày những tính năng của Emacs như một Python IDE (và một số tính năng mở rộng). Trong phần này, tôi sẽ giới thiệu một số tính năng khác mà một IDE cần có.

Tích hợp git bằng Magit

Magit là một package thuộc loại non-utility phổ biến nhất trên MELPA và được sử dụng bởi hầu hết những người dùng Emacs cần thao tác với git. Nó thực sự mạnh mẽ và để nói về nó thì nội dung 1 bài viết là không đủ. Có một bài viết về Magit và bạn có thể tham khảo nó để biết thêm chi tiết. Hình dưới đây lấy từ bài viết đó cho thấy khả năng tích hợp git trong Emacs tuyệt với như thế nào.

mastering emacs magit

Những mode khác của Emacs

Trên đây chúng ta đang nói đến Emacs để phát triển Python, tuy nhiên Emacs không chỉ hỗ trợ Python. Tôi có thể dùng Emacs để thao tác với tất cả các file Python, Golang, JavaScript, Markdown, JSON, và rất nhiều file khác nữa. Bạn có thể chỉ cần dùng Emacs, nó hỗ trợ rất tốt hầu hết các ngôn ngữ lập trình. Có một số cấu hình cho Emacs khá đầy đủ trên mạng như config này hay config này rất đầy đủ, nó hỗ trợ nhiều ngôn ngữ mà bạn cần như:

  • Python
  • Golang
  • Ruby
  • Markdown
  • YAML
  • Web (HTML/JS/CSS)
  • SASS
  • SQL
  • v.v...

Emacs trong Terminal

Sau khi làm quen với Emacs, có thể bạn sẽ thích nó và muốn dùng nó ở bất cứ đâu. Nó rất đơn giản, bạn chỉ cần set -o emacs ở bash. Tuy nhiên, một tính năng thú vị của Emacs là nó có thể chạy cả ở giao diện dòng lệnh của Terminal. Bạn chỉ cần gõ emacs -nw ở bash là nó sẽ chạy Emacs với giao diện dòng lệnh.

Kết luận

Emacs là một editor rất mạnh mẽ, có thể nói là một trong số các editor tốt nhất cho lập trình viên. Có nhiều lựa chọn khác nhau nếu bạn muốn lập trình với Python, nhưng tôi recommend bạn nên học cách sử dụng Emacs hoặc Vim bởi chúng là những môi trường phát triển đa năng. Dưới đây là config đầy đủ cho Emacs. Có thể trong những bài viết sau, tôi sẽ nói về Vim, cũng là một editor rất thú vị. Hy vọng bài viết sẽ giúp ích cho bạn trong quá trình lựa chọn IDE cho mình.

;; init.el --- Emacs configuration

;; INSTALL PACKAGES
;; --------------------------------------

(require 'package)

(add-to-list 'package-archives
      '("melpa" . "http://melpa.org/packages/") t)

(package-initialize)
(when (not package-archive-contents)
 (package-refresh-contents))

(defvar myPackages
 '(better-defaults
   ein
   elpy
   flycheck
   material-theme
   py-autopep8))

(mapc #'(lambda (package)
   (unless (package-installed-p package)
     (package-install package)))
     myPackages)

;; BASIC CUSTOMIZATION
;; --------------------------------------

(setq inhibit-startup-message t) ;; hide the startup message
(load-theme 'material t) ;; load material theme
(global-linum-mode t) ;; enable line numbers globally

;; PYTHON CONFIGURATION
;; --------------------------------------

(elpy-enable)
(elpy-use-ipython)

;; use flycheck not flymake with elpy
(when (require 'flycheck nil t)
 (setq elpy-modules (delq 'elpy-module-flymake elpy-modules))
 (add-hook 'elpy-mode-hook 'flycheck-mode))

;; enable autopep8 formatting on save
(require 'py-autopep8)
(add-hook 'elpy-mode-hook 'py-autopep8-enable-on-save)

;; init.el ends here

I apologise for any typos. If you notice a problem, please let me know.

Thank you all for your attention.