Làm cách nào tôi có thể định dạng lại chuỗi nhiều dòng trong vim khi sử dụng kiểu tệp Python?


23

Giả sử tôi đang chỉnh sửa một số mã Python trong vim trông giống như:

myobj.myfunc("Some string parameter that goes on and on and on and on and sometimes doesn't"
             "split very"
             "neatly over different lines so that"
             "it is formatted attractively")

Tôi muốn định dạng lại cái này để nó phản ánh đúng với cái textwidthtôi đã đặt:

myobj.myfunc("Some string parameter that goes on and on and "
             "on and on and sometimes doesn't split very "
             "neatly over different lines so that it is "
             "formatted attractively")

Có cách nào làm dễ hơn không? Nếu đây là một đoạn văn bản thông thường, gqiphoặc tương tự sẽ hữu ích, nhưng điều này sẽ không xử lý các trích dẫn được sử dụng để xóa chuỗi.

Lưu ý : Tôi đang hỏi cụ thể về Python ở đây, nhưng lý tưởng nhất, câu trả lời này sẽ phù hợp với nhiều loại ngôn ngữ lập trình cho phép tiếp tục chuỗi.


1
Câu hỏi tương tự ở đây: vim.1045645.n5.nabble.com/ từ
Andrew Ferrier

3
Bạn cũng đã xem xét viết lại mã như một """multi-line string"""?
200_success

1
@ 200_success, đó là một mẹo tuyệt vời, cảm ơn. Tôi hoàn toàn không biết về tính năng đó của Python. Nó dường như hoạt động, chủ yếu - mặc dù tất cả các tham số cho chức năng được phản xạ lại, điều này không lý tưởng. Tôi nghĩ rằng câu hỏi của tôi vẫn hợp lệ cho loại chuỗi tôi có, và chắc chắn cho các lang khác.
Andrew Ferrier

2
Lưu ý rằng một chuỗi nhiều dòng sẽ thêm các ký tự khoảng trắng, đây có thể là một vấn đề nếu khoảng trắng có vấn đề trong chuỗi.
Matt Boehm

Câu trả lời:


6

Oh đó là một khó khăn. Tôi nghĩ rằng cách tiếp cận tốt nhất có thể là một macro nhưng nhiều khả năng là một plugin. Đây là một ví dụ tôi đã đánh lên (tôi cần một sở thích tốt hơn). Nó dường như hoạt động với tôi nhưng sẽ cần plugin thụt đầu trăn để thụt lề đúng cách. Hãy thử nó.

function ReformatMultiLines()
  let brx = '^\s*"'
  let erx = '"\s*$'
  let fullrx = brx . '\(.\+\)' . erx
  let startLine = line(".")
  let endLine   = line(".")
  while getline(startLine) =~ fullrx
    let startLine -= 1
  endwhile
  if getline(endLine) =~ erx
    let endLine += 1
  endif
  while getline(endLine) =~ fullrx
    let endLine += 1
  endwhile
  if startLine != endLine
    exec endLine . ' s/' . brx . '//'
    exec startLine . ' s/' . erx . '//'
    exec startLine . ',' . endLine . ' s/' . fullrx . '/\1/'
    exec startLine . ',' . endLine . ' join'
  endif
  exec startLine
  let orig_tw = &tw
  if &tw == 0
    let &tw = &columns
    if &tw > 79
      let &tw = 79
    endif
  endif
  let &tw -= 3 " Adjust for missing quotes and space characters
  exec "normal A%-%\<Esc>gqq"
  let &tw = orig_tw
  let endLine = search("%-%$")
  exec endLine . ' s/%-%$//'
  if startLine == endLine
    return
  endif
  exec endLine
  exec 'normal I"'
  exec startLine
  exec 'normal A "'
  if endLine - startLine == 1
    return
  endif
  let startLine += 1
  while startLine != endLine
    exec startLine
    exec 'normal I"'
    exec 'normal A "'
    let startLine += 1
  endwhile
endfunction

Sau đó, bạn có thể sử dụng nó với :call ReformatMultiLines()và / hoặc sử dụng nó trong ánh xạ.


6

Nếu đây là một sự xuất hiện thường xuyên, tốt nhất bạn nên tìm kiếm một plugin hoặc sử dụng chức năng của @Sukima. Tuy nhiên, nếu tôi đang làm điều này một cách nhanh chóng, thì đây là những gì tôi có thể làm:

  1. Thêm một dòng mới sau paren mở và trước paren đóng để các chuỗi nằm trên các dòng riêng biệt.

    myobj.myfunc(
                 "Some string parameter that goes on and on and on and on and sometimes doesn't"
                 "split very"
                 "neatly over different lines so that"
                 "it is formatted attractively"
    )
    
  2. Chọn các dòng có chuỗi và xóa dấu ngoặc kép xung quanh: :norm ^x$x

  3. Giảm băng thông (để tính các trích dẫn bị thiếu) :set tw-=2
  4. Chọn lại và định dạng: gvgq
  5. Sửa lỗi băng thông: :set tw+=2
  6. Thêm lại dấu ngoặc kép : gv:norm I"<Esc>A". Thay vì <Esc>bạn muốn chèn một lối thoát theo nghĩa đen bằng cách gõ ctrl-v theo sau là phím thoát. Vì tôi ánh xạ jj để thoát, tôi thường chỉ gõ jj ở đây.
  7. Tùy chọn sử dụng J để nối lại hai / hai dòng đầu tiên. Khi tôi có một chuỗi rất dài trong python như thế này, tôi thường thích bắt đầu nó trên dòng tiếp theo và chỉ thụt vào nó một cấp hơn dòng trước. Điều này mang lại nhiều không gian ngang cho chuỗi và chỉ cảm thấy tự nhiên hơn đối với tôi. Ngoài ra, bạn có thể lưu chuỗi vào một biến ở đâu đó ở trên. Giả sử đó là một chuỗi tĩnh, bạn thậm chí có thể lưu nó vào một biến toàn cục để nó ở mức thụt thấp hơn nhiều và có thể phù hợp với ít dòng hơn. Lưu ý rằng bạn phải tham gia paren đóng trên cùng một dòng, bạn có thể muốn giảm / tăng độ rộng văn bản lên 3 thay vì 2.

1
Cảm ơn. Tôi chỉ thử điều này nhưng :set tw-=2kết quả trong E487: Argument must be positive: tw-=2. Là cú pháp không chính xác?
Andrew Ferrier

1
Kiểm tra giá trị hiện tại của băng thông với :set tw?. Tôi đoán là bạn có độ rộng văn bản được đặt thành 0. Các bước này giả định rằng băng thông văn bản bắt đầu là số lượng ký tự bạn muốn trên mỗi dòng.
Matt Boehm

Trong ví dụ của bạn, bạn có thể muốn s/2/3/và thêm một khoảng trắng trước trích dẫn kết thúc, chuỗi dài của bạn sẽ không có khoảng cách thích hợp giữa các từ.
cdosborn

1

Phân tích cú pháp và định dạng mã là khó, đặc biệt đối với các ngôn ngữ động như Python.

Thay vì cố gắng phân tích Python trong Vimscript, tôi khuyên bạn nên sử dụng một trình định dạng bên ngoài như yapf . Với câu trả lời của tôi ở đây, bạn có thể viết nó tự động bằng cách viết với:

augroup write_cmd
    autocmd BufWritePre *.py call s:write_cmd('yapf')
augroup end

Các s:write_cmd()chức năng trong câu trả lời khác - Tôi sẽ không thêm nó ở đây vì vậy tôi sẽ không phải cập nhật nó ở hai nơi nếu tôi tìm thấy một lỗi :-)

Bạn cũng có thể thiết lập formatprgđể yapfvà tự định dạng nó với gq.


Chào. Câu trả lời hữu ích, nhưng tôi không hài lòng vì tôi không nghĩ nó trả lời câu hỏi này: câu hỏi này đặc biệt hỏi về việc định dạng lại chuỗi đa dòng, yapfdường như không nên làm. Tuy nhiên, tôi đồng ý rằng nó trông giống như một công cụ hữu ích.
Andrew Ferrier

@AndrewFerrier Đủ công bằng; Tôi có thể tuyên thệ tôi đã thấy nó định dạng lại chuỗi khi tôi đã thử nghiệm điều này vào ngày khác, nhưng bây giờ tôi cũng không thể làm cho nó hoạt động được: - / Đoán tôi đã bối rối.
Martin Tournoij

0

Các chức năng và ánh xạ tương ứng đã giải quyết vấn đề này cho tôi:

function! BreakMultlineString(quote)
let c = 100
while c == 100
    normal 100|
    let c = virtcol('.')
    if c == 100
        execute "normal ," . a:quote
    endif
endwhile
endfunction

function! JoinMultilineString()
    let c = "'"
    while c == "'" || c == '"'
        normal gj^
        let c = matchstr(getline('.'), '\%' . col('.') . 'c.')
        normal k
        if c == "'" || c == '"'
            normal ,j
        endif
    endwhile
endfunction

" break lines
nnoremap <Leader>" 100\|Bi"<CR>"<Esc>
nnoremap <Leader><Leader>" :call BreakMultlineString('"')<CR>
nnoremap <Leader>' 100\|Bi'<CR>'<Esc>
nnoremap <Leader><Leader>' :call BreakMultlineString("'")<CR>

" join lines
nmap <Leader>j Jds'ds"x
nnoremap <Leader>J :call JoinMultilineString()<CR>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.