Skip to content

Instantly share code, notes, and snippets.

@pakkinlau
Created October 28, 2023 17:31
Show Gist options
  • Save pakkinlau/e8f55eb16a6611315d2908b00f226890 to your computer and use it in GitHub Desktop.
Save pakkinlau/e8f55eb16a6611315d2908b00f226890 to your computer and use it in GitHub Desktop.
A python script that convert the mathematics LaTeX format that you can copy from ChatGPT, into the LaTeX format that markdown (such as Obsidian) can display.
"""
This script automatically converts the output of GPT-3 to markdown format.
Future: convert this script to be a chrome extension.
For linux users, they might need to install `xclip` or `xsel` to find clipboard mechanism.
`sudo apt-get install xclip`: Install xclip
"""
import re
import pyperclip
import platform
import subprocess
import sys
# Detect the operating system
if platform.system() == "Linux":
# Set clipboard mechanism to xclip for Linux systems
try:
subprocess.check_output(['xclip', '-version'])
except subprocess.CalledProcessError:
print("xclip is not installed. Attempting to install...")
try:
# Install xclip using the package manager (apt in this case)
subprocess.check_call(['sudo', 'apt-get', 'install', 'xclip'])
print("xclip installed successfully.")
except subprocess.CalledProcessError:
print("Failed to install xclip. Please install it manually.")
sys.exit(1)
pyperclip.set_clipboard("xclip")
gpt_response = pyperclip.paste()
def convert_text_pattern(text):
# Define the patterns to match
# caution, the order of the patterns matters
#note: \[ --> [
# \\ --> \
patterns = {
r'\n\s+\\\[': r'$$', # match \[ followed by any number of spaces at the beginning of a line
r'\n\s+\\\]': r'$$', # match \] preceded by any number of spaces at the end of a line
r"\\\[\s": r"$", # match \[ followed by a space
r"\\\(\s": r"$", # match \( followed by a space
r"\s\\\]": r"$$", # match \] preceded by a space
r"\s\\\)": r"$", # match \) preceded by a space
r"\\\[\n": r"$$", # match \[ followed by a newline
r"\n\\\]": r"$$", # match \] preceded by a newline
r"\\\(" : r"$", # match \(
r"\\\)" : r"$", # match \)
r"\\\]\n" : r"$$\n", # handling some cases of \] followed by a newline cannot be detected
r"\\\]": r"$$", # matching some missing closing brackets
}
# prevent '\r' from being replaced
# Iterate over patterns and replace them in the text
for pattern, replacement in patterns.items():
text = re.sub(pattern, replacement, text)
return text
converted_text = convert_text_pattern(gpt_response)
pyperclip.copy(converted_text)
@sw1jari
Copy link

sw1jari commented Dec 14, 2023

Thanks! I modified this to replace the pyperclip dependency with xclip.

import re
import platform
import subprocess
import sys

def copy_to_clipboard(text):
    process = subprocess.Popen(['xclip', '-selection', 'clipboard', '-in'], stdin=subprocess.PIPE, close_fds=True)
    process.communicate(input=text.encode('utf-8'))

def paste_from_clipboard():
    try:
        output = subprocess.check_output(['xclip', '-selection', 'clipboard', '-out'], universal_newlines=True)
        return output
    except subprocess.CalledProcessError:
        print("Error accessing clipboard")
        return None

# Detect the operating system
if platform.system() == "Linux":
    try:
        subprocess.check_output(['xclip', '-version'])
    except subprocess.CalledProcessError:
        print("xclip is not installed. Attempting to install...")
        try:
            subprocess.check_call(['sudo', 'apt-get', 'install', 'xclip'])
            print("xclip installed successfully.")
        except subprocess.CalledProcessError:
            print("Failed to install xclip. Please install it manually.")
            sys.exit(1)

gpt_response = paste_from_clipboard()

def convert_text_pattern(text):
    # Define the patterns to match

    # caution, the order of the patterns matters
    #note: \[ --> [
    # \\ --> \
    patterns = {
        r'\n\s+\\\[': r'$$',  # match \[ followed by any number of spaces at the beginning of a line
        r'\n\s+\\\]': r'$$',  # match \] preceded by any number of spaces at the end of a line
        r"\\\[\s": r"$", # match \[ followed by a space
        r"\\\(\s": r"$", # match \( followed by a space
        r"\s\\\]": r"$$", # match \] preceded by a space
        r"\s\\\)": r"$", # match \) preceded by a space
        r"\\\[\n": r"$$", # match \[ followed by a newline
        r"\n\\\]": r"$$", # match \] preceded by a newline
        r"\\\(" : r"$", # match \(
        r"\\\)" : r"$", # match \)
        r"\\\]\n" : r"$$\n", # handling some cases of \] followed by a newline cannot be detected
        r"\\\]": r"$$", # matching some missing closing brackets
    }
    # prevent '\r' from being replaced

    # Iterate over patterns and replace them in the text
    for pattern, replacement in patterns.items():
        text = re.sub(pattern, replacement, text)
    return text

converted_text = convert_text_pattern(gpt_response)
copy_to_clipboard(converted_text)

Tip for dmenu/rofi/etc. users: copy this script as gpt2md in a directory that's in your PATH (like /usr/local/bin/gpt2md) and make it executable with chmod +x gpt2md. make sure #!/usr/bin/env python3 is at the top of the file.

@pakkinlau
Copy link
Author

@sw1jari Nice to meet you. Thank you for trying out my script.
It seems you have made the script more compatible in Linux environmnet. Good work!
Welcome adding my discord pakkin.lau to chat about anything about programing as well!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment