Navigating project with vim-projectionist

Tản mạn

Đây là một bài TIL, nhưng sẽ được viết theo format một bài post. Lý do đầu tiên là vì mình đang rảnh =)) Lý do thứ hai là đã lâu rồi mình mới tìm được 1 Vim-plugin thú vị như thế này =))

Chắc hẳn bạn đã từng nghe tới Editor War - Cuộc chiến giữa 2 “phe”: Vim và Emacs =)) Mình nhớ có lần đã từng đọc trong 1 comment trong thread Editor War rằng:

Vim wins, just because Vim has Tim Pope.

Đây là 1 câu joke, nhưng nó đã thể hiện 1 phần nào về profile khủng của bác Tim Pope này.

Nói sơ qua thì bác Tim Pope này là super star về Vim, viết rất nhiều plugins, mà cái nào cũng tính hàng nghìn/ chục nghìn stars. Nếu bạn đã từng dùng Vim, chắc hẳn bạn cũng đã dùng qua 1 vài plugins mà bác Tim Pope viết. Có thể kể tới 1 vài plugins như: vim-fugitive, vim-surround, vim-pathogen, vim-commentary, vim-sensible, vim-rails (đây là plugin cho mọi Rails dev nếu dùng Vim luôn :D ), …

Và hôm nay, mình muốn giới thiệu 1 plugin khác cũng của bác này. Đó là vim-projectionist.

vim-projectionist

Trong bài viết về How I use Vim#Plugins#vim-rails, mình đã có nói về những công dụng cực kì hữu ích của vim-rails. Plugin này hỗ trợ việc jumping around rất thuận tiện giữa Controller, Model, View, Test files, … thông qua command gf, Alternate and Related Files. Tuy nhiên plugin này có 2 nhược điểm: 1 là chỉ dùng được cho Rails project, và 2 là vẫn chưa xử lý triệt để cho 1 số case đặc biệt. (vim-rails/issues/262)

Do đó, bác Tpope đã bắt tay vào viết vim-projectionist.

Mục đích

Tạo ra một plugin cho phép navigating giữa các files trong 1 project.

Ví dụ:

  • Khi tôi đang ở trong file app/controllers/xx_controller.rb, gõ :A thì sẽ jump được tới file spec/requests/xx_controller_spec.rb. Khi đã ở trong file test, tôi có thể gõ :A để quay lại file controller của test đó.
  • Mở rộng ra cho các dự án khác (vd Flask, Django, …), tôi có thể định nghĩa được “đâu là alternate/related files của file A”. Như thế thì khi đang ở trong file A, tôi sẽ có thể jump tới bất cứ alternate files nào mà tôi muốn.

Ý tưởng

Tạo ra file .projections.json, đặt ở thư mục ~/ hoặc root của project. Sau đó define rules. vim-projections sẽ đọc file này, parse ra rule và giúp mình jump tới file cần thiết

Về config file .projections.json như thế nào, các bạn có thể tham khảo :help projectionist để đọc thêm nha.

Examples

Ví dụ mình có 1 project Flask như thế này:

> tree .
.
├── MANIFEST.in
├── flaskr
│   ├── __init__.py
│   ├── auth.py
│   ├── blog.py
│   ├── db.py
│   ├── schema.sql
│   ├── static
│   │   └── style.css
│   └── templates
│       ├── auth
│       │   ├── login.html
│       │   └── register.html
│       ├── base.html
│       └── blog
│           ├── create.html
│           ├── index.html
│           ├── show.html
│           └── update.html
├── instance
│   └── flaskr.sqlite
├── setup.cfg
├── setup.py
├── tests
│   ├── conftest.py
│   ├── data.sql
│   ├── test_auth.py
│   ├── test_blog.py
│   ├── test_db.py
│   ├── test_factory.py
│   └── views
└── venv

Bây giờ, mình muốn: Khi đang ở trong file flaskr/blog.py, gõ :A thì sẽ nhảy tới tests/test_blog.py, hoặc Có thể quick edit template files, …

Như thế mình sẽ config .projections.json với content này:

{
  "flaskr/*.py": {
    "type": "view",
    "alternate": "tests/test_{basename}.py"
  },
  "tests/test_*.py": {
    "type": "test",
    "alternate": "flaskr/{basename}.py"
  },
  "flaskr/templates/*.html": {
    "type": "template"
  },
  "flaskr/__init__.py": {
    "type": "init"
  }
}

Hiện tại thì config này đang khá ok với mình, thời gian tới mình sẽ add thêm các rules mới nếu cần.

Nếu muốn config với nhiều rules linh hoạt hơn, bạn có thể tham khảo các config trong links dưới bài viết nha.