Skip to content

Instantly share code, notes, and snippets.

@LockeBirdsey
Last active May 25, 2021 05:29
Show Gist options
  • Save LockeBirdsey/5487d23a56c1a38dfb97d1fd91d145a3 to your computer and use it in GitHub Desktop.
Save LockeBirdsey/5487d23a56c1a38dfb97d1fd91d145a3 to your computer and use it in GitHub Desktop.
Markdown merger:
#v0.6
import argparse
import re
import sys
parser = argparse.ArgumentParser(description="Incorporate multiple markdown files into a single source markdown file based on keys. Returns STDOUT")
parser.add_argument('source', type=str, help="The source markdown file")
parser.add_argument('--manual', metavar="file", type=str, nargs='+', help="a list of files to be incorporated into the source file. \
\nCan pass in file names that match the keys or can direct keys to files using \"KEY:FILE\" where KEY is the key in the markdown\
file and FILE is the path to the file whose contents you want to replace the key with")
parser.add_argument('--auto', help="automatically find keys in the source file and attempts to find that file and incorporate into the source file. Requires keys to end in .md", action="store_true")
parser.add_argument('--ignore-errors', dest="ignore", help="Ignores errors", action="store_true")
parser.add_argument('--unsafe', dest="unsafe", help="Performs changes in an unsafe fashion. Subkeys /may/ get parsed and overwritten", action="store_true")
parser.add_argument('--recursive', dest="recursive", help="Performs changes recursively. ", action="store_true")
args = parser.parse_args()
source = args.source
def as_key(key):
return "["+key+"]"
def read_in_file(fname):
try:
f = open(fname,'r')
s = f.read()
f.close()
return s
except IOError as e:
if not args.ignore:
print("ERROR: file "+fname+" could not be found. Exiting...")
sys.exit(1)
else:
print("WARNING: file "+fname+" could not be found. Ignoring...")
return None
def is_key_commented_out(source, key):
return re.search(r"\<\!\-\-(?:.|\n|\r)*\["+key+r"\](?:.|\n|\r)*-->", source)
def replace_keys_with_files(source_str, key_value_pairs):
string_bank = [] #for safety
for pair in key_value_pairs:
file_path = pair['path']
key = pair['key']
if is_key_commented_out(source_str, key):
print("WARNING: key ["+key+"] has been commented out and will not be used")
else:
fstr = read_in_file(file_path)
if fstr is not None:
key = as_key(key)
if args.unsafe:
source_str = source_str.replace(key, fstr)
else:
key_pos = source_str.find(key)
key_len = len(key)
str_len = len(source_str)
string_bank.append(source_str[0:key_pos+key_len].replace(key, fstr))
source_str = source_str[key_pos+key_len:str_len]
if args.unsafe:
return source_str
else:
return ''.join(string_bank) + source_str
def recursive_replace(source, key_value_pairs):
new_source = replace_keys_with_files(source, key_value_pairs)
if new_source == source:
return new_source
else:
return recursive_replace(new_source, key_value_pairs)
##########################
# Main Logic Starts Here #
##########################
source_f = read_in_file(source)
kvp = []
if args.manual:
for i in args.manual:
spl = i.split(":")
if len(spl) == 1:
k = {"key":i, "path":i}
else:
k = {"key":spl[0], "path":spl[1]}
if source_f.find(as_key(k['key'])) != -1:
kvp.append(k)
elif args.auto:
keys = re.findall(r"\[([A-Za-z0-9_\.\/]*[A-Za-z0-9_]+\.md)\]", source_f)
for i in keys:
kvp.append({"key":i, "path":i})
if args.recursive:
source_f = recursive_replace(source_f, kvp)
else:
source_f = replace_keys_with_files(source_f, kvp)
print(source_f)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment