Created
December 15, 2022 08:15
-
-
Save lboulard/fb99965a9e8cf8b2a33ab35660d8ed79 to your computer and use it in GitHub Desktop.
Copy highlighted source code to clipboard
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
0<0# : ^ | |
""" | |
:: Keep a python script inside a bat file | |
:: Source https://stackoverflow.com/a/41651933 | |
@%USERPROFILE%\.virtualenvs\scratch\Scripts\python.exe -x -B "%~f0" %* | |
@EXIT /B | |
""" | |
""" | |
Requires pywin32, Pygments, Pillow | |
__author__ = "Laurent Boulard" | |
__date__ = "2022-12-15" | |
__version__ = "0.1" | |
""" | |
import html | |
import sys | |
from pathlib import Path, PurePath | |
import win32clipboard | |
from pygments import highlight | |
from pygments.formatters.html import HtmlFormatter | |
from pygments.lexers import get_lexer_for_filename, guess_lexer | |
from pygments.styles import get_style_by_name | |
from pygments.util import ClassNotFound | |
# Source: https://gist.github.com/Erreinion/6691093 | |
class HtmlClipboard: | |
CF_HTML = None | |
MARKER_BLOCK_OUTPUT = ( | |
"Version:1.0\r\n" | |
"StartHTML:%09d\r\n" | |
"EndHTML:%09d\r\n" | |
"StartFragment:%09d\r\n" | |
"EndFragment:%09d\r\n" | |
"StartSelection:%09d\r\n" | |
"EndSelection:%09d\r\n" | |
"SourceURL:%s\r\n" | |
) | |
DEFAULT_HTML_BODY = ( | |
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">' | |
"<HTML><HEAD></HEAD><BODY><!--StartFragment-->%s<!--EndFragment--></BODY></HTML>" | |
) | |
def GetCfHtml(self): | |
""" | |
Return the FORMATID of the HTML format | |
""" | |
if self.CF_HTML is None: | |
self.CF_HTML = win32clipboard.RegisterClipboardFormat("HTML Format") | |
return self.CF_HTML | |
def PutFragment(self, fragment, selection=None, html=None, source=None): | |
""" | |
Put the given well-formed fragment of Html into the clipboard. | |
selection, if given, must be a literal string within fragment. | |
html, if given, must be a well-formed Html document that textually | |
contains fragment and its required markers. | |
""" | |
if selection is None: | |
selection = fragment | |
if html is None: | |
html = self.DEFAULT_HTML_BODY % fragment | |
if source is None: | |
source = "file://HtmlClipboard.py" | |
fragmentStart = html.index(fragment) | |
fragmentEnd = fragmentStart + len(fragment) | |
selectionStart = html.index(selection) | |
selectionEnd = selectionStart + len(selection) | |
self.PutToClipboard( | |
html, fragmentStart, fragmentEnd, selectionStart, selectionEnd, source | |
) | |
def PutToClipboard( | |
self, | |
html, | |
fragmentStart, | |
fragmentEnd, | |
selectionStart, | |
selectionEnd, | |
source="None", | |
): | |
""" | |
Replace the Clipboard contents with the given html information. | |
""" | |
try: | |
win32clipboard.OpenClipboard(0) | |
win32clipboard.EmptyClipboard() | |
src = self.EncodeClipboardSource( | |
html, fragmentStart, fragmentEnd, selectionStart, selectionEnd, source | |
) | |
src = src.encode("UTF-8") | |
# print(src) | |
win32clipboard.SetClipboardData(self.GetCfHtml(), src) | |
finally: | |
win32clipboard.CloseClipboard() | |
def EncodeClipboardSource( | |
self, html, fragmentStart, fragmentEnd, selectionStart, selectionEnd, source | |
): | |
""" | |
Join all our bits of information into a string formatted as per the HTML format specs. | |
""" | |
# How long is the prefix going to be? | |
dummyPrefix = self.MARKER_BLOCK_OUTPUT % (0, 0, 0, 0, 0, 0, source) | |
lenPrefix = len(dummyPrefix) | |
prefix = self.MARKER_BLOCK_OUTPUT % ( | |
lenPrefix, | |
len(html) + lenPrefix, | |
fragmentStart + lenPrefix, | |
fragmentEnd + lenPrefix, | |
selectionStart + lenPrefix, | |
selectionEnd + lenPrefix, | |
source, | |
) | |
return prefix + html | |
def pygments_guess_lexer(filename, content): | |
try: | |
return get_lexer_for_filename(filename) | |
except ClassNotFound: | |
pass | |
try: | |
return guess_lexer(content) | |
except ClassNotFound: | |
pass | |
return None | |
style = get_style_by_name("sas") | |
formatter = HtmlFormatter(full=False, wrapcode=True, style=style) | |
css = formatter.get_style_defs() | |
css = f""" | |
body{{ font-family: system-ui, sans-serif; font-size: 10pt; }} | |
{css} | |
pre, code {{ | |
font-family: consolas, monospace; | |
line-height: 1em; | |
}} | |
""" | |
fragments = [] | |
for filename in sys.argv[1:]: | |
if filename == "-": | |
code = sys.stdin.read() | |
filename = "stdin" | |
else: | |
code = Path(filename).read_text() | |
lexer = pygments_guess_lexer(filename, code) | |
if lexer: | |
formatter = HtmlFormatter( | |
full=False, wrapcode=True, style=style, filename=filename | |
) | |
fragment = highlight(code, lexer, formatter) | |
else: | |
fragment = html.escape(code.strip()) | |
fragment = f"""<div class="highlight"> | |
<span class="filename">{html.escape(filename)}</span> | |
<pre><code>{fragment}</code></pre></div> | |
""" | |
fragments.append(fragment) | |
else: | |
if not sys.argv[1:]: | |
print( | |
"Usage %s: source [source ...]" % PurePath(__file__).stem, file=sys.stderr | |
) | |
sys.exit(1) | |
cb = HtmlClipboard() | |
fragment = "\n".join(fragments) | |
cb.PutFragment( | |
fragment, | |
html=f"""<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" | |
"http://www.w3.org/TR/html4/strict.dtd"> | |
<!-- | |
generated by Pygments <https://pygments.org/> | |
Copyright 2006-2022 by the Pygments team. | |
Licensed under the BSD license, see LICENSE for details. | |
--> | |
<html> | |
<head> | |
<title>Code to clipboard</title> | |
<style type="text/css"> | |
{css} | |
</style> | |
</head> | |
<body> | |
{fragment} | |
</body> | |
</html> | |
""", | |
) | |
# Local Variables: | |
# mode: python | |
# coding: utf-8-dos | |
# End: | |
# vim: set ff=dos ft=python: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment