{"thread":{"id":"23810","subject":"[ANNOUNCE] diffit - A git plugin for vim","startedAt":"2010-05-15T10:50:09Z","lastAt":"2010-05-16T09:41:57Z","messageCount":4,"participants":["Clemens Buchacher","Jakub Narebski","Wincent Colaiuta"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"141720","messageId":"20100515105009.GA10517@localhost","threadId":"23810","inReplyTo":null,"subject":"[ANNOUNCE] diffit - A git plugin for vim","fromName":"Clemens Buchacher","fromEmail":"drizzd@aon.at","sentAt":"2010-05-15T10:50:09Z","receivedAt":"2010-05-15T10:50:09Z","isPatch":false,"sender":{"key":"drizzd@gmx.net","avatar":"https://avatars.githubusercontent.com/u/59082?v=4"},"body":"Hi,\n\nI am currently working on a git plugin for vim. My aim is for it to imitate\nmuch of git-gui's functionality. Right now, it is still closer to \"add -p\".\n\nBut I believe it's already useful. And since I'm new to vim scripting, it\ncan use some testing.\n\nTo install, copy diffit.vim (attached to this email) to\n~/.vim/plugin/diffit.vim .\n\nTo toggle diffit mode, use <Leader>d, where <Leader> is '\\' by default.\n\nControl keys:\n\n <Leader>d      toggle diffit mode\n s              stage hunk\n d              skip file\n\nI hope you like it. Have fun!\n\nClemens\n---\n\nYou can clone diffit from here.\n\n git://repo.or.cz/diffit.git\n http://github.com/drizzd/diffit.git\n\n\n\" ============================================================================\n\" File:        diffit.vim\n\" Description: Show diff for current buffer\n\" Maintainer:  Clemens Buchacher <drizzd@aon.at>\n\" License:     GPLv2\n\"\n\" ============================================================================\nif exists('loaded_diffit')\n    finish\nend\nlet loaded_diffit = 1\n\nlet s:diffit_version = '0'\n\n\"for line continuation - i.e dont want C in &cpo\nlet s:old_cpo = &cpo\nset cpo&vim\n\nmap <silent> <Leader>d :call <SID>Diffit()<CR>\n\nfunction s:Error(msg)\n\techohl ErrorMsg\n\techon 'diffit: ' . a:msg\n\techohl None\nendfunction\n\nfunction s:Info(msg)\n\techon 'diffit: ' . a:msg\nendfunction\n\nfunction s:Die(msg)\n\tcall s:Error('fatal: ' . a:msg)\n\tthrow \"diffit\"\nendfunction\n\nfunction s:System(...)\n\tlet out = system(join(a:000))\n\tif v:shell_error\n\t\tcall s:Die(a:0 . ' failed: ' . out)\n\tend\n\treturn out\nendfunction\n\nfunction s:Header()\n\tlet header = []\n\tfor n in range(1, line('$'))\n\t\t\tlet l = getline(n)\n\t\t\tif l =~ '^diff --git ' ||\n\t\t\t\t\t\t\\l =~ '^diff --cc ' ||\n\t\t\t\t\t\t\\l =~ '^diff --combined ' ||\n\t\t\t\t\t\t\\l =~ '^old mode ' ||\n\t\t\t\t\t\t\\l =~ '^new mode ' ||\n\t\t\t\t\t\t\\l =~ '^--- ' ||\n\t\t\t\t\t\t\\l =~ '^+++ '\n\t\t\t\tcall add(header, l)\n\t\t\t\tcontinue\n\t\t\tend\n\t\t\tif l !~ '^index '\n\t\t\t\tbreak\n\t\t\tend\n\tendfor\n\treturn [header, n - 1]\nendfunction\n\nfunction s:Exit()\n\tlet view = b:view\n\tbdelete\n\tcall winrestview(view)\nendfunction\n\nfunction s:Diffit()\n\tif exists('b:diffit') && b:diffit == 1\n\t\tcall s:Exit()\n\t\treturn\n\tend\n\ttry\n\t\tcall s:Diffit_init()\n\tcatch /^diffit$/\n\t\tif exists('b:diffit') && b:diffit == 1\n\t\t\tcall s:Exit()\n\t\tend\n\tendtry\nendfunction\n\nfunction s:Read_diff(pathlist)\n\tlet diff = tempname()\n\tlet path = ''\n\tfor path in a:pathlist\n\t\tlet out = s:System('git diff', '--', path, '>', diff)\n\t\tif getfsize(diff) > 0\n\t\t\tbreak\n\t\tend\n\tendfor\n\treturn [diff, path]\nendfunction\n\nfunction s:Write_diff(diff, orig)\n\tsetlocal modifiable\n\tsilent 1,$delete _\n\tsilent exe 'read ' . a:diff\n\tsilent 1delete _\n\tsetlocal nomodifiable\n\n\tif a:orig\n\t\tlet orig_pos = b:view['lnum']\n\t\tlet new_pos = s:Diffpos(orig_pos)\n\t\tlet view = copy(b:view)\n\t\tlet view['lnum'] = abs(new_pos)\n\t\tif new_pos > 0\n\t\t\tlet view['topline'] += new_pos - orig_pos\n\t\t\tlet view['topline'] = max([1, view['topline']])\n\t\telse\n\t\t\tlet view['topline'] = -new_pos - 4\n\t\tend\n\t\tlet view['curswant'] += 1\n\t\tlet view['col'] += 1\n\t\tcall winrestview(view)\n\telse\n\t\tcall cursor(abs(s:Diffpos(0)), 1)\n\tend\nendfunction\n\nfunction s:Diffit_init()\n\tupdate\n\tlet out = s:System('git rev-parse',  '--is-inside-work-tree')\n\tif v:shell_error == 128 || split(out)[0] != 'true'\n\t\tcall s:Error('not inside work tree')\n\t\treturn\n\telseif v:shell_error\n\t\tcall s:Error('git rev-parse failed: ' . out)\n\t\treturn\n\tend\n\tlet out = s:System('git diff', '--name-only')\n\tlet pathlist = split(out, '\\n')\n\tif empty(pathlist)\n\t\tcall s:Info('no changes')\n\t\treturn\n\tend\n\tlet orig_path = bufname('%')\n\tlet k = index(pathlist, orig_path)\n\tif k > 0\n\t\tcall remove(pathlist, k)\n\t\tcall insert(pathlist, orig_path, 0)\n\tend\n\tlet [diff, path] = s:Read_diff(pathlist)\n\tlet orig = path == orig_path\n\tif getfsize(diff) == 0\n\t\tcall s:Info('no changes')\n\t\treturn\n\tend\n\n\tlet view = winsaveview()\n\tsilent! exe 'edit ' . tempname()\n\tlet b:pathlist = pathlist\n\tlet b:view = view\n\tlet b:diffit = 1\n\tsetf git-diff\n\tsetlocal noswapfile\n\tsetlocal buftype=nofile\n\tsetlocal nowrap\n\tsetlocal foldcolumn=0\n\tsetlocal nobuflisted\n\n\tiabc <buffer>\n\n\tnnoremap <silent> <buffer> s :call <SID>Stage_hunk(line('.'))<CR>\n\tnnoremap <silent> <buffer> d :call <SID>Next_diff()<CR>\n\n\tcall s:Write_diff(diff, orig)\n\techon '\"' . path . '\"'\nendfunction\n\nfunction s:Next_diff()\n\tcall remove(b:pathlist, 0)\n\tlet [diff, path] = s:Read_diff(b:pathlist)\n\tif getfsize(diff) > 0\n\t\tcall s:Write_diff(diff, 0)\n\t\techon '\"' . path . '\"'\n\telse\n\t\tcall s:Exit()\n\tend\nendfunction\n\nfunction s:Diffpos(orig_pos)\n\tlet diffpos = -1\n\tlet hunk_start = 1\n\tlet hunk_end = 1\n\tcall cursor(1, 1)\n\twhile search('^@@', 'W') > 0\n\t\tlet [start, length] = matchlist(getline('.'),\n\t\t\t\\'^@@ -[0-9]*,[0-9]* +\\%(\\([0-9]*\\),\\)\\?\\([0-9]*\\)')[1:2]\n\t\tif empty(start)\n\t\t\tlet start = 1\n\t\tend\n\t\tif diffpos < 0\n\t\t\tlet diffpos = -line('.')\n\t\tend\n\t\tif start > a:orig_pos\n\t\t\tbreak\n\t\tend\n\t\tlet diffpos = line('.')\n\t\tlet hunk_start = start\n\t\tlet hunk_end = hunk_start + length - 1\n\tendwhile\n\tif diffpos < 0\n\t\treturn diffpos\n\tend\n\tlet pos = hunk_start - 1\n\tlet target_pos = min([a:orig_pos, hunk_end])\n\twhile diffpos < line('$')\n\t\tif getline(diffpos) =~ '^-'\n\t\t\tlet diffpos += 1\n\t\t\tcontinue\n\t\tend\n\t\tif pos >= target_pos\n\t\t\tbreak\n\t\tend\n\t\tlet diffpos += 1\n\t\tlet pos += 1\n\tendwhile\n\n\tif getline(diffpos) =~ '^-'\n\t\treturn -last\n\telse\n\t\treturn diffpos\n\tend\nendfunction\n\nfunction s:Stage_hunk(pos)\n\tcall cursor(a:pos, 1)\n\tlet h_start = search('^@@', 'bcW')\n\tif h_start == 0\n\t\treturn\n\tend\n\tcall cursor(h_start, 1)\n\tlet h_end = search('^@@', 'nW')-1\n\tif h_end < 0\n\t\tlet h_end = line('$')\n\tend\n\tlet h_range = h_start . ',' . h_end\n\n\tlet [patch, header_end] = s:Header()\n\tcall extend(patch, getline(h_start, h_end))\n\tlet patchfile = tempname()\n\tcall writefile(patch, patchfile)\n\tlet out = s:System('git apply', '--cached', '--whitespace=nowarn', patchfile)\n\n\tsetlocal modifiable\n\tsilent exe h_range . 'delete _'\n\tsetlocal nomodifiable\n\tif line('$') == header_end\n\t\tcall s:Next_diff()\n\t\treturn\n\tend\nendfunction\n\nlet &cpo = s:old_cpo\n"},{"id":"141734","messageId":"m3tyq9cjq2.fsf@localhost.localdomain","threadId":"23810","inReplyTo":"20100515105009.GA10517@localhost","subject":"Re: [ANNOUNCE] diffit - A git plugin for vim","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-05-15T14:40:22Z","receivedAt":"2010-05-15T14:40:22Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Clemens Buchacher <drizzd@aon.at> writes:\n\n> I am currently working on a git plugin for vim. My aim is for it to imitate\n> much of git-gui's functionality. Right now, it is still closer to \"add -p\".\n> \n> But I believe it's already useful. And since I'm new to vim scripting, it\n> can use some testing.\n> \n> To install, copy diffit.vim (attached to this email) to\n> ~/.vim/plugin/diffit.vim .\n> \n> To toggle diffit mode, use <Leader>d, where <Leader> is '\\' by default.\n> \n> Control keys:\n> \n>  <Leader>d      toggle diffit mode\n>  s              stage hunk\n>  d              skip file\n\n> You can clone diffit from here.\n> \n>  git://repo.or.cz/diffit.git\n>  http://github.com/drizzd/diffit.git\n\nCould you add information about 'diffit' to \"Interfaces, Frontends And\nTools\" page on Git Wiki:\n  https://git.wiki.kernel.org/index.php/InterfacesFrontendsAndTools\nin the 'Editors and IDE integration' section?\n\nThanks in advance.\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"141761","messageId":"514EDDA1-E8A4-45CD-ACF5-F7FE18CABD4F@wincent.com","threadId":"23810","inReplyTo":"20100515105009.GA10517@localhost","subject":"Re: [ANNOUNCE] diffit - A git plugin for vim","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2010-05-16T09:12:37Z","receivedAt":"2010-05-16T09:12:37Z","isPatch":false,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"El 15/05/2010, a las 12:50, Clemens Buchacher escribió:\n\n> Hi,\n> \n> I am currently working on a git plugin for vim. My aim is for it to imitate\n> much of git-gui's functionality. Right now, it is still closer to \"add -p\".\n> \n> But I believe it's already useful. And since I'm new to vim scripting, it\n> can use some testing.\n\nClemens, were you aware that there are already a couple of Git plug-ins for Vim? Of these, the most advanced one currently is almost certainly Fugitive:\n\nhttp://github.com/tpope/vim-fugitive\n\nCheers,\nWincent\n"},{"id":"141760","messageId":"20100516094157.GA9553@localhost","threadId":"23810","inReplyTo":"514EDDA1-E8A4-45CD-ACF5-F7FE18CABD4F@wincent.com","subject":"Re: [ANNOUNCE] diffit - A git plugin for vim","fromName":"Clemens Buchacher","fromEmail":"drizzd@aon.at","sentAt":"2010-05-16T09:41:57Z","receivedAt":"2010-05-16T09:41:57Z","isPatch":false,"sender":{"key":"drizzd@gmx.net","avatar":"https://avatars.githubusercontent.com/u/59082?v=4"},"body":"Hi Wincent,\n\nOn Sun, May 16, 2010 at 11:12:37AM +0200, Wincent Colaiuta wrote:\n\n> El 15/05/2010, a las 12:50, Clemens Buchacher escribió:\n> \n> > Hi,\n> > \n> > I am currently working on a git plugin for vim. My aim is for it to imitate\n> > much of git-gui's functionality. Right now, it is still closer to \"add -p\".\n> > \n> > But I believe it's already useful. And since I'm new to vim scripting, it\n> > can use some testing.\n> \n> Clemens, were you aware that there are already a couple of Git plug-ins\n> for Vim? Of these, the most advanced one currently is almost certainly\n> Fugitive:\n\nThe git plugins I am aware of, including vim-fugitive, mostly implement git\ncommands to be executed from vim. I find that utterly useless, since I can\nalready do that from the command line.\n\nWhat I can not do from the command line is staging hunks and lines\ninteractively, possibly interrupted by a quick fix to a change. This is what\nI would use git-gui for, only it does not integrate very well with my vim +\ncmdline centric workflow.\n\nHere's my TODO list:\n\n- handle file mode changes\n\n- navigation (prev/next hunk/file)\n\n- stage individual lines and (virtual) range\n\n- unstage changes\n\n- file browser (modified, staged, untracked)\n\n- prepare commit message\n\n- git add -e?\n\nIf existing plugins already implement these features, then I have missed it,\nand I will be happy to use or improve them instead.\n\nAs for diffing, some of the existing plugins implement side-by-side, or even\ninline diff, using the vimdiff feature. I prefer the native git-diff format,\nhowever.\n\nCheers,\nClemens\n"}]}