💾 Archived View for gmi.noulin.net › gitRepositories › systemSetup › file › dotfiles › .vim › plugin… captured on 2024-08-18 at 18:53:56. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

systemSetup

Log

Files

Refs

README

LICENSE

dirdiff.vim (30620B)

     1 " -*- vim -*-
     2 " FILE: "/home/wlee/.vim/plugin/DirDiff.vim" {{{
     3 " LAST MODIFICATION: "Wed, 11 Apr 2012 15:49:03 -0500 (wlee)"
     4 " HEADER MAINTAINED BY: N/A
     5 " VERSION: 1.1.5
     6 " (C) 2001-2015 by William Lee, <wl1012@yahoo.com>
     7 " }}}
     8 
     9 " Public Interface:
    10 command! -nargs=* -complete=dir DirDiff call <SID>DirDiff (<f-args>)
    11 command! -nargs=0 DirDiffOpen call <SID>DirDiffOpen ()
    12 command! -nargs=0 DirDiffNext call <SID>DirDiffNext ()
    13 command! -nargs=0 DirDiffPrev call <SID>DirDiffPrev ()
    14 command! -nargs=0 DirDiffUpdate call <SID>DirDiffUpdate ()
    15 command! -nargs=0 DirDiffQuit call <SID>DirDiffQuit ()
    16 
    17 " The following comamnds can be used in the Vim diff mode:
    18 " 
    19 " \dg - Diff get: maps to :diffget<CR>
    20 " \dp - Diff put: maps to :diffput<CR>
    21 " \dj - Diff next: (think j for down) 
    22 " \dk - Diff previous: (think k for up)
    23 
    24 if !exists("g:DirDiffEnableMappings")
    25     let g:DirDiffEnableMappings = 0
    26 endif
    27 
    28 if g:DirDiffEnableMappings
    29     nnoremap <unique> <Leader>dg :diffget<CR>
    30     nnoremap <unique> <Leader>dp :diffput<CR>
    31     nnoremap <unique> <Leader>dj :DirDiffNext<CR>
    32     nnoremap <unique> <Leader>dk :DirDiffPrev<CR>
    33 endif
    34 
    35 " Global Maps:
    36 
    37 " Default Variables.  You can override these in your global variables
    38 " settings.
    39 "
    40 " For DirDiffExcludes and DirDiffIgnore, separate different patterns with a
    41 " ',' (comma and no space!).
    42 "
    43 " eg. in your .vimrc file: let g:DirDiffExcludes = "CVS,*.class,*.o"
    44 "                          let g:DirDiffIgnore = "Id:"
    45 "                          " ignore white space in diff
    46 "                          let g:DirDiffAddArgs = "-w" 
    47 "
    48 " You can set the pattern that diff excludes.  Defaults to the CVS directory
    49 if !exists("g:DirDiffExcludes")
    50     let g:DirDiffExcludes = ""
    51 endif
    52 " This is the -I argument of the diff, ignore the lines of differences that
    53 " matches the pattern
    54 if !exists("g:DirDiffIgnore")
    55     let g:DirDiffIgnore = ""
    56 endif
    57 if !exists("g:DirDiffSort")
    58     let g:DirDiffSort = 1
    59 endif
    60 if !exists("g:DirDiffWindowSize")
    61     let g:DirDiffWindowSize = 14
    62 endif
    63 if !exists("g:DirDiffInteractive")
    64     let g:DirDiffInteractive = 0
    65 endif
    66 if !exists("g:DirDiffIgnoreCase")
    67     let g:DirDiffIgnoreCase = 0
    68 endif
    69 " Additional arguments
    70 if !exists("g:DirDiffAddArgs")
    71     let g:DirDiffAddArgs = ""
    72 endif
    73 " Support for i18n (dynamically figure out the diff text)
    74 " Defaults to off
    75 if !exists("g:DirDiffDynamicDiffText")
    76     let g:DirDiffDynamicDiffText = 0
    77 endif
    78 
    79 " String used for the English equivalent "Files "
    80 if !exists("g:DirDiffTextFiles")
    81     let g:DirDiffTextFiles = "Files "
    82 endif
    83 
    84 " String used for the English equivalent " and "
    85 if !exists("g:DirDiffTextAnd")
    86     let g:DirDiffTextAnd = " and "
    87 endif
    88 
    89 " String used for the English equivalent " differ")
    90 if !exists("g:DirDiffTextDiffer")
    91     let g:DirDiffTextDiffer = " differ"
    92 endif
    93 
    94 " String used for the English equivalent "Only in ")
    95 if !exists("g:DirDiffTextOnlyIn")
    96     let g:DirDiffTextOnlyIn = "Only in "
    97 endif
    98 
    99 " String used for the English equivalent ": ")
   100 if !exists("g:DirDiffTextOnlyInCenter")
   101     let g:DirDiffTextOnlyInCenter = ": "
   102 endif
   103 
   104 " Set some script specific variables:
   105 "
   106 let s:DirDiffFirstDiffLine = 6
   107 let s:DirDiffALine = 1
   108 let s:DirDiffBLine = 2
   109 
   110 " -- Variables used in various utilities
   111 if has("unix")
   112     let s:DirDiffCopyCmd = "cp"
   113     let s:DirDiffCopyFlags = ""
   114     let s:DirDiffCopyDirCmd = "cp"
   115     let s:DirDiffCopyDirFlags = "-rf"
   116     let s:DirDiffCopyInteractiveFlag = "-i"
   117 
   118     let s:DirDiffDeleteCmd = "rm"
   119     let s:DirDiffDeleteFlags = ""
   120     let s:DirDiffDeleteInteractiveFlag = "-i"
   121 
   122     let s:DirDiffDeleteDirCmd = "rm"
   123     let s:DirDiffDeleteDirFlags = "-rf"
   124 
   125     let s:sep = "/"
   126 
   127     let s:DirDiffMakeDirCmd  = "!mkdir "
   128 
   129 elseif has("win32")
   130     let s:DirDiffCopyCmd = "copy"
   131     let s:DirDiffCopyFlags = ""
   132     let s:DirDiffCopyDirCmd = "xcopy"
   133     let s:DirDiffCopyDirFlags = "/e /i /q"
   134     let s:DirDiffCopyInteractiveFlag = "/-y"
   135 
   136     let s:DirDiffDeleteCmd = "del"
   137     let s:DirDiffDeleteFlags = "/s /q"
   138     let s:DirDiffDeleteInteractiveFlag = "/p"
   139     " Windows is somewhat stupid since "del" can only remove the files, not
   140     " the directory.  The command "rd" would remove files recursively, but it
   141     " doesn't really work on a file (!).  where is the deltree command???
   142      
   143     let s:DirDiffDeleteDirCmd = "rd"
   144     " rd is by default prompting, we need to handle this in a different way
   145     let s:DirDiffDeleteDirFlags = "/s"
   146     let s:DirDiffDeleteDirQuietFlag = "/q"
   147 
   148     let s:sep = "\\"
   149 
   150     let s:DirDiffMakeDirCmd  = "!mkdir "
   151 else
   152     " Platforms not supported
   153     let s:DirDiffCopyCmd = ""
   154     let s:DirDiffCopyFlags = ""
   155     let s:DirDiffDeleteCmd = ""
   156     let s:DirDiffDeleteFlags = ""
   157     let s:sep = ""
   158 endif
   159 
   160 
   161 function! <SID>DirDiff(srcA, srcB)
   162     " Setup
   163     let DirDiffAbsSrcA = fnamemodify(expand(a:srcA, ":p"), ":p")
   164     let DirDiffAbsSrcB = fnamemodify(expand(a:srcB, ":p"), ":p")
   165 
   166     " Check for an internationalized version of diff ?
   167     call <SID>GetDiffStrings()
   168 
   169     " Remove the trailing \ or /
   170     let DirDiffAbsSrcA = substitute(DirDiffAbsSrcA, '\\$\|/


, '', '')
   171     let DirDiffAbsSrcB = substitute(DirDiffAbsSrcB, '\\$\|/


, '', '')
   172 
   173     let DiffBuffer = tempname()
   174     " We first write to that file
   175     " Constructs the command line
   176     let cmd = "!diff"
   177     let cmdarg = " -r --brief"
   178 
   179     " If variable is set, we ignore the case
   180     if (g:DirDiffIgnoreCase)
   181         let cmdarg = cmdarg." -i"
   182     endif
   183     if (g:DirDiffAddArgs != "")
   184         let cmdarg = cmdarg." ".g:DirDiffAddArgs." "
   185     endif
   186     if (g:DirDiffExcludes != "")
   187         let cmdarg = cmdarg.' -x"'.substitute(g:DirDiffExcludes, ',', '" -x"', 'g').'"'
   188     endif
   189     if (g:DirDiffIgnore != "")
   190         let cmdarg = cmdarg.' -I"'.substitute(g:DirDiffIgnore, ',', '" -I"', 'g').'"'
   191     endif
   192     " Prompt the user for additional arguments
   193 "    let addarg = input("Additional diff args (current =". cmdarg. "): ")
   194     let addarg = ""
   195     let cmd = cmd.cmdarg." ".addarg." \"".DirDiffAbsSrcA."\" \"".DirDiffAbsSrcB."\""
   196     let cmd = cmd." > \"".DiffBuffer."\""
   197 
   198     echo "Diffing directories, it may take a while..."
   199     let error = <SID>DirDiffExec(cmd, 0)
   200     if (error == 0)
   201         redraw | echom "diff found no differences - directories match."
   202         return
   203     endif
   204     silent exe "edit ".DiffBuffer
   205     echo "Defining [A] and [B] ... "
   206     " We then do a substitution on the directory path
   207     " We need to do substitution of the the LONGER string first, otherwise
   208     " it'll mix up the A and B directory
   209     if (strlen(DirDiffAbsSrcA) > strlen(DirDiffAbsSrcB))
   210             silent! exe "%s/".<SID>EscapeDirForRegex(DirDiffAbsSrcA)."/[A]/"
   211             silent! exe "%s/".<SID>EscapeDirForRegex(DirDiffAbsSrcB)."/[B]/"
   212     else
   213             silent! exe "%s/".<SID>EscapeDirForRegex(DirDiffAbsSrcB)."/[B]/"
   214             silent! exe "%s/".<SID>EscapeDirForRegex(DirDiffAbsSrcA)."/[A]/"
   215     endif
   216     " In windows, diff behaves somewhat weirdly, for the appened path it'll
   217     " use "/" instead of "\".  Convert this to \
   218     if (has("win32"))
   219         silent! %s/\//\\/g
   220     endif
   221 
   222     echo "Sorting entries ..."
   223     " We then sort the lines if the option is set
   224     if (g:DirDiffSort == 1)
   225         1,$call <SID>Sort("s:Strcmp")
   226     endif
   227 
   228     " Put in spacer in front of each line
   229     silent! %s/^/    /
   230 
   231     " We then put the file [A] and [B] on top of the diff lines
   232     call append(0, "[A]=". DirDiffAbsSrcA)
   233     call append(1, "[B]=". DirDiffAbsSrcB)
   234     if g:DirDiffEnableMappings
   235         call append(2, "Usage:   <Enter>/'o'=open,'s'=sync,'<Leader>dg'=diffget,'<Leader>dp'=diffput,'<Leader>dj'=next,'<Leader>dk'=prev, 'q'=quit")
   236     else
   237         call append(2, "Usage:   <Enter>/'o'=open,'s'=sync,'q'=quit")
   238     endif
   239     call append(3, "Options: 'u'=update,'x'=set excludes,'i'=set ignore,'a'=set args" )
   240     call append(4, "Diff Args:" . cmdarg)
   241     call append(5, "")
   242     " go to the beginning of the file
   243     0
   244     setlocal nomodified
   245     setlocal nomodifiable
   246     setlocal buftype=nowrite
   247     "setlocal buftype=nofile
   248     "setlocal bufhidden=delete
   249     setlocal bufhidden=hide
   250     setlocal nowrap
   251 
   252     " Set up local key bindings
   253     " 'n' actually messes with the search next pattern, I think using \dj and
   254     " \dk is enough.  Otherwise, use j,k, and enter.
   255 "    nnoremap <buffer> n :call <SID>DirDiffNext()<CR>
   256 "    nnoremap <buffer> p :call <SID>DirDiffPrev()<CR>
   257     nnoremap <buffer> s :. call <SID>DirDiffSync()<CR>
   258     vnoremap <buffer> s :call <SID>DirDiffSync()<CR>
   259     nnoremap <buffer> u :call <SID>DirDiffUpdate()<CR>
   260     nnoremap <buffer> x :call <SID>ChangeExcludes()<CR>
   261     nnoremap <buffer> a :call <SID>ChangeArguments()<CR>
   262     nnoremap <buffer> i :call <SID>ChangeIgnore()<CR>
   263     nnoremap <buffer> q :call <SID>DirDiffQuit()<CR>
   264 
   265     nnoremap <buffer> o    :call <SID>DirDiffOpen()<CR>
   266     nnoremap <buffer> <CR>  :call <SID>DirDiffOpen()<CR>  
   267     nnoremap <buffer> <2-Leftmouse> :call <SID>DirDiffOpen()<CR>
   268     call <SID>SetupSyntax()
   269 
   270     " Open the first diff
   271     call <SID>DirDiffNext()
   272 endfunction
   273 
   274 " Set up syntax highlighing for the diff window
   275 "function! <SID>SetupSyntax()
   276 function! <SID>SetupSyntax()
   277   if has("syntax") && exists("g:syntax_on") 
   278       "&& !has("syntax_items")
   279     syn match DirDiffSrcA               "\[A\]"
   280     syn match DirDiffSrcB               "\[B\]"
   281     syn match DirDiffUsage              "^Usage.*"
   282     syn match DirDiffOptions            "^Options.*"
   283     " exec 'syn match DirDiffFiles              "' . s:DirDiffDifferLine .'"'
   284     " exec 'syn match DirDiffOnly               "' . s:DirDiffDiffOnlyLine . '"'
   285     syn match DirDiffSelected           "^==>.*" contains=DirDiffSrcA,DirDiffSrcB
   286 
   287     hi def link DirDiffSrcA               Directory
   288     hi def link DirDiffSrcB               Type
   289     hi def link DirDiffUsage              Special
   290     hi def link DirDiffOptions            Special
   291     hi def link DirDiffFiles              String
   292     hi def link DirDiffOnly               PreProc
   293     hi def link DirDiffSelected           DiffChange
   294   endif
   295 endfunction
   296 
   297 " You should call this within the diff window
   298 function! <SID>DirDiffUpdate()
   299     let dirA = <SID>GetBaseDir("A")
   300     let dirB = <SID>GetBaseDir("B")
   301     call <SID>DirDiff(dirA, dirB)
   302 endfun
   303 
   304 " Quit the DirDiff mode
   305 function! <SID>DirDiffQuit()
   306     let in = confirm ("Are you sure you want to quit DirDiff?", "&Yes\n&No", 2)
   307     if (in == 1)
   308         call <SID>CloseDiffWindows()
   309         bd!
   310     endif
   311 endfun
   312 
   313 " Returns an escaped version of the path for regex uses
   314 function! <SID>EscapeDirForRegex(path)
   315     " This list is probably not complete, modify later
   316     return escape(a:path, "/\\[]$^~")
   317 endfunction
   318 
   319 " Close the opened diff comparison windows if they exist
   320 function! <SID>CloseDiffWindows()
   321     if (<SID>AreDiffWinsOpened())
   322         wincmd k
   323         " Ask the user to save if buffer is modified
   324         call <SID>AskIfModified()
   325         bd!
   326         " User may just have one window opened, we may not need to close
   327         " the second diff window
   328         if (&diff)
   329             call <SID>AskIfModified()
   330             bd!
   331         endif
   332     endif
   333 endfunction
   334 
   335 function! <SID>EscapeFileName(path)
   336         if (v:version >= 702)
   337                 return fnameescape(a:path)
   338         else
   339                 " This is not a complete list of escaped character, so it's
   340                 " not as sophisicated as the fnameescape, but this should
   341                 " cover most of the cases and should work for Vim version <
   342                 " 7.2
   343                 return escape(a:path, " \t\n*?[{`$\\%#'\"|!<")
   344         endif
   345 endfunction
   346 
   347 function! <SID>EchoErr(varName, varValue)
   348         echoe '' . a:varName . ' : ' . a:varValue
   349 endfunction
   350 
   351 function! <SID>DirDiffOpen()
   352     " First dehighlight the last marked
   353     call <SID>DeHighlightLine()
   354 
   355         let buffNumber = bufnr('%')
   356     let line = getline(".")
   357 
   358     " We first parse back the [A] and [B] directories from the top of the line
   359     let dirA = <SID>GetBaseDir("A")
   360     let dirB = <SID>GetBaseDir("B")
   361 
   362 
   363     " Save the number of this window, to which we wish to return
   364     " This is required in case there are other windows open
   365         " let thisWindow = winnr()
   366         "let thisWindow = winnr(buffNumber)
   367 
   368         exec 'buffer ' . buffNumber
   369 
   370     call <SID>CloseDiffWindows()
   371     " Mark the current location of the line
   372     "mark n
   373     let b:currentDiff = line(".")
   374 
   375     " Ensure we're in the right window
   376     " silent! exec thisWindow.'wincmd w'
   377 
   378     " Parse the line and see whether it's a "Only in" or "Files Differ"
   379     call <SID>HighlightLine()
   380     let fileA = <SID>GetFileNameFromLine("A", line)
   381     let fileB = <SID>GetFileNameFromLine("B", line)
   382     if <SID>IsOnly(line)
   383         " We open the file
   384         let fileSrc = <SID>ParseOnlySrc(line)
   385         if (fileSrc == "A")
   386             let fileToOpen = fileA
   387         elseif (fileSrc == "B")
   388             let fileToOpen = fileB
   389         endif
   390         split
   391         wincmd k
   392         silent exec "edit ". <SID>EscapeFileName(fileToOpen)
   393         " Fool the window saying that this is diff
   394         diffthis
   395         wincmd j
   396         " Resize the window
   397         exe("resize " . g:DirDiffWindowSize)
   398         exe (b:currentDiff)
   399     elseif <SID>IsDiffer(line)
   400         "Open the diff windows
   401         split
   402         wincmd k
   403         silent exec "edit ".<SID>EscapeFileName(fileB)
   404 
   405         " To ensure that A is on the left and B on the right, splitright must be off
   406         " let saved_splitright = &splitright
   407         " set nosplitright
   408         " silent exec "vert diffsplit ".<SID>EscapeFileName(fileA)
   409         " let &splitright = saved_splitright
   410         silent exec "leftabove vert diffsplit ".<SID>EscapeFileName(fileA)
   411 
   412         " Go back to the diff window
   413         wincmd j
   414         " Resize the window
   415         exe("resize " . g:DirDiffWindowSize)
   416         exe (b:currentDiff)
   417         " Center the line
   418         exe ("normal z.")
   419     else
   420         echo "There is no diff at the current line!"
   421     endif
   422 endfunction
   423 
   424 " Ask the user to save if the buffer is modified
   425 "
   426 function! <SID>AskIfModified()
   427     if (&modified)
   428         let input = confirm("File " . expand("%:p") . " has been modified.", "&Save\nCa&ncel", 1)
   429         if (input == 1)
   430             w!
   431         endif
   432     endif
   433 endfunction
   434 
   435 
   436 function! <SID>HighlightLine()
   437     let savedLine = line(".")
   438     exe (b:currentDiff)
   439     setlocal modifiable
   440     let line = getline(".")
   441     if (match(line, "^    ") == 0)
   442         s/^    /==> /
   443     endif
   444     setlocal nomodifiable
   445     setlocal nomodified
   446     exe (savedLine)
   447     " This is necessary since the modified file would make the syntax
   448     " disappear.
   449     call <SID>SetupSyntax()
   450     redraw
   451 endfunction
   452 
   453 function! <SID>DeHighlightLine()
   454     let savedLine = line(".")
   455     exe (b:currentDiff)
   456     let line = getline(".")
   457     setlocal modifiable
   458     if (match(line, "^==> ") == 0)
   459         s/^==> /    /
   460     endif
   461     setlocal nomodifiable
   462     setlocal nomodified
   463     exe (savedLine)
   464     redraw
   465 endfunction
   466 
   467 " Returns the directory for buffer "A" or "B".  You need to be in the diff
   468 " buffer though.
   469 function! <SID>GetBaseDir(diffName)
   470     let currLine = line(".")
   471     if (a:diffName == "A")
   472         let baseLine = s:DirDiffALine
   473     else
   474         let baseLine = s:DirDiffBLine
   475     endif
   476     let regex = '\['.a:diffName.'\]=\(.*\)'
   477     let line = getline(baseLine)
   478     let rtn = substitute(line, regex , '\1', '')
   479     return rtn
   480 endfunction
   481 
   482 function! <SID>DirDiffNext()
   483     " If the current window is a diff, go down one
   484     if (&diff == 1)
   485         wincmd j
   486     endif
   487     " if the current line is <= 6, (within the header range), we go to the
   488     " first diff line open it
   489     if (line(".") < s:DirDiffFirstDiffLine)
   490         exe (s:DirDiffFirstDiffLine)
   491         let b:currentDiff = line(".")
   492     endif
   493     silent! exe (b:currentDiff + 1)
   494     call <SID>DirDiffOpen()
   495 endfunction
   496 
   497 function! <SID>DirDiffPrev()
   498     " If the current window is a diff, go down one
   499     if (&diff == 1)
   500         wincmd j
   501     endif
   502     silent! exe (b:currentDiff - 1)
   503     call <SID>DirDiffOpen()
   504 endfunction
   505 
   506 " For each line, we can perform a recursive copy or delete to sync up the
   507 " difference. Returns non-zero if the operation is NOT successful, returns 0
   508 " if everything is fine.
   509 "
   510 function! <SID>DirDiffSyncHelper(AB, line)
   511     let fileA = <SID>GetFileNameFromLine("A", a:line)
   512     let fileB = <SID>GetFileNameFromLine("B", a:line)
   513 "    echo "Helper line is ". a:line. " fileA " . fileA . " fileB " . fileB
   514     if <SID>IsOnly(a:line)
   515         " If a:AB is "A" and the ParseOnlySrc returns "A", that means we need to
   516         " copy
   517         let fileSrc = <SID>ParseOnlySrc(a:line)
   518         let operation = ""
   519         if (a:AB == "A" && fileSrc == "A")
   520             let operation = "Copy"
   521             " Use A, and A has source, thus copy the file from A to B
   522             let fileFrom = fileA
   523             let fileTo = fileB
   524         elseif (a:AB == "A" && fileSrc == "B")
   525             let operation = "Delete"
   526             " Use A, but B has source, thus delete the file from B
   527             let fileFrom = fileB
   528             let fileTo = fileA
   529         elseif (a:AB == "B" && fileSrc == "A")
   530             let operation = "Delete"
   531             " Use B, but the source file is A, thus removing A
   532             let fileFrom = fileA
   533             let fileTo = fileB
   534         elseif (a:AB == "B" && fileSrc == "B")
   535             " Use B, and B has the source file, thus copy B to A
   536             let operation = "Copy"
   537             let fileFrom = fileB
   538             let fileTo = fileA
   539         endif
   540     elseif <SID>IsDiffer(a:line)
   541         " Copy no matter what
   542         let operation = "Copy"
   543         if (a:AB == "A")
   544             let fileFrom = fileA
   545             let fileTo = fileB
   546         elseif (a:AB == "B")
   547             let fileFrom = fileB
   548             let fileTo = fileA
   549         endif
   550     else 
   551         echo "There is no diff here!"
   552         " Error
   553         return 1
   554     endif
   555     if (operation == "Copy")
   556         let rtnCode = <SID>Copy(fileFrom, fileTo)
   557     elseif (operation == "Delete")
   558         let rtnCode = <SID>Delete(fileFrom)
   559     endif
   560     return rtnCode
   561 endfunction
   562 
   563 " Synchronize the range
   564 function! <SID>DirDiffSync() range
   565     let answer = 1
   566     let silence = 0
   567     let syncMaster = "A"
   568     let currLine = a:firstline
   569     let lastLine = a:lastline
   570     let syncCount = 0
   571 
   572     while ((currLine <= lastLine))
   573         " Update the highlight
   574         call <SID>DeHighlightLine()
   575         let b:currentDiff = currLine
   576         call <SID>HighlightLine()
   577         let line = getline(currLine)
   578         if (!silence)
   579             let answer = confirm(substitute(line, "^....", '', ''). "\nSynchronization option:" , "&A -> B\n&B -> A\nA&lways A\nAl&ways B\n&Skip\nCa&ncel", 6)
   580             if (answer == 1 || answer == 3)
   581                 let syncMaster = "A"
   582             endif
   583             if (answer == 2 || answer == 4)
   584                 let syncMaster = "B"
   585             endif
   586             if (answer == 3 || answer == 4)
   587                 let silence = 1
   588             endif
   589             if (answer == 5)
   590                 let currLine = currLine + 1
   591                 continue
   592             endif
   593             if (answer == 6)
   594                 break
   595             endif
   596         endif
   597 
   598 "        call <SID>DeHighlightLine()
   599         let rtnCode = <SID>DirDiffSyncHelper(syncMaster, line)
   600         if (rtnCode == 0)
   601             " Successful
   602             let syncCount = syncCount + 1
   603             " Assume that the line is synchronized, we delete the entry
   604             setlocal modifiable
   605             exe (currLine.",".currLine." delete")
   606             setlocal nomodifiable
   607             setlocal nomodified
   608             let lastLine = lastLine - 1
   609         else
   610             " Failed!
   611             let currLine = currLine + 1
   612         endif
   613     endwhile
   614     echo syncCount . " diff item(s) synchronized."
   615 endfunction
   616 
   617 " Return file "A" or "B" depending on the line given.  If it's a Only line,
   618 " either A or B does not exist, but the according value would be returned.
   619 function! <SID>GetFileNameFromLine(AB, line)
   620     " Determine where the source of the copy is.
   621     let dirA = <SID>GetBaseDir("A")
   622     let dirB = <SID>GetBaseDir("B")
   623 
   624     let fileToProcess = ""
   625 
   626     if <SID>IsOnly(a:line)
   627         let fileToProcess = <SID>ParseOnlyFile(a:line)
   628     elseif <SID>IsDiffer(a:line)
   629         let regex = '^.*' . s:DirDiffDifferLine . '\[A\]\(.*\)' . s:DirDiffDifferAndLine . '\[B\]\(.*\)' . s:DirDiffDifferEndLine . '.*



   630         let fileToProcess = substitute(a:line, regex, '\1', '')
   631     else
   632     endif
   633 
   634     "echo "line : " . a:line. "AB = " . a:AB . " File to Process " . fileToProcess
   635     if (a:AB == "A")
   636         return dirA . fileToProcess
   637     elseif (a:AB == "B")
   638         return dirB . fileToProcess
   639     else
   640         return ""
   641     endif
   642 endfunction
   643 
   644 "Returns the source (A or B) of the "Only" line
   645 function! <SID>ParseOnlySrc(line)
   646     return substitute(a:line, '^.*' . s:DirDiffDiffOnlyLine . '\[\(.\)\].*' . s:DirDiffDiffOnlyLineCenter . '.*', '\1', '')
   647 endfunction
   648 
   649 function! <SID>ParseOnlyFile(line)
   650     let regex = '^.*' . s:DirDiffDiffOnlyLine . '\[.\]\(.*\)' . s:DirDiffDiffOnlyLineCenter . '\(.*\)'
   651     let root = substitute(a:line, regex , '\1', '')
   652     let file = root . s:sep . substitute(a:line, regex , '\2', '')
   653     return file
   654 endfunction
   655 
   656 function! <SID>Copy(fileFromOrig, fileToOrig)
   657     let fileFrom = substitute(a:fileFromOrig, '/', s:sep, 'g')
   658     let fileTo = substitute(a:fileToOrig, '/', s:sep, 'g')
   659     echo "Copy from " . fileFrom . " to " . fileTo
   660     if (s:DirDiffCopyCmd == "")
   661         echo "Copy not supported on this platform"
   662         return 1
   663     endif
   664 
   665     " Constructs the copy command
   666     let copycmd = "!".s:DirDiffCopyCmd." ".s:DirDiffCopyFlags
   667     " Append the interactive flag
   668     if (g:DirDiffInteractive)
   669         let copycmd = copycmd . " " . s:DirDiffCopyInteractiveFlag
   670     endif
   671     let copycmd = copycmd . " \"".fileFrom."\" \"".fileTo."\""
   672 
   673     " Constructs the copy directory command
   674     let copydircmd = "!".s:DirDiffCopyDirCmd." ".s:DirDiffCopyDirFlags
   675     " Append the interactive flag
   676     if (g:DirDiffInteractive)
   677         let copydircmd = copydircmd . " " . s:DirDiffCopyInteractiveFlag
   678     endif
   679     let copydircmd = copydircmd . " \"".fileFrom."\" \"".fileTo."\""
   680 
   681     let error = 0
   682     if (isdirectory(fileFrom))
   683         let error = <SID>DirDiffExec(copydircmd, g:DirDiffInteractive)
   684     else
   685         let error = <SID>DirDiffExec(copycmd, g:DirDiffInteractive)
   686     endif
   687     if (error != 0)
   688         echo "Can't copy from " . fileFrom . " to " . fileTo
   689         return 1
   690     endif
   691     return 0
   692 endfunction
   693 
   694 " Would execute the command, either silent or not silent, by the
   695 " interactive flag ([0|1]).  Returns the v:shell_error after
   696 " executing the command.
   697 function! <SID>DirDiffExec(cmd, interactive)
   698     let error = 0
   699     if (a:interactive)
   700         exe (a:cmd)
   701         let error = v:shell_error
   702     else
   703         silent exe (a:cmd)
   704         let error = v:shell_error
   705     endif
   706 "    let d = input("DirDiffExec: " . a:cmd . " " . a:interactive . " returns " . v:shell_error)
   707     return error
   708 endfunction
   709 
   710 " Delete the file or directory.  Returns 0 if nothing goes wrong, error code
   711 " otherwise.
   712 function! <SID>Delete(fileFromOrig)
   713     let fileFrom = substitute(a:fileFromOrig, '/', s:sep, 'g')
   714     echo "Deleting from " . fileFrom
   715     if (s:DirDiffDeleteCmd == "")
   716         echo "Delete not supported on this platform"
   717         return 1
   718     endif
   719 
   720     let delcmd = ""
   721 
   722     if (isdirectory(fileFrom))
   723         let delcmd = "!".s:DirDiffDeleteDirCmd." ".s:DirDiffDeleteDirFlags
   724         if (g:DirDiffInteractive)
   725             " If running on Unix, and we're running in interactive mode, we
   726             " append the -i tag
   727             if (has("unix"))
   728                 let delcmd = delcmd . " " . s:DirDiffDeleteInteractiveFlag
   729             endif
   730         else
   731             " If running on windows, and we're not running in interactive
   732             " mode, we append the quite flag to the "rd" command
   733             if (has("win32"))
   734                 let delcmd = delcmd . " " . s:DirDiffDeleteDirQuietFlag
   735             endif
   736         endif
   737     else
   738         let delcmd = "!".s:DirDiffDeleteCmd." ".s:DirDiffDeleteFlags
   739         if (g:DirDiffInteractive)
   740             let delcmd = delcmd . " " . s:DirDiffDeleteInteractiveFlag
   741         endif
   742     endif
   743 
   744     let delcmd = delcmd ." \"".fileFrom."\""
   745     let error = <SID>DirDiffExec(delcmd, g:DirDiffInteractive)
   746     if (error != 0)
   747         echo "Can't delete " . fileFrom
   748     endif
   749     return error
   750 endfunction
   751 
   752 function! <SID>AreDiffWinsOpened()
   753     let currBuff = expand("%:p")
   754     let currLine = line(".")
   755     wincmd k
   756     let abovedBuff = expand("%:p")
   757     if (&diff)
   758         let abovedIsDiff = 1
   759     else
   760         let abovedIsDiff = 0
   761     endif
   762     " Go Back if the aboved buffer is not the same
   763     if (currBuff != abovedBuff)
   764         wincmd j
   765         " Go back to the same line
   766         exe (currLine)
   767         if (abovedIsDiff == 1)
   768             return 1
   769         else
   770             " Aboved is just a bogus buffer, not a diff buffer
   771             return 0
   772         endif
   773     else
   774         exe (currLine)
   775         return 0
   776     endif
   777 endfunction
   778 
   779 " The given line begins with the "Only in"
   780 function! <SID>IsOnly(line)        
   781     return (match(a:line, "^ *" . s:DirDiffDiffOnlyLine . "\\|^==> " . s:DirDiffDiffOnlyLine ) == 0)
   782 endfunction
   783 
   784 " The given line begins with the "Files"
   785 function! <SID>IsDiffer(line)
   786     return (match(a:line, "^ *" . s:DirDiffDifferLine . "\\|^==> " . s:DirDiffDifferLine  ) == 0)
   787 endfunction
   788 
   789 " Let you modify the Exclude patthern
   790 function! <SID>ChangeExcludes()
   791     let g:DirDiffExcludes = input ("Exclude pattern (separate multiple patterns with ','): ", g:DirDiffExcludes)
   792     echo "\nPress update ('u') to refresh the diff."
   793 endfunction
   794 
   795 " Let you modify additional arguments for diff
   796 function! <SID>ChangeArguments()
   797     let g:DirDiffAddArgs = input ("Additional diff args: ", g:DirDiffAddArgs)
   798     echo "\nPress update ('u') to refresh the diff."
   799 endfunction
   800 
   801 " Let you modify the Ignore patthern
   802 function! <SID>ChangeIgnore()
   803     let g:DirDiffIgnore = input ("Ignore pattern (separate multiple patterns with ','): ", g:DirDiffIgnore)
   804     echo "\nPress update ('u') to refresh the diff."
   805 endfunction
   806 
   807 " Sorting functions from the Vim docs.  Use this instead of the sort binary.
   808 "
   809 " Function for use with Sort(), to compare two strings.
   810 func! <SID>Strcmp(str1, str2)
   811   if (a:str1 < a:str2)
   812         return -1
   813   elseif (a:str1 > a:str2)
   814         return 1
   815   else
   816         return 0
   817   endif
   818 endfunction
   819 
   820 " Sort lines.  SortR() is called recursively.
   821 func! <SID>SortR(start, end, cmp)
   822   if (a:start >= a:end)
   823         return
   824   endif
   825   let partition = a:start - 1
   826   let middle = partition
   827   let partStr = getline((a:start + a:end) / 2)
   828   let i = a:start
   829   while (i <= a:end)
   830         let str = getline(i)
   831         exec "let result = " . a:cmp . "(str, partStr)"
   832         if (result <= 0)
   833             " Need to put it before the partition.  Swap lines i and partition.
   834             let partition = partition + 1
   835             if (result == 0)
   836                 let middle = partition
   837             endif
   838             if (i != partition)
   839                 let str2 = getline(partition)
   840                 call setline(i, str2)
   841                 call setline(partition, str)
   842             endif
   843         endif
   844         let i = i + 1
   845   endwhile
   846 
   847   " Now we have a pointer to the "middle" element, as far as partitioning
   848   " goes, which could be anywhere before the partition.  Make sure it is at
   849   " the end of the partition.
   850   if (middle != partition)
   851         let str = getline(middle)
   852         let str2 = getline(partition)
   853         call setline(middle, str2)
   854         call setline(partition, str)
   855   endif
   856   call <SID>SortR(a:start, partition - 1, a:cmp)
   857   call <SID>SortR(partition + 1, a:end, a:cmp)
   858 endfunc
   859 
   860 " To Sort a range of lines, pass the range to Sort() along with the name of a
   861 " function that will compare two lines.
   862 func! <SID>Sort(cmp) range
   863   call <SID>SortR(a:firstline, a:lastline, a:cmp)
   864 endfunc
   865 
   866 " Added to deal with internationalized version of diff, which returns a
   867 " different string than "Files ... differ" or "Only in ... "
   868 
   869 function! <SID>GetDiffStrings()
   870     " Check if we have the dynamic text string turned on.  If not, just return
   871     " what's set in the global variables
   872 
   873     if (g:DirDiffDynamicDiffText == 0)
   874         let s:DirDiffDiffOnlyLineCenter = g:DirDiffTextOnlyInCenter
   875         let s:DirDiffDiffOnlyLine = g:DirDiffTextOnlyIn
   876         let s:DirDiffDifferLine = g:DirDiffTextFiles
   877         let s:DirDiffDifferAndLine = g:DirDiffTextAnd
   878         let s:DirDiffDifferEndLine = g:DirDiffTextDiffer
   879         return
   880     endif
   881 
   882         let tmp1 = tempname()
   883         let tmp2 = tempname()
   884         let tmpdiff = tempname()
   885 
   886     " We need to pad the backslashes in order to make it match
   887     let tmp1rx = <SID>EscapeDirForRegex(tmp1)
   888     let tmp2rx = <SID>EscapeDirForRegex(tmp2)
   889     let tmpdiffrx = <SID>EscapeDirForRegex(tmpdiff)
   890 
   891         silent exe s:DirDiffMakeDirCmd . "\"" . tmp1 . "\""
   892         silent exe s:DirDiffMakeDirCmd . "\"" . tmp2 . "\""
   893         silent exe "!echo test > \"" . tmp1 . s:sep . "test" . "\""
   894         silent exe "!diff -r --brief \"" . tmp1 . "\" \"" . tmp2 . "\" > \"" . tmpdiff . "\""
   895 
   896         " Now get the result of that diff cmd
   897         silent exe "split ". tmpdiff
   898     "echo "First line: " . getline(1)
   899     "echo "tmp1: " . tmp1
   900     "echo "tmp1rx: " . tmp1rx
   901     let regex = '\(^.*\)' . tmp1rx . '\(.*\)' . "test"
   902         let s:DirDiffDiffOnlyLine = substitute( getline(1), regex, '\1', '') 
   903         let s:DirDiffDiffOnlyLineCenter = substitute( getline(1), regex, '\2', '') 
   904     "echo "DirDiff Only: " . s:DirDiffDiffOnlyLine
   905         
   906         q
   907 
   908         " Now let's get the Differ string
   909     "echo "Getting the diff in GetDiffStrings"
   910         
   911         silent exe "!echo testdifferent > \"" . tmp2 . s:sep . "test" . "\""
   912         silent exe "!diff -r --brief \"" . tmp1 . "\" \"" . tmp2 . "\" > \"" . tmpdiff . "\""
   913         
   914         silent exe "split ". tmpdiff
   915         let s:DirDiffDifferLine = substitute( getline(1), tmp1rx . ".*$", "", '') 
   916     " Note that the diff on cygwin may output '/' instead of '\' for the
   917     " separator, so we need to accomodate for both cases
   918     let andrx = "^.*" . tmp1rx . "[\\\/]test\\(.*\\)" . tmp2rx . "[\\\/]test.*$"
   919     let endrx = "^.*" . tmp1rx . "[\\\/]test.*" . tmp2rx . "[\\\/]test\\(.*$\\)"
   920     "echo "andrx : " . andrx
   921     "echo "endrx : " . endrx
   922         let s:DirDiffDifferAndLine = substitute( getline(1), andrx , "\\1", '') 
   923     let s:DirDiffDifferEndLine = substitute( getline(1), endrx, "\\1", '') 
   924 
   925         "echo "s:DirDiffDifferLine = " . s:DirDiffDifferLine
   926         "echo "s:DirDiffDifferAndLine = " . s:DirDiffDifferAndLine
   927         "echo "s:DirDiffDifferEndLine = " . s:DirDiffDifferEndLine
   928 
   929         q
   930 
   931         " Delete tmp files
   932     "echo "Deleting tmp files."
   933 
   934         call <SID>Delete(tmp1)
   935         call <SID>Delete(tmp2)
   936         call <SID>Delete(tmpdiff)
   937 
   938         "avoid get diff text again
   939         let g:DirDiffTextOnlyInCenter = s:DirDiffDiffOnlyLineCenter
   940         let g:DirDiffTextOnlyIn = s:DirDiffDiffOnlyLine
   941         let g:DirDiffTextFiles = s:DirDiffDifferLine
   942         let g:DirDiffTextAnd = s:DirDiffDifferAndLine
   943         let g:DirDiffTextDiffer = s:DirDiffDifferEndLine
   944         let g:DirDiffDynamicDiffText = 0
   945 
   946 endfunction