Giống như Ctrl-A và Ctrl-X nhưng chỉ sửa đổi chữ số đầu tiên


10

Có cách nào để tăng / giảm chữ số đầu tiên sau / dưới con trỏ, không phải toàn bộ số.

Tôi biết đó không phải là cách vim hoạt động, nhưng có một plugin nào đó không? Tôi đã không thể tìm thấy nó.

Nó rất hữu ích khi chỉnh sửa css và trong các trường hợp khác nữa.

Được:

▐margin: 10px

Khi tôi nhấn CTRL-Atôi muốn xem:

▐margin: 20px

Thực tế:

▐margin: 11px

10
Bạn cũng có thể làm 10<C-a>để thêm 10 hoặc r2thay thế 1 bằng 2.
jamessan

Câu trả lời:


6

Điều này dường như hoạt động khá tốt và thực hiện những điều khá lành mạnh khi sử dụng <C-a>trên 9 (95 trở thành 105) hoặc sử dụng <C-x>trên 0 (105 trở thành 95):

nnoremap g<C-a> :call search('\d', 'c')<CR>a <Esc>h<C-a>lxh
nnoremap g<C-x> :call search('\d', 'c')<CR>a <Esc>h<C-x>lxh
  • Đầu tiên, chúng tôi tìm kiếm bất kỳ chữ số nào, search()có lợi thế là không đặt lại @/.
  • a <Esc>h - Chuyển đến chế độ chèn, thêm khoảng trắng sau chữ số và sang bên trái để con trỏ ở trên cùng của chữ số.
  • Bây giờ chúng ta có thể sử dụng <C-a>hoặc <C-x>.
  • Chúng tôi sử dụng lxhđể loại bỏ không gian chúng tôi thêm vào.

Tôi đã ánh xạ cái này đến g<C-a>g<C-x>, vì vậy bạn vẫn có thể gọi bản gốc.

Một phiên bản hơi khác sẽ chỉ tìm kiếm các số trên dòng hiện tại (nhưng sẽ để lại một khoảng trống lơ lửng nếu không có số nào trên dòng hiện tại):

nnoremap g<C-a> :call search('\d', 'c', line('.'))<CR>a <Esc>h<C-a>lxh
nnoremap g<C-x> :call search('\d', 'c', line('.'))<CR>a <Esc>h<C-x>lxh

Và đây là một phiên bản khác sử dụng khái niệm tương tự như trước đây, nhưng cũng thêm một khoảng trắng trước chữ số. Điều này sẽ làm g<C-a>bỏ qua bất kỳ dấu hiệu munis trước số (theo mặc định, <C-a>vào -42ý chí 'tăng' nó sang -41.

Nó cũng chấp nhận số đếm, do đó 5g<C-a>sẽ tăng số lượng lên 5:

fun! Increment(dir, count)
    " No number on the current line
    if !search('\d', 'c', getline('.'))
        return
    endif

    " Store cursor position
    let l:save_pos = getpos('.')

    " Add spaces around the number
    s/\%#\d/ \0 /
    call setpos('.', l:save_pos)
    normal! l

    " Increment or decrement the number
    if a:dir == 'prev'
        execute "normal! " . repeat("\<C-x>"), a:count
    else
        execute "normal! " . repeat("\<C-a>", a:count)
    endif

    " Remove the spaces
    s/\v (\d{-})%#(\d) /\1\2/

    " Restore cursor position
    call setpos('.', l:save_pos)
endfun

nnoremap <silent> g<C-a> :<C-u>call Increment('next', v:count1)<CR>
nnoremap <silent> g<C-x> :<C-u>call Increment('prev', v:count1)<CR>

9

Gia tăng cơ bản

Đây là một macro đơn giản để thực hiện hành động:

:nnoremap <leader>a m`lv$xh<c-a>p``
:nnoremap <leader>x m`lv$xh<c-x>p``

Ở chế độ bình thường bạn

  • m` Đánh dấu vị trí của bạn
  • l di chuyển một nhân vật sang phải
  • v$x cắt đến cuối dòng
  • h di chuyển về vị trí ban đầu
  • <c-a> tăng (hoặc giảm)
  • p dán lại vết cắt của bạn
  • `` quay trở lại dấu ấn của bạn

Chuyển sang số tiếp theo

Nếu bạn muốn chuyển sang số tiếp theo (hoặc giữ nguyên vị trí hiện tại nếu ở số), bạn cần một chức năng kiểm tra ký tự bị nguyền rủa hiện tại và có thể nhảy sang số tiếp theo.

function! NextNum()
  let ch = getline(".")[col(".")-1]
  if ch !~ "[0-9]"
    execute "normal! /[0-9]\<cr>"
  endif
endfunction

nnoremap <leader>a :call NextNum()<cr>m`lv$xh<c-a>p``
nnoremap <leader>x :call NextNum()<cr>m`lv$xh<c-x>p``

NextNumlấy ký tự dưới con trỏ, kiểm tra xem nó có phải là số không và nếu không tìm kiếm số tiếp theo. Sau đó, phần còn lại là như vậy. Nếu bạn muốn ánh xạ khác nhau, chỉ cần thay đổi nnoremap <leader>athành những gì bạn muốn, ví dụ nnoremap <c-a>.

Bỏ qua các tiêu cực và số cao hơn 9

Nếu bạn muốn chỉ xoay vòng qua các chữ số và không có chúng hoạt động như các số nguyên đã ký, các hàm sau sẽ tăng và giảm và cuộn lại ở 0 và 9.

function! NextNum()
  let ch = getline(".")[col(".")-1]
  if ch !~ "[0-9]"
    execute "normal! /[0-9]\<cr>"
  endif
endfunction

function! IncDec(val, dec)
  if a:dec
    if a:val == 0
      return 9
    else
      return a:val - 1
    endif
  else
    if a:val == 9
      return 0
    else
      return a:val + 1
    endif
  endif
endfunction

function! DoMath(dec)
  call NextNum()
  normal! x
  let @" = IncDec(@", a:dec)
  normal! P
endfunction

nnoremap <leader>a :call DoMath(0)<cr>
nnoremap <leader>x :call DoMath(1)<cr>

Bây giờ khi bạn đang ở trên 8và gõ <leader>abạn nhận được 9. Làm lại một lần nữa kết quả 0. Nếu bạn nhấn <leader>xvào 0bạn nhận được 9. Tương tự với số âm. Các chức năng cắt một ký tự đơn, tăng, giảm hoặc cuộn qua và sau đó dán vào vị trí.


Một cái gì đó không đúng ở đây, nhưng tôi sẽ ghi nhớ ý tưởng đó, có lẽ nó có thể được cải thiện. Nó sẽ nhảy đến chữ số đầu tiên trên dòng hiện tại nếu có và hoạt động trên nó. Tốt nhất là có thể ánh xạ đến <c-a>/<c-x>cũng.
fireev

Phiên bản cập nhật. Bây giờ nhảy tới số tiếp theo hoặc nếu bạn hiện trên một chữ số cho phép bạn tăng nó.
jecxjo

Đúng! Điều này thật tuyệt vời, cảm ơn bạn! Tôi không hiểu tại sao câu hỏi lại bị hạ thấp, điều này gây khó chịu cho tôi kể từ ngày đầu tiên và rõ ràng nhiều người định nghĩa lại <c-a><c-x>một điều gì khác bởi vì hành vi mặc định không hữu ích.
fireev

Tôi có thể thấy nó bị hạ cấp bởi vì câu hỏi dành cho một cái gì đó rất cụ thể và loại câu hỏi ban đầu đã thay đổi trên đường đi ... sự cần thiết phải chuyển sang số đầu tiên. Điều đó sang một bên, tôi thực sự sử dụng <c-a><c-x>rất nhiều. Bất cứ khi nào tôi cập nhật một phiên bản hoặc tăng một biến phạm vi, tôi chỉ [N]<c-a>thay vì xóa và thay thế.
jecxjo

1
Nó có thể nhưng sẽ là một tập hợp các hàm lớn hơn nhiều. Việc triển khai hiện tại tận dụng lợi thế <c-a><c-x>cần phải bỏ đi cho một chức năng tương tự nhưng bỏ qua dấu gạch ngang.
jecxjo

5

Đây là phiên bản tôi đã viết bằng biểu thức thay thế:

map <c-a> :s/\d/\=submatch(0) < 9 ? submatch(0) + 1 : submatch(0)/<CR>
map <c-x> :s/\d/\=submatch(0) > 0 ? submatch(0) - 1 : submatch(0)/<CR>

Mỗi người chỉ tìm ký tự chữ số đầu tiên trên dòng và cộng hoặc trừ một ký tự nếu nó nằm trong phạm vi [0-8] hoặc [1-9], tương ứng. Nó có ba vấn đề:

  1. Nó chủ yếu là thao tác văn bản và chỉ nhìn vào ký tự đầu tiên, vì vậy nó không biết liệu một số có âm hay không. Điều này có thể sửa được, nhưng tôi thích hành vi hiện tại như hiện tại.
  2. Nó ghi đè thanh ghi tìm kiếm: "/và nếu bạn có hlsearch trên, thì tất cả các số trong bộ đệm hiện tại sẽ được tô sáng khi bạn sử dụng. Bạn có thể nối thêm :noh<CR>vào từng maplệnh trên để dừng tô sáng, nhưng tôi không biết làm thế nào để ngăn chặn thanh ghi không bị ghi đè.
  3. Nó hoạt động trên số đầu tiên trên dòng, không phải số đầu tiên sau con trỏ.

Ngoài ra, nếu là tôi, tôi sẽ ánh xạ ở trên <leader>a<leader>x, hơn là CTRL-A/X. Bằng cách này, bạn có cả hai hành vi có sẵn cho bạn. <leader>theo mặc định là phím dấu gạch chéo ngược ( \).


Thực tế là nó bỏ qua số âm là tốt, trên thực tế hành vi mặc định có vẻ lạ đối với tôi. Tôi nghĩ rằng nó có vẻ tốt hơn nhiều với :nohlà tốt. Nhưng vấn đề thực sự là nó không thể sử dụng vị trí con trỏ làm cơ sở và do đó bạn chỉ có thể tăng chữ số đầu tiên trong dòng.
fireev

Điều này dừng lại ở số 9, và trên 10, nó tăng lên 11, không phải 10 ... Tôi nghĩ rằng điều này là vô ý (tức là một lỗi)? Ngoài ra, bạn luôn muốn sử dụng ánh xạ không đệ quy ( noremap) và không bao giờ map . Xem trang này để được giải thích chi tiết hơn về điều đó.
Martin Tournoij
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.