2011-09-23 39 views
10

Sử dụng Vim Tôi thực sự là một người hâm mộ của chế độ trực quan cho phép bạn chèn văn bản trước một cột.Chèn thụt đầu dòng cho các cột trong Vim

Chèn một số khoảng cách sau khi các mũi tên,

> one 
> two 
> three 

có thể được thực hiện thông qua <Ctrl-V>jjI <Esc>:

> one 
> two 
> three 
  • đi sang chế độ hình ảnh <Ctrl-V>,
  • mở rộng lựa chọn hình ảnh jj,
  • chèn một số khoảng trắng I__,
  • tuyên truyền thay đổi cho tất cả các dòng blockwise lựa chọn <Esc>

thị giác Bây giờ tôi có một file văn bản mà cần một số định dạng. Đây là những gì nó trông giống như:

start() -- xxx 
initialize() -- xxx 
go() -- xxx 

Bây giờ tôi muốn sắp xếp một phần của văn bản này để sắp xếp nó vào các cột như thế này:

start()  -- xxx 
initialize() -- xxx 
go()   -- xxx 

Tôi có vấn đề là tôi không thể chèn một số tiền khác nhau của thụt đầu dòng vào mỗi dòng và chỉ thụt lề một lượng không gian cố định/tab là không đủ. Làm cách nào để bạn có thể thực hiện thụt lề, trong đó tất cả văn bản thụt lề sẽ phải được căn chỉnh ở cùng một cột?


EDIT: Tôi chỉ tìm ra một phương pháp khá tiết và khó sử dụng:

  • tìm ra vị trí chuỗi để thụt lề từ: \--,
  • chèn n (giả sử 20) không gian trước đó: 20i <Esc>,
  • xóa một phần của những khoảng trống đó trở lại một cột nhất định (giả sử 15): d|15,
  • lưu các bước đó dưới dạng macro và lặp lại macro thường xuyên nếu cần,

... rất xấu xí!

+0

bản sao có thể có của [Cách chèn dấu cách lên cột X để xếp hàng mọi thứ trong cột?] (Http://stackoverflow.com/questions/6154306/how-to-insert-spaces-up-to-column- x-to-line-up-vật-trong-cột) – DocMax

Trả lời

14

Tôi tốt hơn nhiều mà không cần bất kỳ plugin vim nào. Đây là giải pháp của tôi:

<Shift-V>jj:!column -ts --

Sau đó chèn -- thành nhiều dòng cũng giống như bạn đã viết trong câu hỏi.


Bạn cũng có thể thêm một số nhận xét vào lúc chèn.

:set virtualedit=all

<Ctrl-V>jjA-- xxx<Esc>

+2

Đây là tất nhiên cách bạn nên làm điều đó tại thời điểm chèn. +1. – Benoit

+0

sẽ không hoạt động trong trường hợp của tôi ... các phần '--- xxx' trên mỗi dòng bắt đầu ở các cột khác nhau. Vì vậy, bạn không thể căn chỉnh các phần chỉnh sửa của lựa chọn hình ảnh của bạn. (tệp tôi cần chỉnh sửa đã có cấu trúc này và tôi cần phải định dạng lại nó cho phù hợp) – oliver

+1

Bạn có làm việc trên * nix không? Nếu vậy, bạn có thể thử lệnh 'column' trong Vim. ' jj:! Column -ts --', sau đó chèn' --' vào nhiều dòng bạn muốn. – ernix

4

Bạn phải sử dụng một plugin cụ thể, bạn có thể sử dụng plugin Tabular hoặc Align trong trường hợp này.

Cả hai đều cho phép bạn căn chỉnh văn bản trên các ký tự cụ thể, như -- trong ví dụ của bạn. Cú pháp của họ hơi khác một chút. Chọn một trong đó phù hợp với bạn nhất.

+0

chỉ cần cài đặt Tabular và nó hoạt động chính xác. Nice ... mặc dù tôi đã hy vọng rằng nhiệm vụ khá nhỏ này sẽ không liên quan đến việc cài đặt một plugin. cám ơn vì sự gợi ý! – oliver

+0

@oliver: Có thể giải quyết tác vụ này mà không cần cài đặt plugin. Tuy nhiên, giải pháp này không nhỏ gọn như khi sử dụng một trong các plugin đó. –

3

Nếu không có plugin và nếu bạn đã nhập ý kiến ​​của bạn mà không emix của giải pháp:

:,+2 s/--/         & 

này sẽ đảm bảo tất cả các bình luận sẽ được chuyển leftwise để sắp xếp chúng đúng.

Sau đó blockwise chọn cột mà bạn muốn sắp xếp các văn bản, và: 100<

+0

Đẹp và đơn giản. Thích nó! – oliver

+0

Ngoài ra, hãy xem xét ':, 2s/\ ze -/\ = repeat ('', 32)'. –

+0

@ib .: điều này cũng tốt, nhưng tùy thuộc vào cài đặt bàn phím của bạn, có thể chậm hơn để nhập! – Benoit

3

Một cách dễ dàng để gắn kết văn bản trong cột là sử dụng Tabular hoặc Align plugin. Nếu không có trong số này đã sẵn sàng trong tay, người ta có thể sử dụng sau đây hơi phức tạp (và một chút cồng kềnh tìm kiếm) nhưng hoàn toàn làm việc (cho các trường hợp trong câu hỏi) lệnh. 1,2

:let m=0|g/\ze -- /let m=max([m,searchpos(@/,'c')[1]]) 
:%s//\=repeat(' ',m-col('.')) 

Mục đích của lệnh đầu tiên là để xác định độ rộng của cột để bên trái của dấu phân cách (mà tôi giả định là -- đây). Chiều rộng là được tính là độ dài tối đa của văn bản trong cột đầu tiên trong số tất cả các dòng. Lệnh :global được sử dụng để liệt kê các dòng chứa dấu tách (các dòng khác không yêu cầu căn chỉnh). Nguyên mẫu \ze nằm ngay sau đầu mẫu, đặt kết thúc trận đấu ở cùng vị trí bắt đầu (xem :help \ze). Thay đổi đường biên của trận đấu không ảnh hưởng đến cách hoạt động của lệnh :global, mẫu được viết theo cách như vậy chỉ để phù hợp với nhu cầu của lệnh thay thế tiếp theo: Vì hai lệnh này có thể chia sẻ cùng một mẫu, được bỏ qua trong phần thứ hai.

Lệnh được chạy trên các dòng phù hợp,

:let m=max([m,searchpos(@/,'c')[1]]) 

gọi searchpos() chức năng để tìm kiếm các mô hình sử dụng trong các phụ huynh :global lệnh, và để có được vị trí cột của trận đấu. Mẫu được gọi là @/ bằng cách sử dụng thanh ghi mẫu tìm kiếm cuối cùng (xem :help "/). Điều này lợi dụng thực tế là lệnh :global cập nhật số đăng ký / ngay khi bắt đầu thực thi. Cờ c được chuyển thành đối số thứ hai trong cuộc gọi searchpos() cho phép khớp tại số đầu tiên của một dòng (:global định vị con trỏ ở đầu dòng để thực thi lệnh), bởi vì nó có thể ở đó không có văn bản ở bên trái của dấu phân cách. Hàm searchpos() trả về một danh sách, phần tử đầu tiên là là số dòng của vị trí phù hợp, và thứ hai là vị trí cột.Nếu lệnh được chạy trên một dòng, dòng khớp với mẫu của lệnh có chứa :global. Khi searchpos() là để tìm kiếm cùng một mẫu, chắc chắn có một kết quả phù hợp trên dòng đó. Do đó, chỉ có cột bắt đầu trận đấu được quan tâm, do đó, nó được trích xuất từ ​​danh sách trả về theo số chỉ số [1]. Vị trí này rất bằng với chiều rộng của văn bản trong cột đầu tiên của dòng, cộng với một. Vì vậy, m được đặt thành giá trị hiện tại tối đa và vị trí cột đó.

Lệnh thứ hai,

:%s//\=repeat(' ',m-col('.')) 

miếng đệm sự xuất hiện đầu tiên của tách trên tất cả các dòng có chứa nó, với số lượng không gian mà là mất tích để làm cho văn bản trước khi tách lấy m ký tự, trừ một ký tự. Lệnh này là một toàn cầu thay thay thế một khoảng trống ngay trước khi tách (xem bình luận về :global lệnh trên) với kết quả đánh giá của biểu thức (xem :help sub-replace-\=)

repeat(' ',m-col('.')) 

Các repeat() lặp chức năng đối số đầu tiên của nó (dưới dạng chuỗi) số của lần được đưa ra trong đối số thứ hai. Vì mỗi lần thay thế con trỏ là được di chuyển đến đầu của kết hợp mẫu, m-col('.') bằng với số lượng không gian cần thiết để chuyển dấu phân tách sang phải để căn chỉnh các cột (col('.') trả về vị trí cột hiện tại của con trỏ).


Dưới đây là phiên bản một dòng của cặp lệnh này.

:let m=0|exe'g/\ze -- /let m=max([m,searchpos(@/,"c")[1]])'|%s//\=repeat(' ',m-col('.')) 

Trong các phiên bản trước đó của câu trả lời các lệnh sử dụng để được như sau.

:let p=[0]|%s/^\ze\(.*\) -- /\=map(p,'max([v:val,len(submatch(1))+1])')[1:0]/ 
:exe'%s/\ze\%<'.p[0].'c -- /\=repeat(" ",'.p[0].'-col("."))' 

Những người quan tâm đến các lệnh cụ thể này có thể tìm thấy mô tả chi tiết trong lịch sử chỉnh sửa.

+1

wow ... có vẻ như có liên quan! bạn có muốn giải thích giải pháp của mình không? – oliver

+0

@oliver: Chắc chắn rồi. Tôi đã thêm một lời giải thích chi tiết cho câu trả lời. –

+0

cảm ơn lời giải thích chi tiết! mặc dù tôi không nghĩ rằng tôi sẽ sử dụng điều này (tôi không bao giờ có thể nhớ :) trong thực tế tôi thực sự rất thích đọc theo câu trả lời của bạn và chắc chắn đã học được một số điều về vim ... một lần nữa! – oliver

0

Đây là một sửa đổi về câu trả lời của Benoit có hai bước.

Bước đầu tiên, chặn tìm kiếm văn bản đã chọn và thay thế - bằng nhiều khoảng trắng.

'<,'>s/--/       --/ 

Bây giờ tất cả nhận xét phải có nhiều không gian, nhưng vẫn không đồng đều.

Bước thứ hai, chặn chọn lại văn bản và sử dụng một regex khác để khớp với tất cả các ký tự bạn muốn giữ lại (nói 20 kí tự đầu tiên) cộng với tất cả dấu cách sau và thay thế nó bằng một bản sao 20 ký tự:

'<,'>s/\(.\{20}\)\s*/\1/ 

Không hoàn toàn dễ dàng như Benoit, nhưng tôi không thể tìm ra cách thực hiện bước thứ hai.

Các vấn đề liên quan