Last active
November 11, 2021 12:26
-
-
Save skt041959/688a768223bb89a7c3da0fe8a34cc705 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import vim | |
import re | |
import json | |
import asyncio | |
import logging | |
try: | |
from patiencediff import PatienceSequenceMatcher as SequenceMatcher | |
except ImportError: | |
from difflib import SequenceMatcher | |
logger = logging.getLogger(__name__) | |
logger.setLevel(logging.DEBUG) | |
logger.debug('session loaded') | |
LUA_CODE = """ | |
_G.fold_fromsearch = function(winid) | |
vim.api.nvim_win_call(winid, function() | |
vim.wo.foldmethod = 'manual' | |
vim.cmd([[normal! zE]]) | |
vim.wo.foldminlines = 0 | |
vim.wo.foldlevel = 0 | |
vim.wo.foldtext = "(v:folddashes.'').((v:foldend)-(v:foldstart)+(1))" | |
local lastline = 0 | |
for _,l in ipairs(vim.b.searchfold_matches) do | |
if l - lastline > 1 then | |
vim.cmd( tostring(lastline+1) .. ',' .. tostring(l-1) .. 'fold' ) | |
end | |
lastline = l | |
end | |
if vim.api.nvim_buf_line_count(0) - lastline > 1 then | |
vim.cmd( tostring(lastline+1) .. ',$' .. 'fold' ) | |
end | |
end) | |
end | |
""" | |
vim.exec_lua(LUA_CODE) | |
def logdiff_loglevel(level): | |
logger.setLevel(logging.getLevelName(level)) | |
async def async_searchfold(bufnr, winid, filename, pattern): | |
command = ['rg', '-z', '--json', pattern, filename] | |
vim.command('redraw', async_=True) | |
vim.api.notify(' '.join(command), 2, {}, async_=True) | |
logger.debug(command) | |
rg_proc = await asyncio.create_subprocess_exec( | |
*command, | |
stdout=asyncio.subprocess.PIPE, | |
stderr=asyncio.subprocess.PIPE, | |
) | |
# rg_proc = subprocess.run( | |
# command, | |
# universal_newlines=True, | |
# encoding="utf8", | |
# check=False, | |
# capture_output=True, | |
# timeout=60, | |
# ) | |
match_lnums = [] | |
match_content = [] | |
rg_stdout, rg_stderr = await rg_proc.communicate() | |
logger.debug('communicate %d', rg_proc.pid) | |
if rg_proc.returncode != 0: | |
return | |
for line in rg_stdout.splitlines(False): | |
value = json.loads(line) | |
if value['type'] == 'match': | |
data = value['data'] | |
match_lnums.append(data['line_number']) | |
match_content.append(data['lines']['text']) | |
vim.async_call(lambda: vim.api.buf_set_var(bufnr, 'searchfold_matches', match_lnums)) | |
# vim.async_call(lambda: vim.api.buf_set_var(bufnr, 'searchfold_content', match_content)) | |
vim.async_call(lambda: vim.lua.fold_fromsearch(winid)) | |
return bufnr, match_lnums, match_content | |
LogDiffSigns = { | |
'LogDiffDelete': { | |
'text': ' ', | |
'linehl': 'DiffDelete', | |
}, | |
'LogDiffAdd': { | |
'text': ' ', | |
'linehl': 'DiffAdd', | |
}, | |
'LogDiffChange': { | |
'text': ' ', | |
'linehl': 'DiffChange', | |
}, | |
} | |
SearchTasks = {} | |
def searchfold(*args): | |
logger.debug(args) | |
SearchTasks[args[0]] = asyncio.create_task(async_searchfold(*args)) | |
logdiff_ignore_pattern_string = '|'.join( | |
[ | |
r'^.*?\]', | |
r'(cpu|real|mem) ?[:=] ?[m0-9:\.]+', | |
r'(cpu|real|epoch) time ?[:=] ?[0-9:\.]+', | |
r'\d{1,2}:\d{2}:\d{2}\.\d{1,3}', | |
] | |
) | |
async def async_logdiff_mark(bufnr1, bufnr2, ignore_pattern=None): | |
if ignore_pattern is not None: | |
logdiff_ignore = re.compile(ignore_pattern) | |
else: | |
logdiff_ignore = re.compile(logdiff_ignore_pattern_string, re.IGNORECASE) | |
results = await asyncio.gather(*SearchTasks.values()) | |
matches = {result[0]: {'lnums': result[1], 'content': result[2]} for result in results} | |
logger.debug(results) | |
lines1 = [logdiff_ignore.sub('###', e) for e in matches[bufnr1]['content']] | |
lines2 = [logdiff_ignore.sub('###', e) for e in matches[bufnr2]['content']] | |
lnums1 = matches[bufnr1]['lnums'] | |
lnums2 = matches[bufnr2]['lnums'] | |
deleted = [] | |
inserted = [] | |
changed1 = [] | |
changed2 = [] | |
for group in SequenceMatcher(None, lines1, lines2).get_grouped_opcodes(0): | |
for tag, i1, i2, j1, j2 in group: | |
if tag == 'replace': | |
changed1.extend(range(i1, i2)) | |
changed2.extend(range(j1, j2)) | |
elif tag == 'delete': | |
deleted.extend(range(i1, i2)) | |
elif tag == 'insert': | |
inserted.extend(range(j1, j2)) | |
for name, define in LogDiffSigns.items(): | |
vim.funcs.sign_define(name, define, async_=True) | |
for nr in changed1: | |
vim.funcs.sign_place( | |
0, 'LogDiff', 'LogDiffChange', bufnr1, {'lnum': lnums1[nr]}, async_=True | |
) | |
for nr in changed2: | |
vim.funcs.sign_place( | |
0, 'LogDiff', 'LogDiffChange', bufnr2, {'lnum': lnums2[nr]}, async_=True | |
) | |
for nr in deleted: | |
vim.funcs.sign_place( | |
0, 'LogDiff', 'LogDiffDelete', bufnr1, {'lnum': lnums1[nr]}, async_=True | |
) | |
for nr in inserted: | |
vim.funcs.sign_place( # | |
0, 'LogDiff', 'LogDiffAdd', bufnr2, {'lnum': lnums2[nr]}, async_=True | |
) | |
vim.command('redraw', async_=True) | |
vim.api.notify(logdiff_ignore_pattern_string, 2, {}, async_=True) | |
def logdiff_mark(bufnr1, bufnr2, ignore_pattern=None): | |
logger.debug('create diff task') | |
asyncio.create_task(async_logdiff_mark(bufnr1, bufnr2, ignore_pattern)) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function! LogFold() abort | |
if empty(s:logdiff_mark) | |
runtime autoload/yarp.vim | |
let s:logdiff_mark = yarp#py3('logdiff_mark') | |
endif | |
call s:logdiff_mark.notify('searchfold', | |
\ bufnr(), win_getid(), bufname(), g:searchfold_pattern) | |
setlocal nowrap | |
endfunction | |
function! LogFoldAndDiff(...) abort | |
call call('SetLogPattern', a:000) | |
windo setlocal nowrap | checktime % | |
noautocmd windo call LogFold() | |
if len(tabpagebuflist()) < 2 | |
sign unplace * group=LogDiff | |
return | |
endif | |
if empty(s:logdiff_mark) | |
runtime autoload/yarp.vim | |
let s:logdiff_mark = yarp#py3('logdiff_mark') | |
endif | |
let [bufnr1, bufnr2 ; _] = tabpagebuflist() | |
call s:logdiff_mark.notify('logdiff_mark', bufnr1, bufnr2) | |
endfunction |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment