क्या मैं अधिसूचित किया जा सकता हूं जब मैं पूर्ववत से परिवर्तन पूर्ववत कर रहा हूं?


15

मैं कुछ समय के लिए विम में अनौपचारिक सुविधा का उपयोग कर रहा हूं । यह बहुत अच्छी सुविधा है।

हालाँकि, एक झुंझलाहट यह है कि गलती से किए गए परिवर्तनों को बदलना बहुत आसान है जो मैंने पिछली बार फ़ाइल खोलने के दौरान किया था; जो 2 मिनट पहले, एक घंटा पहले, अंतिम सप्ताह या एक महीने पहले हो सकता है।

उदाहरण के लिए, मान लें कि मैं एक फ़ाइल खोलता हूं, कुछ परिवर्तन करता हूं, बंद हो जाता हूं और कुछ अन्य फाइलें बदल देता हूं, और पता चलता है कि मेरे परिवर्तन आवश्यक नहीं थे, या शायद वे कुछ अस्थायी डीबग कथन थे।

इससे पहले, मैं सिर्फ uकुंजी पकड़ सकता था जब तक कि विम ने "पहले से ही सबसे पुराने बदलाव पर" नहीं कहा :wq, और किया जाए। लेकिन अब मुझे बहुत सावधानी बरतनी है कि मैंने पिछली बार जब मैंने फ़ाइल खोली थी, तो उन परिवर्तनों को पूर्ववत् न करूँ। यह देखने का कोई स्पष्ट तरीका नहीं है कि आप ऐसा कब कर रहे हैं।

क्या इसे और अधिक स्पष्ट करने का कोई तरीका है? उदाहरण के लिए इसे कहीं पर दिखा कर, चेतावनी जारी करके, या यहाँ तक कि पुष्टिकरण के लिए भी।


यह एक ऐसा प्रश्न है जिसे मैंने अनौपचारिक सुविधा के अनावरण के बाद से सोचा है, और एक मैं इस साइट के अनावरण के बाद से पूछने के लिए अर्थ प्राप्त कर रहा हूं! उम्मीद है कि एक अच्छा जवाब होगा। मुझे लगता है कि मैं उस उत्तर को भी स्वीकार करूंगा जिसने एक आदेश दिया था जो फाइल को उस स्थिति में वापस ले गया था जब आपने इसे पिछली बार खोला था। (या बेहतर है, उस पूर्ववत स्थिति में वापस आ गया।)
रिच

जवाबों:


8

मुझे यह सटीक समस्या थी। यहाँ है कि मैं अपने vimrc करने के लिए इसे मेरे लिए जोड़ा:

" Always write undo history, but only read it on demand
" use <leader>u to load old undo info
" modified from example in :help undo-persistence

if has('persistent_undo')
  set undodir=~/.vim/undo " location to store undofiles
  nnoremap <leader>u :call ReadUndo()<CR>
  au BufWritePost * call WriteUndo()
endif

func! ReadUndo()
  let undofile = undofile(expand('%'))
  if filereadable(undofile)
    let undofile = escape(undofile,'% ')
    exec "rundo " . undofile
  endif
endfunc

func! WriteUndo()
  let undofile = escape(undofile(expand('%')),'% ')
  exec "wundo " . undofile
endfunc

ध्यान दें कि आपने विकल्प निर्धारित नहीं किया है undofile; यदि आपके पास है तो आपको अपने vimrc से निकालना होगा।

पूर्ववत अब "सामान्य" के रूप में काम करता है। लेकिन हम करते हैं मैन्युअल रूप से पूर्ववत फ़ाइल पर लिखने wundoमें आदेश BufWritePost

ReadUndo()समारोह मैन्युअल के साथ पूर्ववत फ़ाइल पढ़ता है rundoऔर सेट undofileविकल्प। अब हम uइतिहास में वापस जाने के लिए उपयोग कर सकते हैं । मैंने इसे मैप किया <Leader>u

यह शायद बेहतर हो सकता है। यह पिछली पूर्ववत जानकारी को अधिलेखित कर देता है, इसलिए आप फ़ाइल को संपादित किए गए पिछले पिछली बार वापस नहीं जा सकते। लेकिन मुझे खुद इसकी जरूरत नहीं है।


नोट मैंने इसके साथ एक समस्या देखी है: आप केवल मौजूदा सत्र की सामग्री को पूर्ववत् फ़ाइल में सहेजते हैं। यह डिफ़ॉल्ट व्यवहार से अलग है, जहां पिछले सत्र की सामग्री + पूर्ववत फ़ाइल में पहले से मौजूद सभी जानकारी सहेज ली गई है ... इसे ठीक करने का तरीका, पूर्ववत फ़ाइल को पढ़ना, पूर्ववत परिवर्तनों को मर्ज करना और फिर लिखना होगा पूर्ववत फ़ाइल ... लेकिन यह संभव नहीं लगता है ...: - /
मार्टिन Tournoij

@Carpetsmoker मैं सहमत हूं। यह करना अच्छा होगा यदि यह संभव था। जैसा कि ऐसा होता है कि इसने मेरे लिए लंबे समय तक अच्छा काम किया है। YMMV।
सुपरजेर

5

ऊह, ऊह, आखिरकार इस निफ्टी कमांड को दिखाने का मौका !

विम "समय में वापस जा सकते हैं।" यह एक :earlierआदेश है ...

                                                        :ea :earlier            
:earlier {count}        Go to older text state {count} times.                   
:earlier {N}s           Go to older text state about {N} seconds before.        
:earlier {N}m           Go to older text state about {N} minutes before.        
:earlier {N}h           Go to older text state about {N} hours before.          
:earlier {N}d           Go to older text state about {N} days before.           

:earlier {N}f           Go to older text state {N} file writes before.          
                        When changes were made since the last write             
                        ":earlier 1f" will revert the text to the state when    
                        it was written.  Otherwise it will go to the write      
                        before that.                                            
                        When at the state of the first file write, or when      
                        the file was not written, ":earlier 1f" will go to      
                        before the first change.                                

... जो फ़ाइल को पिछली स्थिति में वापस ला सकता है। इसका उपयोग कई तरीकों से किया जा सकता है।

  • यदि आप बॉलपार्क का अनुमान लगा सकते हैं कि इन बदलावों को करने में आपको कितना समय लगा है, तो आप इस कमांड में एक समय फीड कर सकते हैं। या, उदाहरण के लिए, यदि आप जानते हैं कि आपने पिछले दिन फ़ाइल को नहीं बदला था (परिवर्तनों को पूर्ववत करना चाहते हैं) को छोड़कर, आप उपयोग कर सकते हैं

    :earlier 1d
    
  • यदि आपने केवल उस फ़ाइल को लिखा (सहेजा है) जिसे आप पूर्ववत करना चाहते हैं, या आपने फ़ाइल को बिल्कुल भी सहेजा नहीं है, तो आप इसका उपयोग कर सकते हैं

    :earlier 1f
    

    जैसा कि :helpपाठ में वर्णित है , यह पूर्व लिखित संस्करण पर वापस आ जाएगा यदि आपने अभी फ़ाइल लिखी है, या पिछली बार वापस लौटा दी गई थी यदि आपके पास कोई सहेजे गए परिवर्तन नहीं हैं।

यह आपके प्रश्न का सटीक उत्तर नहीं देता है, लेकिन यह एक XY समस्या की तरह लगता है।


1
यह एक XY समस्या का एक सा लगता है : क्यों? मैं पूर्ववत हूं u, और मैं गलती से उन परिवर्तनों को पार कर जाता हूं जो मैंने अभी किए हैं ... मुझे यकीन नहीं है कि मूल "एक्स-समस्या" यहां क्या हो सकती है?
मार्टिन टूरनोइज

1
मैं अब :earlierवैसे ही हूं, लेकिन मुझे अभी भी अनुमान लगाने की आवश्यकता है ; बस के रूप में मैं का उपयोग करते समय अनुमान लगाने की जरूरत है u... मामलों में यह शायद थोड़ा बेहतर है, लेकिन मैं कुछ और अधिक स्पष्ट (यदि संभव हो तो) पसंद करूंगा।
मार्टिन टूरनोइज

1
@Carpetsmoker "एक्स" है "मैं पूर्ववत करना चाहते हैं तो बस इन परिवर्तनों है कि मैं सबसे हाल ही में बनाया है।" "Y" है "मैं पूर्ववत कैसे बदल सकता हूं और अनदेखा कर सकता हूं?" आप अभी भी अनुमान लगाना चाहते हैं, लेकिन आपने अपने प्रश्न में कहा है कि आपके द्वारा किए गए अंतिम परिवर्तन पिछले सप्ताह या उससे पहले हुए थे, इसलिए आप ऐसा कुछ कर सकते हैं :ea 5d। आप :ea 1fदृष्टिकोण का उपयोग भी कर सकते हैं । किसी भी मामले में, यह बहुत कम दानेदार है।
डोरकनॉब

"X" और "Y" बस एक ही समस्या का एक rephrasing मुझे लगता है? मैंने अपने प्रश्न में "सप्ताह" का उल्लेख किया था, लेकिन यह भी घंटे, या मिनट हो सकता है (संशोधित किया गया है) ... यह इस तरह के रूप में एक बुरा जवाब नहीं है , मैं (और हूँ) बस उम्मीद है कि कुछ बेहतर है ...
मार्टिन टूरनोइज

मैं इस पर @Carpetsmoker के साथ हूं। मुझे इसके बारे में पता है: पहले कुछ समय के लिए, लेकिन मैं अभी भी इस सवाल में वर्णित कारण के लिए अनौपचारिक बंद कर दिया है।
रिच

4

अपडेट 2015-06-28 : मैंने एक छोटा बग तय किया , और इसे एक प्लगइन के रूप में जारी किया । प्लगइन कोड थोड़ा बेहतर है, इसमें वह कर्सर को स्थानांतरित करने के बाद फिर से चेतावनी देता है; मैं आपको प्लगइन का उपयोग करने की सलाह देता हूं।



सुपरजेर का जवाब बहुत अच्छा काम करता है, लेकिन दुर्भाग्यपूर्ण साइड-इफेक्ट है कि आप केवल पिछले विम सत्र से परिवर्तन कर सकते हैं, और पिछले सभी विम सत्र नहीं।

ऐसा इसलिए है क्योंकि wundoपूर्ववत् फ़ाइल को ओवरराइट कर देता है; इसका विलय नहीं हुआ है। जहां तक ​​मुझे पता है, इसे ठीक करने का कोई तरीका नहीं है।

तो यहाँ मेरा वैकल्पिक समाधान है, यह एक बड़ा लाल चेतावनी संदेश दिखाएगा जब आप पूर्ववत फ़ाइल से परिवर्तन पूर्ववत कर रहे हैं।

यह इंगो करकट के उत्तर के समान है , लेकिन इसमें बाहरी प्लगइन की आवश्यकता नहीं है और इसमें कुछ सूक्ष्म अंतर हैं (बीप के बजाय चेतावनी प्रदर्शित करता है, आपको uदो बार प्रेस करने की आवश्यकता नहीं है )।

ध्यान दें कि यह केवल संशोधित uऔर <C-r>बांधता है, और नहींU , :undoहै, और :redoआदेशों।

" Use the undo file
set undofile

" When loading a file, store the curent undo sequence
augroup undo
    autocmd!
    autocmd BufReadPost,BufCreate,BufNewFile * let b:undo_saved = undotree()['seq_cur'] | let b:undo_warned = 0
augroup end 

" Remap the keys
nnoremap u :call Undo()<Cr>u
nnoremap <C-r> <C-r>:call Redo()<Cr>


fun! Undo()
    " Don't do anything if we can't modify the buffer or there's no filename
    if !&l:modifiable || expand('%') == '' | return | endif

    " Warn if the current undo sequence is lower (older) than whatever it was
    " when opening the file
    if !b:undo_warned && undotree()['seq_cur'] <= b:undo_saved
        let b:undo_warned = 1
        echohl ErrorMsg | echo 'WARNING! Using undofile!' | echohl None
        sleep 1
    endif
endfun

fun! Redo()
    " Don't do anything if we can't modify the buffer or there's no filename
    if !&l:modifiable || expand('%') == '' | return | endif

    " Reset the warning flag
    if &l:modifiable && b:undo_warned && undotree()['seq_cur'] >= b:undo_saved
        let b:undo_warned = 0
    endif
endfun

3

मेरे पास निम्नलिखित हैं, जो जब पूर्ववत बफर सामग्री तक पहुंचता है तो रुक जाता है और बीप करता है।

runtime autoload/repeat.vim " Must load the plugin now so that the plugin's mappings can be overridden.
let s:undoPosition = []
function! s:StopAtSavedPosition( action )
    " Buffers of type "nofile" and "nowrite" never are 'modified', so only do
    " the check for normal buffers representing files. (Otherwise, the warning
    " annoyingly happens on every undo.)
    if ingo#buffer#IsPersisted() && ! &l:modified && s:undoPosition != ingo#record#PositionAndLocation(1)
        " We've reached the undo position where the buffer contents correspond
        " to the persisted file. Stop and beep, and only continue when undo is
        " pressed again at the same position.
        call ingo#msg#WarningMsg(a:action . ' reached saved buffer state')
        execute "normal! \<C-\>\<C-n>\<Esc>" | " Beep.

        let s:undoPosition = ingo#record#PositionAndLocation(1)
        return 1
    else
        let s:undoPosition = []
        return 0
    endif
endfunction
nnoremap <silent> u     :<C-U>if ! &l:modifiable<Bar>execute 'normal! u'<Bar>elseif ! <SID>StopAtSavedPosition('Undo')<Bar>call repeat#wrap('u',v:count)<Bar>endif<CR>
nnoremap <silent> <C-R> :<C-U>if ! &l:modifiable<Bar>execute "normal! \<lt>C-R>"<Bar>elseif ! <SID>StopAtSavedPosition('Redo')<Bar>call repeat#wrap("\<Lt>C-R>",v:count)<Bar>endif<CR>

यह repeat.vim प्लगइन के साथ एकीकृत करता है; इसके लिए मेरे इनगो-लाइब्रेरी प्लगइन की आवश्यकता है


क्या आप "राज़ी" का उपयोग कर रहे हैं, इसका मतलब है कि "राज्य उस समय था जब बफर लोड किया गया था?" मैं आमतौर पर डिस्क के लिए सहेजे गए फ़ाइल की स्थिति से मतलब रखने के लिए "लगातार" की उम्मीद करता हूं।
रिच

@ रीच: नहीं, हमारी एक ही परिभाषा है। मेरे मैपिंग बिल्कुल वैसा नहीं करते हैं जैसा प्रश्न पूछते हैं, लेकिन मैंने अभी भी इसे बहुत उपयोगी पाया है।
इंगो करकट

2

मुझे लगता है कि मैं उस उत्तर को भी स्वीकार करूंगा जिसने एक आदेश दिया था जो फाइल को उस स्थिति में वापस ले गया था जब आपने इसे पिछली बार खोला था। (या बेहतर है, उस पूर्ववत स्थिति में वापस कूद गए।)

> धनी

मुझे वास्तव में उद्धृत विचार पसंद आया इसलिए मैंने :Revertकमान बनाई । मुझे आशा है कि आप इसे अपने प्रश्न के लिए प्रासंगिक पाएंगे।

function! s:Real_seq(inner, outer) abort
  let node = a:outer
  for i in a:inner
    if has_key(i, 'alt')
      call s:Real_seq(i.alt, deepcopy(node))
    endif
    if has_key(i, 'curhead')
      return {'seq': node.seq}
    endif
    let node.seq  = i.seq
  endfor
endfunction

function! s:Get_seq(tree) abort
  let query = s:Real_seq(a:tree.entries, {'seq': 0})
  if (type(query) == 4)
    return query.seq
  else
    return undotree()['seq_cur']
  endif
endfunction

au BufReadPost,BufNewFile * if !exists('b:undofile_start') 
      \ | let b:undofile_start = s:Get_seq(undotree()) | endif

command! -bar Revert execute "undo " . get(b:, 'undofile_start', 0)

हेल्पर फ़ंक्शंस Get_seqऔर Real_seq, अंडरोट्री पर आधारित , आवश्यक हैं क्योंकि undotree()['seq_cur']कभी-कभी पूर्ववत पेड़ में वर्तमान स्थिति को इंगित करने के लिए पर्याप्त नहीं है। आप इसके बारे में और अधिक यहाँ पढ़ सकते हैं ।


यह एक अच्छा समाधान की तरह दिखता है। लेकिन आप में त्रुटि है auvimrc वहाँ में दोषी है। सीधे शब्दों में कहें तो इसे छोड़ दें
Naumann
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.