diff --git a/autoload/magit/sign.vim b/autoload/magit/sign.vim index abf488dd65dab1ed70b9f109aa1ebec33f2f7656..fd44abd407d4c83f8b502adb73fe1dd57c347d19 100644 --- a/autoload/magit/sign.vim +++ b/autoload/magit/sign.vim @@ -60,6 +60,12 @@ function! magit#sign#find_signs(pattern, startline, endline) return found_signs endfunction +" magit#sign#find_stage_signs: helper function to get marked lines for stage +" param[in] startline,endline: range of lines +function! magit#sign#find_stage_signs(startline, endline) + return magit#sign#find_signs(s:magit_mark_sign, a:startline, a:endline) +endfunction + " s:magit_mark_sign: string of the sign for lines to be staged let s:magit_mark_sign='MagitMark' diff --git a/plugin/magit.vim b/plugin/magit.vim index 99068abc03d0234007291c449eafbaba4942faae..391c94c45482f8cb9101d3b30550555e20accb0f 100644 --- a/plugin/magit.vim +++ b/plugin/magit.vim @@ -418,12 +418,14 @@ endfunction " s:mg_create_diff_from_select: craft the diff to apply from a selection " in a chunk " remarks: it works with full lines, and can not span over multiple chunks -" param[in] start_select_line,end_select_line: limits of the selection +" param[in] select_lines: List containing all selected line numbers " return: List containing the diff to apply, including the chunk header (must " be applied with git apply --recount) -function! s:mg_create_diff_from_select(start_select_line, end_select_line) +function! s:mg_create_diff_from_select(select_lines) + let start_select_line = a:select_lines[0] + let end_select_line = a:select_lines[-1] let [starthunk,endhunk] = <SID>mg_select_hunk_block() - if ( a:start_select_line < starthunk || a:end_select_line > endhunk ) + if ( start_select_line < starthunk || end_select_line > endhunk ) throw 'out of hunk selection' endif let section=<SID>mg_get_section() @@ -436,13 +438,12 @@ function! s:mg_create_diff_from_select(start_select_line, end_select_line) endif endfor let selection = [] - let visual_selection = getline(a:start_select_line, a:end_select_line) call add(selection, current_hunk.header) let current_line = starthunk + 1 for hunk_line in current_hunk.lines - if ( current_line >= a:start_select_line && current_line <= a:end_select_line ) - call add(selection, visual_selection[current_line-a:start_select_line]) + if ( index(a:select_lines, current_line) != -1 ) + call add(selection, getline(current_line)) elseif ( hunk_line =~ '^+.*' ) " just ignore these lines elseif ( hunk_line =~ '^-.*' ) @@ -749,7 +750,13 @@ function! magit#stage_hunk(discard) catch 'out_of_block' let [start,end] = <SID>mg_select_file_block() endtry - let selection = getline(start, end) + let marked_lines = magit#sign#find_stage_signs(start, end) + if ( empty(marked_lines) ) + let selection = getline(start, end) + else + let selection = <SID>mg_create_diff_from_select( + \map(keys(marked_lines), 'str2nr(v:val)')) + endif endtry return magit#stage_block(selection, a:discard) endfunction @@ -762,7 +769,13 @@ endfunction " return: no function! magit#stage_vselect() range " func-range a:firstline a:lastline seems to work at least from vim 7.2 - let selection = <SID>mg_create_diff_from_select(a:firstline, a:lastline) + let lines = [] + let curline = a:firstline + while ( curline <= a:lastline ) + call add(lines, curline) + let curline += 1 + endwhile + let selection = <SID>mg_create_diff_from_select(lines) return magit#stage_block(selection, 0) endfunction