Last active
September 1, 2023 21:07
-
-
Save molsonkiko/408493626c31695e13a0a5270eea9c94 to your computer and use it in GitHub Desktop.
Merge files by line (Notepad++ PythonScript script)
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
# -*- coding: utf-8 -*- | |
# reference: https://community.notepad-plus-plus.org/topic/24872/is-there-any-alternative-to-merge-files-in-one-plugin/7?_=1693515221904 | |
# installation guide: https://community.notepad-plus-plus.org/topic/23039/faq-desk-how-to-install-and-run-a-script-in-pythonscript | |
from __future__ import print_function | |
import os | |
import re | |
from Npp import * | |
__version__ = '0.2.0' | |
EOLS = ('\r\n', '\r', '\n') | |
def getCurrentEol(): | |
return EOLS[editor.getEOLMode()] | |
def main(): | |
fnames = [x[0] for x in notepad.getFiles()] | |
setfnames = set(fnames) | |
fnames_str = '\r\n'.join(fnames) | |
while True: | |
fnames_chosen_str = notepad.prompt("remove the names of any files in this list that you don't want to merge", 'merge files together', fnames_str) | |
if fnames_chosen_str is None: | |
return | |
fnames_chosen = [f for f in fnames_chosen_str.split('\r\n') if f] | |
bad = False | |
for fname in fnames_chosen: | |
if fname not in setfnames: | |
bad = True | |
notepad.messageBox( | |
'Filename %s was not a currently open file' % fname, | |
'nonexistent filename', | |
MESSAGEBOXFLAGS.ICONEXCLAMATION | |
) | |
break | |
if not bad: | |
break | |
lines_fname_map = {} | |
for fname in fnames_chosen: | |
notepad.open(fname) | |
text = editor.getText() | |
eol = getCurrentEol() | |
lines = text.split(eol) | |
lines_fname_map[fname] = lines | |
maxlen = max(len(x) for x in lines_fname_map.values()) | |
merged = [] | |
collisions = {} | |
for ii in range(maxlen): | |
line_filled_by = None | |
for fname, lines in lines_fname_map.items(): | |
len_ = len(lines) | |
if ii >= len_: | |
continue | |
line = lines[ii] | |
if line: | |
if line_filled_by: | |
if ii not in collisions: | |
collisions[ii] = {line_filled_by: merged[ii]} | |
collisions[ii][fname] = line | |
else: | |
line_filled_by = fname | |
merged.append(line) | |
n_collisions = len(collisions) | |
many_collisions = n_collisions > 10 | |
short_fnames = {} | |
short_fname_values = set() | |
for fname in fnames_chosen: | |
fname_parts = fname.split(os.sep) | |
first_part_idx = len(fname_parts) - 1 | |
short_fname = '\\'.join(fname_parts[first_part_idx:]) | |
while first_part_idx >= 0 and short_fname in short_fname_values: | |
first_part_idx -= 1 | |
short_fname = '\\'.join(fname_parts[first_part_idx:]) | |
short_fname_values.add(short_fname) | |
short_fnames[fname] = short_fname | |
for coll_ix, (ii, collision) in enumerate(collisions.items()): | |
collisions_text_list = [] | |
collision_lines = list(collision.values()) | |
for fname, line in collision.items(): | |
existing_choice = merged[ii] | |
collisions_text_list.append('[ %s ] %r : %r' % ( | |
'X' if line == existing_choice else '', | |
short_fnames[fname], | |
line | |
)) | |
collisions_text = '\r\n'.join(collisions_text_list) | |
result = notepad.prompt('Collision at line %d. Put an X in the box of the file whose line you want to keep, then hit OK or Cancel to skip this line' % ii, 'merge collisions', collisions_text) | |
stop_processing = False | |
if result: | |
for jj, result_line in enumerate(result.split('\r\n')): | |
if re.search(r'^\s*\[\s*\S\s*\]', result_line): | |
line_to_use = collision_lines[jj] | |
merged[ii] = line_to_use | |
break | |
else: | |
stop_processing = True | |
remaining_colisions = n_collisions - coll_ix - 1 | |
if coll_ix % 5 == 0 and remaining_colisions >= 5: | |
mb_result = notepad.messageBox( | |
'There are %d unresolved collisions left. Stop processing them now?' % remaining_colisions, | |
'Many collisions left', | |
MESSAGEBOXFLAGS.ICONQUESTION | MESSAGEBOXFLAGS.YESNO | |
) | |
if mb_result == MESSAGEBOXFLAGS.RESULTYES: | |
break | |
notepad.new() | |
editor.setText('\r\n'.join(merged)) | |
notepad.messageBox('This file contains the merger of the selected files', 'merger complete') | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment