Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
Markboard3 updates Markboard for Sublime Text 3. It now only runs on
Mac OS X with Pandoc.
  • Loading branch information
Daniel Shannon committed Feb 4, 2013
0 parents commit 32307a9
Show file tree
Hide file tree
Showing 9 changed files with 275 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.DS_Store
*.pyc
6 changes: 6 additions & 0 deletions Default.sublime-commands
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"caption": "Markboard: Copy Rich Text",
"command": "markboard_copy_formatted"
}
]
6 changes: 6 additions & 0 deletions Default.sublime-keymap
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"keys": ["ctrl+alt+c"],
"command": "markboard_copy_formatted"
}
]
48 changes: 48 additions & 0 deletions Main.sublime-menu
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
[
{
"caption": "Preferences",
"mnemonic": "n",
"id": "preferences",
"children":
[
{
"caption": "Package Settings",
"mnemonic": "P",
"id": "package-settings",
"children":
[
{
"caption": "Markboard",
"children":
[
{
"command": "open_file", "args":
{
"file": "${packages}/Markboard/README.mdown"
},
"caption": "README"
},
{
"caption": "-"
},
{
"command": "open_file", "args":
{
"file": "${packages}/Markboard/Markboard.sublime-settings"
},
"caption": "Settings – Default"
},
{
"command": "open_file", "args":
{
"file": "${packages}/User/Markboard.sublime-settings"
},
"caption": "Settings – User"
}
]
}
]
}
]
}
]
175 changes: 175 additions & 0 deletions Markboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
'''
Grateful thanks to the following people for their work, which constitutes the bricks of this
little script:
* Trent Mick, author of python-markdown2 (https://github.com/trentm/python-markdown2),
which processes the Markdown;
* Phillip Piper, who wrote the snippet that interacts with the clipboard under Windows; and
* "Clark," whose guide explained the proper way to use the Foundation and AppKit libraries
to access OS X's clipboard.
I can't blame anyone but myself for the gtk scripting, which is as yet untested and likely to be
less than impeccable; nor for the code's mortar, which largely ditto.
---Daniel Shannon, [email protected], http://daniel.sh
OS X docs: http://www.libertypages.com/clarktech/?p=3299
Windows docs: http://code.activestate.com/recipes/474121-getting-html-from-the-windows-clipboard/
Linux docs: http://www.pygtk.org/docs/pygtk/class-gtkclipboard.html#method-gtkclipboard--store
http://developer.gnome.org/gtkmm/stable/classGtk_1_1Clipboard.html
http://stackoverflow.com/questions/1992869/how-to-paste-html-to-clipboard-with-gtk
http://gtk.php.net/manual/en/gtk.enum.targetflags.php
'''

import codecs
import os
import tempfile
import threading
import subprocess
import sublime
import sublime_plugin
import Markboard3.MarkboardClippers


def err(theError):
print("[Markboard: " + theError + "]")


class MarkboardCopyFormattedCommand(sublime_plugin.TextCommand):
def is_enabled(self):
multimarkdown = self.view.score_selector(0, "text.html.multimarkdown") > 0
markdown = self.view.score_selector(0, "text.html.markdown") > 0
return multimarkdown or markdown

def checkPandoc(self, env):
cmd = ['pandoc', '--version']
try:
output = subprocess.check_output(cmd, env=env)
except Exception as e:
err("Exception: " + str(e))

return output.startswith("pandoc")

def run(self, edit):
plat = sublime.platform()
if plat == "windows":
sublime.status_message("Windows is unsupported under Sublime 3")
return
if plat == "linux":
sublime.status_message("Linux is unsupported under Sublime 3")
return

env = os.environ.copy()
env['PATH'] = env['PATH'] + ":" + sublime.load_settings("Markboard.sublime-settings").get("pandoc_path", "/usr/local/bin")

if not self.checkPandoc(env):
sublime.status_message("Markboard requires Pandoc")
return

selections = self.view.sel()
threads = []

f = tempfile.NamedTemporaryFile(mode="w+", suffix=".mdown", delete=False)
writer = f.name
f.close()
self.runningThreadBuffer = ""

singleCursors = passedSelections = 0
for theSelection in selections:
theSubstring = self.view.substr(theSelection)
if len(theSubstring) == 0:
singleCursors += 1
else:
normalString = self.normalize_line_endings(theSubstring)
f = codecs.open(writer, "a", "utf-8")
f.write(normalString + "\n\n")
passedSelections += 1
f.close()

if singleCursors > 0 and passedSelections < 1:
theBuffer = self.view.substr(sublime.Region(0, self.view.size()))
normalString = self.normalize_line_endings(theBuffer)
f = codecs.open(writer, "a", "utf-8")
f.write(normalString + "\n\n")
f.close()

newThread = MarkboardPandocMarkdownProcessor(writer, self.view.window(), env)
threads.append(newThread)
newThread.start()

self.manageThreads(threads)

def manageThreads(self, theThreads, offset=0, i=0, direction=1):
next_threads = []
for aThread in theThreads:
if aThread.is_alive():
next_threads.append(aThread)
continue
self.runningThreadBuffer += "\n\n"
self.runningThreadBuffer += aThread.result
theThreads = next_threads

if len(theThreads):
before = i % 8
after = 7 - before
if not after:
direction = -1
if not before:
direction = 1
i += direction
self.view.set_status("markboard", "Markdown markup... [%s=%s]" %
(" " * before, " " * after))

sublime.set_timeout(lambda: self.manageThreads(theThreads, offset, i, direction), 100)
return
clipObject = self.clipboardCopy()
if clipObject:
self.view.erase_status("markboard")
sublime.status_message("Formatted text copied.")
else:
self.view.erase_status("markboard")
sublime.status_message("Fatal error formatting text.")

def normalize_line_endings(self, string):
string = string.replace('\r\n', '\n').replace('\r', '\n')
line_endings = self.view.settings().get('default_line_ending')
if line_endings == 'windows':
string = string.replace('\n', '\r\n')
elif line_endings == 'mac':
string = string.replace('\n', '\r')
return string

def clipboardCopy(self):
plat = sublime.platform()
if plat == "osx":
return Markboard3.MarkboardClippers.OSXClipObject(self.runningThreadBuffer)
if plat == "windows":
self.view.erase_status("markboard")
sublime.status_message("Windows is unsupported under Sublime 3")
return None
if plat == "linux":
self.view.erase_status("markboard")
sublime.status_message("Linux is unsupported under Sublime 3")
return None


class MarkboardPandocMarkdownProcessor(threading.Thread):
def __init__(self, theFilename, theWindow, env):
self.myFilename = theFilename
self.result = None
self.window = theWindow
self.env = env
threading.Thread.__init__(self)

def run(self):
f = tempfile.NamedTemporaryFile(mode="w+", suffix=".html", delete=False)
outFile = f.name
f.close()
markdownFrom = "--from=markdown"
cmd = ['pandoc', self.myFilename, '--output=%s' % outFile, markdownFrom, '--to=html', '--smart', '--normalize']
try:
subprocess.call(cmd, env=self.env)
except Exception as e:
err("Exception: " + str(e))
self.result = False
else:
f = codecs.open(outFile, "r", "utf-8")
self.result = f.read()
f.close()
6 changes: 6 additions & 0 deletions Markboard.sublime-settings
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
// If you wish to use Pandoc, you should probably specify
// its installation path, as it's often not found by
// Sublime.
"pandoc_path": "/usr/local/bin",
}
10 changes: 10 additions & 0 deletions MarkboardClippers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from Foundation import *
from AppKit import *


class OSXClipObject(object):
def __init__(self, theData):
pasteboard = NSPasteboard.generalPasteboard()
typeArray = NSArray.arrayWithObject_(NSHTMLPboardType)
pasteboard.declareTypes_owner_(typeArray, None)
pasteboard.setString_forType_(theData, NSHTMLPboardType)
22 changes: 22 additions & 0 deletions README.mdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Markboard3 for Sublime Text 3
Markboard3 is a quick-and-dirty **OS X--only** plugin for [Sublime Text 3](http://sublimetext.com/3) that processes a Markdown document and copies the output to the clipboard as rich text. Its target audience is that Venn slice of people whom both WYSIWYG editors and completely raw text cause to twitch, who enjoy the expressive force of an emphasized word but also the austerity of a monospaced buffer, who would sooner part with their typing fingers than their typesetting systems but compromise their staunchness each and every time they want to italicize a book title in an e-mail. To these people, Markboard is proudly dedicated. Go forth and WYG no more.


## Installation
Due to Sublime 3's move to a custom Python interpreter, Markboard now requires [Pandoc][] and several external libraries included in this distribution's "Support" directory. To set up Markboard, install Pandoc, then extract the four folders and two files from `Support/PyObjC.zip` and copy them directly to the root level of your Sublime Text 3 "Packages" directory (`~/Library/Application Support/Sublime Text 3/Packcages/`). These files are slight modifications of [PyObjC](http://pyobjc.sourceforge.net) and inbuilt Python modules altered to run correctly within Sublime Text 3.[^1]

If you install Pandoc to a directory other than the default, please change the `pandoc_path` setting in `Markbaord.sublime-settings` so that the package can find it.


## Usage
Just press `Ctrl+Alt+c` in any Markdown document, switch to a rich-text editor, and paste. You can also select specific parts of your Markdown source for processing; if there are multiple selections, they'll be strung together with two newlines between them and copied as a unit.


## Limitations
Markboard3 will only run on Mac OS X.



[^1]: However, be aware that the Sublime interpreter will occasionally return errors on loading the modules, usually along the lines of `__name__ is undefined`. This will not affect either Sublime's performance or this package's.

[pandoc]: http://johnmacfarlane.net/pandoc/
Binary file added Support/PyObjC.zip
Binary file not shown.

0 comments on commit 32307a9

Please sign in to comment.