Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

initial import

  • Loading branch information...
commit ed32ca442e8568643d49550aa4585a8460f4c625 1 parent c86235c
@n1k0 authored
Showing with 35,748 additions and 3 deletions.
  1. +53 −0 Default.sublime-commands
  2. +67 −0 Highlight.py
  3. +21 −0 Main.sublime-menu
  4. +4 −3 README.md
  5. +281 −0 desktop/__init__.py
  6. +549 −0 desktop/dialog.py
  7. +273 −0 desktop/windows.py
  8. +91 −0 pygments/__init__.py
  9. +433 −0 pygments/cmdline.py
  10. +74 −0 pygments/console.py
  11. +74 −0 pygments/filter.py
  12. +357 −0 pygments/filters/__init__.py
  13. +92 −0 pygments/formatter.py
  14. +68 −0 pygments/formatters/__init__.py
  15. +92 −0 pygments/formatters/_mapping.py
  16. +109 −0 pygments/formatters/bbcode.py
  17. +750 −0 pygments/formatters/html.py
  18. +553 −0 pygments/formatters/img.py
  19. +378 −0 pygments/formatters/latex.py
  20. +117 −0 pygments/formatters/other.py
  21. +136 −0 pygments/formatters/rtf.py
  22. +154 −0 pygments/formatters/svg.py
  23. +112 −0 pygments/formatters/terminal.py
  24. +222 −0 pygments/formatters/terminal256.py
  25. +697 −0 pygments/lexer.py
  26. +229 −0 pygments/lexers/__init__.py
  27. +1,645 −0 pygments/lexers/_asybuiltins.py
  28. +232 −0 pygments/lexers/_clbuiltins.py
  29. +249 −0 pygments/lexers/_luabuiltins.py
  30. +295 −0 pygments/lexers/_mapping.py
  31. +3,787 −0 pygments/lexers/_phpbuiltins.py
  32. +232 −0 pygments/lexers/_postgres_builtins.py
  33. +29 −0 pygments/lexers/_scilab_builtins.py
  34. +3 −0  pygments/lexers/_vimbuiltins.py
  35. +1,803 −0 pygments/lexers/agile.py
  36. +360 −0 pygments/lexers/asm.py
  37. +2,891 −0 pygments/lexers/compiled.py
  38. +636 −0 pygments/lexers/dotnet.py
  39. +1,802 −0 pygments/lexers/functional.py
  40. +356 −0 pygments/lexers/hdl.py
  41. +847 −0 pygments/lexers/jvm.py
  42. +1,072 −0 pygments/lexers/math.py
  43. +3,339 −0 pygments/lexers/other.py
  44. +695 −0 pygments/lexers/parsers.py
  45. +361 −0 pygments/lexers/shell.py
  46. +100 −0 pygments/lexers/special.py
  47. +559 −0 pygments/lexers/sql.py
  48. +1,630 −0 pygments/lexers/templates.py
  49. +1,753 −0 pygments/lexers/text.py
  50. +2,851 −0 pygments/lexers/web.py
  51. +74 −0 pygments/plugin.py
  52. +104 −0 pygments/scanner.py
  53. +117 −0 pygments/style.py
  54. +70 −0 pygments/styles/__init__.py
  55. +65 −0 pygments/styles/autumn.py
  56. +51 −0 pygments/styles/borland.py
  57. +49 −0 pygments/styles/bw.py
  58. +81 −0 pygments/styles/colorful.py
  59. +73 −0 pygments/styles/default.py
  60. +72 −0 pygments/styles/emacs.py
  61. +72 −0 pygments/styles/friendly.py
  62. +42 −0 pygments/styles/fruity.py
  63. +75 −0 pygments/styles/manni.py
  64. +106 −0 pygments/styles/monokai.py
  65. +80 −0 pygments/styles/murphy.py
  66. +65 −0 pygments/styles/native.py
  67. +75 −0 pygments/styles/pastie.py
  68. +69 −0 pygments/styles/perldoc.py
  69. +33 −0 pygments/styles/rrt.py
  70. +141 −0 pygments/styles/tango.py
  71. +63 −0 pygments/styles/trac.py
  72. +63 −0 pygments/styles/vim.py
  73. +38 −0 pygments/styles/vs.py
  74. +195 −0 pygments/token.py
  75. +130 −0 pygments/unistring.py
  76. +232 −0 pygments/util.py
View
53 Default.sublime-commands
@@ -0,0 +1,53 @@
+[
+ /* in SublimeText conversions */
+ {
+ "caption": "Highlight: convert to HTML",
+ "command": "highlight_export",
+ "args": {
+ "target": "sublime",
+ "output_type": "html"
+ }
+ },
+ {
+ "caption": "Highlight: convert to RTF",
+ "command": "highlight_export",
+ "args": {
+ "target": "sublime",
+ "output_type": "rtf"
+ }
+ },
+ /* in SublimeText rendering */
+ {
+ "caption": "Highlight: view as HTML",
+ "command": "highlight_export",
+ "args": {
+ "target": "external",
+ "output_type": "html"
+ }
+ },
+ {
+ "caption": "Highlight: view as RTF",
+ "command": "highlight_export",
+ "args": {
+ "target": "external",
+ "output_type": "rtf"
+ }
+ },
+ /* Clipboard exports */
+ {
+ "caption": "Highlight: copy to clipboard as HTML",
+ "command": "highlight_export",
+ "args": {
+ "target": "clipboard",
+ "output_type": "html"
+ }
+ },
+ {
+ "caption": "Highlight: copy to clipboard as RTF",
+ "command": "highlight_export",
+ "args": {
+ "target": "clipboard",
+ "output_type": "rtf"
+ }
+ }
+]
View
67 Highlight.py
@@ -0,0 +1,67 @@
+import desktop
+import os
+import pygments
+import sublime
+import sublime_plugin
+import tempfile
+
+from pygments.lexers import get_lexer_for_filename, guess_lexer
+from pygments.formatters import get_formatter_by_name
+
+
+FORMATS = ('html', 'rtf',)
+HTML_TEMPLATE = u"""<!DOCTYPE html>
+<html>
+<meta charset="%(encoding)s">
+<title>%(title)s</title>
+<style>%(styles)s</style>
+<pre>%(highlighted)s</pre>
+"""
+
+
+def get_template(**kwargs):
+ return HTML_TEMPLATE % dict(**kwargs)
+
+
+class HighlightExportCommand(sublime_plugin.TextCommand):
+ """Code highlighter command."""
+
+ def run(self, edit, target='external', output_type='html'):
+ region = sublime.Region(0, self.view.size())
+ encoding = self.view.encoding()
+ if encoding == 'Undefined':
+ encoding = 'utf-8'
+ elif encoding == 'Western (Windows 1252)':
+ encoding = 'windows-1252'
+ code = self.view.substr(region)
+
+ # pygmentize the code
+ output_type = output_type if output_type in FORMATS else 'html'
+ formatter = get_formatter_by_name(output_type, style='vim', full=True)
+ if self.view.file_name():
+ lexer = get_lexer_for_filename(self.view.file_name(), code)
+ if not lexer:
+ lexer = guess_lexer(code)
+ pygmented = pygments.highlight(code, lexer, formatter)
+
+ if target == 'external':
+ tmp_file = self.write_file('%s.%s' % (self.view.id(), pygmented, encoding), output_type)
+ sublime.status_message(tmp_file)
+ desktop.open(tmp_file)
+ elif target == 'clipboard':
+ sublime.set_clipboard(pygmented)
+ elif target == 'sublime':
+ new_view = self.view.window().new_file()
+ if output_type == 'html':
+ new_view.set_syntax_file('Packages/HTML/HTML.tmLanguage')
+ new_edit = new_view.begin_edit()
+ new_view.insert(new_edit, 0, pygmented)
+ new_view.end_edit(new_edit)
+
+ def write_file(self, filename, contents, encoding='utf-8'):
+ """Writes highlighted contents onto the filesystem."""
+ tmp_fullpath = os.path.join(tempfile.gettempdir(), filename)
+ tmp_file = open(tmp_fullpath, 'w')
+ tmp_file.write(contents.encode(encoding))
+ tmp_file.close()
+ return tmp_fullpath
View
21 Main.sublime-menu
@@ -0,0 +1,21 @@
+[
+ {
+ "id": "edit",
+ "children":
+ [
+ { "id": "highlight_export" },
+ { "children":
+ [
+ { "id": "highligh_export_browser_html" },
+ {
+ "command": "highlight_export",
+ "args": {
+ "target": "browser",
+ "output_type": "html"
+ }
+ }
+ ]
+ }
+ ]
+ }
+]
View
7 README.md
@@ -1,4 +1,5 @@
-SublimeHighlight
-================
+SublimeText2 Highlight Export
+=============================
-An humble SublimeText2 package which export highlighted code
+This SublimeText2 plugin allows to export current editeds code as highlighted
+code using Pygments.
View
281 desktop/__init__.py
@@ -0,0 +1,281 @@
+#!/usr/bin/env python
+
+"""
+Simple desktop integration for Python. This module provides desktop environment
+detection and resource opening support for a selection of common and
+standardised desktop environments.
+
+Copyright (C) 2005, 2006, 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk>
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free
+Software Foundation; either version 3 of the License, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+
+--------
+
+Desktop Detection
+-----------------
+
+To detect a specific desktop environment, use the get_desktop function.
+To detect whether the desktop environment is standardised (according to the
+proposed DESKTOP_LAUNCH standard), use the is_standard function.
+
+Opening URLs
+------------
+
+To open a URL in the current desktop environment, relying on the automatic
+detection of that environment, use the desktop.open function as follows:
+
+desktop.open("http://www.python.org")
+
+To override the detected desktop, specify the desktop parameter to the open
+function as follows:
+
+desktop.open("http://www.python.org", "KDE") # Insists on KDE
+desktop.open("http://www.python.org", "GNOME") # Insists on GNOME
+
+Without overriding using the desktop parameter, the open function will attempt
+to use the "standard" desktop opening mechanism which is controlled by the
+DESKTOP_LAUNCH environment variable as described below.
+
+The DESKTOP_LAUNCH Environment Variable
+---------------------------------------
+
+The DESKTOP_LAUNCH environment variable must be shell-quoted where appropriate,
+as shown in some of the following examples:
+
+DESKTOP_LAUNCH="kdialog --msgbox" Should present any opened URLs in
+ their entirety in a KDE message box.
+ (Command "kdialog" plus parameter.)
+DESKTOP_LAUNCH="my\ opener" Should run the "my opener" program to
+ open URLs.
+ (Command "my opener", no parameters.)
+DESKTOP_LAUNCH="my\ opener --url" Should run the "my opener" program to
+ open URLs.
+ (Command "my opener" plus parameter.)
+
+Details of the DESKTOP_LAUNCH environment variable convention can be found here:
+http://lists.freedesktop.org/archives/xdg/2004-August/004489.html
+
+Other Modules
+-------------
+
+The desktop.dialog module provides support for opening dialogue boxes.
+The desktop.windows module permits the inspection of desktop windows.
+"""
+
+__version__ = "0.4"
+
+import os
+import sys
+
+# Provide suitable process creation functions.
+
+try:
+ import subprocess
+ def _run(cmd, shell, wait):
+ opener = subprocess.Popen(cmd, shell=shell)
+ if wait: opener.wait()
+ return opener.pid
+
+ def _readfrom(cmd, shell):
+ opener = subprocess.Popen(cmd, shell=shell, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ opener.stdin.close()
+ return opener.stdout.read()
+
+ def _status(cmd, shell):
+ opener = subprocess.Popen(cmd, shell=shell)
+ opener.wait()
+ return opener.returncode == 0
+
+except ImportError:
+ import popen2
+ def _run(cmd, shell, wait):
+ opener = popen2.Popen3(cmd)
+ if wait: opener.wait()
+ return opener.pid
+
+ def _readfrom(cmd, shell):
+ opener = popen2.Popen3(cmd)
+ opener.tochild.close()
+ opener.childerr.close()
+ return opener.fromchild.read()
+
+ def _status(cmd, shell):
+ opener = popen2.Popen3(cmd)
+ opener.wait()
+ return opener.poll() == 0
+
+import commands
+
+# Private functions.
+
+def _get_x11_vars():
+
+ "Return suitable environment definitions for X11."
+
+ if not os.environ.get("DISPLAY", "").strip():
+ return "DISPLAY=:0.0 "
+ else:
+ return ""
+
+def _is_xfce():
+
+ "Return whether XFCE is in use."
+
+ # XFCE detection involves testing the output of a program.
+
+ try:
+ return _readfrom(_get_x11_vars() + "xprop -root _DT_SAVE_MODE", shell=1).strip().endswith(' = "xfce4"')
+ except OSError:
+ return 0
+
+def _is_x11():
+
+ "Return whether the X Window System is in use."
+
+ return os.environ.has_key("DISPLAY")
+
+# Introspection functions.
+
+def get_desktop():
+
+ """
+ Detect the current desktop environment, returning the name of the
+ environment. If no environment could be detected, None is returned.
+ """
+
+ if os.environ.has_key("KDE_FULL_SESSION") or \
+ os.environ.has_key("KDE_MULTIHEAD"):
+ return "KDE"
+ elif os.environ.has_key("GNOME_DESKTOP_SESSION_ID") or \
+ os.environ.has_key("GNOME_KEYRING_SOCKET"):
+ return "GNOME"
+ elif sys.platform == "darwin":
+ return "Mac OS X"
+ elif hasattr(os, "startfile"):
+ return "Windows"
+ elif _is_xfce():
+ return "XFCE"
+
+ # KDE, GNOME and XFCE run on X11, so we have to test for X11 last.
+
+ if _is_x11():
+ return "X11"
+ else:
+ return None
+
+def use_desktop(desktop):
+
+ """
+ Decide which desktop should be used, based on the detected desktop and a
+ supplied 'desktop' argument (which may be None). Return an identifier
+ indicating the desktop type as being either "standard" or one of the results
+ from the 'get_desktop' function.
+ """
+
+ # Attempt to detect a desktop environment.
+
+ detected = get_desktop()
+
+ # Start with desktops whose existence can be easily tested.
+
+ if (desktop is None or desktop == "standard") and is_standard():
+ return "standard"
+ elif (desktop is None or desktop == "Windows") and detected == "Windows":
+ return "Windows"
+
+ # Test for desktops where the overriding is not verified.
+
+ elif (desktop or detected) == "KDE":
+ return "KDE"
+ elif (desktop or detected) == "GNOME":
+ return "GNOME"
+ elif (desktop or detected) == "XFCE":
+ return "XFCE"
+ elif (desktop or detected) == "Mac OS X":
+ return "Mac OS X"
+ elif (desktop or detected) == "X11":
+ return "X11"
+ else:
+ return None
+
+def is_standard():
+
+ """
+ Return whether the current desktop supports standardised application
+ launching.
+ """
+
+ return os.environ.has_key("DESKTOP_LAUNCH")
+
+# Activity functions.
+
+def open(url, desktop=None, wait=0):
+
+ """
+ Open the 'url' in the current desktop's preferred file browser. If the
+ optional 'desktop' parameter is specified then attempt to use that
+ particular desktop environment's mechanisms to open the 'url' instead of
+ guessing or detecting which environment is being used.
+
+ Suggested values for 'desktop' are "standard", "KDE", "GNOME", "XFCE",
+ "Mac OS X", "Windows" where "standard" employs a DESKTOP_LAUNCH environment
+ variable to open the specified 'url'. DESKTOP_LAUNCH should be a command,
+ possibly followed by arguments, and must have any special characters
+ shell-escaped.
+
+ The process identifier of the "opener" (ie. viewer, editor, browser or
+ program) associated with the 'url' is returned by this function. If the
+ process identifier cannot be determined, None is returned.
+
+ An optional 'wait' parameter is also available for advanced usage and, if
+ 'wait' is set to a true value, this function will wait for the launching
+ mechanism to complete before returning (as opposed to immediately returning
+ as is the default behaviour).
+ """
+
+ # Decide on the desktop environment in use.
+
+ desktop_in_use = use_desktop(desktop)
+
+ if desktop_in_use == "standard":
+ arg = "".join([os.environ["DESKTOP_LAUNCH"], commands.mkarg(url)])
+ return _run(arg, 1, wait)
+
+ elif desktop_in_use == "Windows":
+ # NOTE: This returns None in current implementations.
+ return os.startfile(url)
+
+ elif desktop_in_use == "KDE":
+ cmd = ["kfmclient", "exec", url]
+
+ elif desktop_in_use == "GNOME":
+ cmd = ["gnome-open", url]
+
+ elif desktop_in_use == "XFCE":
+ cmd = ["exo-open", url]
+
+ elif desktop_in_use == "Mac OS X":
+ cmd = ["open", url]
+
+ elif desktop_in_use == "X11" and os.environ.has_key("BROWSER"):
+ cmd = [os.environ["BROWSER"], url]
+
+ # Finish with an error where no suitable desktop was identified.
+
+ else:
+ raise OSError, "Desktop '%s' not supported (neither DESKTOP_LAUNCH nor os.startfile could be used)" % desktop_in_use
+
+ return _run(cmd, 0, wait)
+
+# vim: tabstop=4 expandtab shiftwidth=4
View
549 desktop/dialog.py
@@ -0,0 +1,549 @@
+#!/usr/bin/env python
+
+"""
+Simple desktop dialogue box support for Python.
+
+Copyright (C) 2007, 2009 Paul Boddie <paul@boddie.org.uk>
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free
+Software Foundation; either version 3 of the License, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+
+--------
+
+Opening Dialogue Boxes (Dialogs)
+--------------------------------
+
+To open a dialogue box (dialog) in the current desktop environment, relying on
+the automatic detection of that environment, use the appropriate dialogue box
+class:
+
+question = desktop.dialog.Question("Are you sure?")
+result = question.open()
+
+To override the detected desktop, specify the desktop parameter to the open
+function as follows:
+
+question.open("KDE") # Insists on KDE
+question.open("GNOME") # Insists on GNOME
+
+The dialogue box options are documented in each class's docstring.
+
+Available dialogue box classes are listed in the desktop.dialog.available
+attribute.
+
+Supported desktop environments are listed in the desktop.dialog.supported
+attribute.
+"""
+
+from desktop import use_desktop, _run, _readfrom, _status
+
+class _wrapper:
+ def __init__(self, handler):
+ self.handler = handler
+
+class _readvalue(_wrapper):
+ def __call__(self, cmd, shell):
+ return self.handler(cmd, shell).strip()
+
+class _readinput(_wrapper):
+ def __call__(self, cmd, shell):
+ return self.handler(cmd, shell)[:-1]
+
+class _readvalues_kdialog(_wrapper):
+ def __call__(self, cmd, shell):
+ result = self.handler(cmd, shell).strip().strip('"')
+ if result:
+ return result.split('" "')
+ else:
+ return []
+
+class _readvalues_zenity(_wrapper):
+ def __call__(self, cmd, shell):
+ result = self.handler(cmd, shell).strip()
+ if result:
+ return result.split("|")
+ else:
+ return []
+
+class _readvalues_Xdialog(_wrapper):
+ def __call__(self, cmd, shell):
+ result = self.handler(cmd, shell).strip()
+ if result:
+ return result.split("/")
+ else:
+ return []
+
+# Dialogue parameter classes.
+
+class String:
+
+ "A generic parameter."
+
+ def __init__(self, name):
+ self.name = name
+
+ def convert(self, value, program):
+ return [value or ""]
+
+class Strings(String):
+
+ "Multiple string parameters."
+
+ def convert(self, value, program):
+ return value or []
+
+class StringPairs(String):
+
+ "Multiple string parameters duplicated to make identifiers."
+
+ def convert(self, value, program):
+ l = []
+ for v in value:
+ l.append(v)
+ l.append(v)
+ return l
+
+class StringKeyword:
+
+ "A keyword parameter."
+
+ def __init__(self, keyword, name):
+ self.keyword = keyword
+ self.name = name
+
+ def convert(self, value, program):
+ return [self.keyword + "=" + (value or "")]
+
+class StringKeywords:
+
+ "Multiple keyword parameters."
+
+ def __init__(self, keyword, name):
+ self.keyword = keyword
+ self.name = name
+
+ def convert(self, value, program):
+ l = []
+ for v in value or []:
+ l.append(self.keyword + "=" + v)
+ return l
+
+class Integer(String):
+
+ "An integer parameter."
+
+ defaults = {
+ "width" : 40,
+ "height" : 15,
+ "list_height" : 10
+ }
+ scale = 8
+
+ def __init__(self, name, pixels=0):
+ String.__init__(self, name)
+ if pixels:
+ self.factor = self.scale
+ else:
+ self.factor = 1
+
+ def convert(self, value, program):
+ if value is None:
+ value = self.defaults[self.name]
+ return [str(int(value) * self.factor)]
+
+class IntegerKeyword(Integer):
+
+ "An integer keyword parameter."
+
+ def __init__(self, keyword, name, pixels=0):
+ Integer.__init__(self, name, pixels)
+ self.keyword = keyword
+
+ def convert(self, value, program):
+ if value is None:
+ value = self.defaults[self.name]
+ return [self.keyword + "=" + str(int(value) * self.factor)]
+
+class Boolean(String):
+
+ "A boolean parameter."
+
+ values = {
+ "kdialog" : ["off", "on"],
+ "zenity" : ["FALSE", "TRUE"],
+ "Xdialog" : ["off", "on"]
+ }
+
+ def convert(self, value, program):
+ values = self.values[program]
+ if value:
+ return [values[1]]
+ else:
+ return [values[0]]
+
+class MenuItemList(String):
+
+ "A menu item list parameter."
+
+ def convert(self, value, program):
+ l = []
+ for v in value:
+ l.append(v.value)
+ l.append(v.text)
+ return l
+
+class ListItemList(String):
+
+ "A radiolist/checklist item list parameter."
+
+ def __init__(self, name, status_first=0):
+ String.__init__(self, name)
+ self.status_first = status_first
+
+ def convert(self, value, program):
+ l = []
+ for v in value:
+ boolean = Boolean(None)
+ status = boolean.convert(v.status, program)
+ if self.status_first:
+ l += status
+ l.append(v.value)
+ l.append(v.text)
+ if not self.status_first:
+ l += status
+ return l
+
+# Dialogue argument values.
+
+class MenuItem:
+
+ "A menu item which can also be used with radiolists and checklists."
+
+ def __init__(self, value, text, status=0):
+ self.value = value
+ self.text = text
+ self.status = status
+
+# Dialogue classes.
+
+class Dialogue:
+
+ commands = {
+ "KDE" : "kdialog",
+ "GNOME" : "zenity",
+ "XFCE" : "zenity", # NOTE: Based on observations with Xubuntu.
+ "X11" : "Xdialog"
+ }
+
+ def open(self, desktop=None):
+
+ """
+ Open a dialogue box (dialog) using a program appropriate to the desktop
+ environment in use.
+
+ If the optional 'desktop' parameter is specified then attempt to use
+ that particular desktop environment's mechanisms to open the dialog
+ instead of guessing or detecting which environment is being used.
+
+ Suggested values for 'desktop' are "standard", "KDE", "GNOME",
+ "Mac OS X", "Windows".
+
+ The result of the dialogue interaction may be a string indicating user
+ input (for Input, Password, Menu, Pulldown), a list of strings
+ indicating selections of one or more items (for RadioList, CheckList),
+ or a value indicating true or false (for Question, Warning, Message,
+ Error).
+
+ Where a string value may be expected but no choice is made, an empty
+ string may be returned. Similarly, where a list of values is expected
+ but no choice is made, an empty list may be returned.
+ """
+
+ # Decide on the desktop environment in use.
+
+ desktop_in_use = use_desktop(desktop)
+
+ # Get the program.
+
+ try:
+ program = self.commands[desktop_in_use]
+ except KeyError:
+ raise OSError, "Desktop '%s' not supported (no known dialogue box command could be suggested)" % desktop_in_use
+
+ # The handler is one of the functions communicating with the subprocess.
+ # Some handlers return boolean values, others strings.
+
+ handler, options = self.info[program]
+
+ cmd = [program]
+ for option in options:
+ if isinstance(option, str):
+ cmd.append(option)
+ else:
+ value = getattr(self, option.name, None)
+ cmd += option.convert(value, program)
+
+ return handler(cmd, 0)
+
+class Simple(Dialogue):
+ def __init__(self, text, width=None, height=None):
+ self.text = text
+ self.width = width
+ self.height = height
+
+class Question(Simple):
+
+ """
+ A dialogue asking a question and showing response buttons.
+ Options: text, width (in characters), height (in characters)
+ Response: a boolean value indicating an affirmative response (true) or a
+ negative response
+ """
+
+ name = "question"
+ info = {
+ "kdialog" : (_status, ["--yesno", String("text")]),
+ "zenity" : (_status, ["--question", StringKeyword("--text", "text")]),
+ "Xdialog" : (_status, ["--stdout", "--yesno", String("text"), Integer("height"), Integer("width")]),
+ }
+
+class Warning(Simple):
+
+ """
+ A dialogue asking a question and showing response buttons.
+ Options: text, width (in characters), height (in characters)
+ Response: a boolean value indicating an affirmative response (true) or a
+ negative response
+ """
+
+ name = "warning"
+ info = {
+ "kdialog" : (_status, ["--warningyesno", String("text")]),
+ "zenity" : (_status, ["--warning", StringKeyword("--text", "text")]),
+ "Xdialog" : (_status, ["--stdout", "--yesno", String("text"), Integer("height"), Integer("width")]),
+ }
+
+class Message(Simple):
+
+ """
+ A message dialogue.
+ Options: text, width (in characters), height (in characters)
+ Response: a boolean value indicating an affirmative response (true) or a
+ negative response
+ """
+
+ name = "message"
+ info = {
+ "kdialog" : (_status, ["--msgbox", String("text")]),
+ "zenity" : (_status, ["--info", StringKeyword("--text", "text")]),
+ "Xdialog" : (_status, ["--stdout", "--msgbox", String("text"), Integer("height"), Integer("width")]),
+ }
+
+class Error(Simple):
+
+ """
+ An error dialogue.
+ Options: text, width (in characters), height (in characters)
+ Response: a boolean value indicating an affirmative response (true) or a
+ negative response
+ """
+
+ name = "error"
+ info = {
+ "kdialog" : (_status, ["--error", String("text")]),
+ "zenity" : (_status, ["--error", StringKeyword("--text", "text")]),
+ "Xdialog" : (_status, ["--stdout", "--msgbox", String("text"), Integer("height"), Integer("width")]),
+ }
+
+class Menu(Simple):
+
+ """
+ A menu of options, one of which being selectable.
+ Options: text, width (in characters), height (in characters),
+ list_height (in items), items (MenuItem objects)
+ Response: a value corresponding to the chosen item
+ """
+
+ name = "menu"
+ info = {
+ "kdialog" : (_readvalue(_readfrom), ["--menu", String("text"), MenuItemList("items")]),
+ "zenity" : (_readvalue(_readfrom), ["--list", StringKeyword("--text", "text"), StringKeywords("--column", "titles"),
+ MenuItemList("items")]
+ ),
+ "Xdialog" : (_readvalue(_readfrom), ["--stdout", "--menubox",
+ String("text"), Integer("height"), Integer("width"), Integer("list_height"), MenuItemList("items")]
+ ),
+ }
+ item = MenuItem
+ number_of_titles = 2
+
+ def __init__(self, text, titles, items=None, width=None, height=None, list_height=None):
+
+ """
+ Initialise a menu with the given heading 'text', column 'titles', and
+ optional 'items' (which may be added later), 'width' (in characters),
+ 'height' (in characters) and 'list_height' (in items).
+ """
+
+ Simple.__init__(self, text, width, height)
+ self.titles = ([""] * self.number_of_titles + titles)[-self.number_of_titles:]
+ self.items = items or []
+ self.list_height = list_height
+
+ def add(self, *args, **kw):
+
+ """
+ Add an item, passing the given arguments to the appropriate item class.
+ """
+
+ self.items.append(self.item(*args, **kw))
+
+class RadioList(Menu):
+
+ """
+ A list of radio buttons, one of which being selectable.
+ Options: text, width (in characters), height (in characters),
+ list_height (in items), items (MenuItem objects), titles
+ Response: a list of values corresponding to chosen items (since some
+ programs, eg. zenity, appear to support multiple default
+ selections)
+ """
+
+ name = "radiolist"
+ info = {
+ "kdialog" : (_readvalues_kdialog(_readfrom), ["--radiolist", String("text"), ListItemList("items")]),
+ "zenity" : (_readvalues_zenity(_readfrom),
+ ["--list", "--radiolist", StringKeyword("--text", "text"), StringKeywords("--column", "titles"),
+ ListItemList("items", 1)]
+ ),
+ "Xdialog" : (_readvalues_Xdialog(_readfrom), ["--stdout", "--radiolist",
+ String("text"), Integer("height"), Integer("width"), Integer("list_height"), ListItemList("items")]
+ ),
+ }
+ number_of_titles = 3
+
+class CheckList(Menu):
+
+ """
+ A list of checkboxes, many being selectable.
+ Options: text, width (in characters), height (in characters),
+ list_height (in items), items (MenuItem objects), titles
+ Response: a list of values corresponding to chosen items
+ """
+
+ name = "checklist"
+ info = {
+ "kdialog" : (_readvalues_kdialog(_readfrom), ["--checklist", String("text"), ListItemList("items")]),
+ "zenity" : (_readvalues_zenity(_readfrom),
+ ["--list", "--checklist", StringKeyword("--text", "text"), StringKeywords("--column", "titles"),
+ ListItemList("items", 1)]
+ ),
+ "Xdialog" : (_readvalues_Xdialog(_readfrom), ["--stdout", "--checklist",
+ String("text"), Integer("height"), Integer("width"), Integer("list_height"), ListItemList("items")]
+ ),
+ }
+ number_of_titles = 3
+
+class Pulldown(Menu):
+
+ """
+ A pull-down menu of options, one of which being selectable.
+ Options: text, width (in characters), height (in characters),
+ items (list of values)
+ Response: a value corresponding to the chosen item
+ """
+
+ name = "pulldown"
+ info = {
+ "kdialog" : (_readvalue(_readfrom), ["--combobox", String("text"), Strings("items")]),
+ "zenity" : (_readvalue(_readfrom),
+ ["--list", "--radiolist", StringKeyword("--text", "text"), StringKeywords("--column", "titles"),
+ StringPairs("items")]
+ ),
+ "Xdialog" : (_readvalue(_readfrom),
+ ["--stdout", "--combobox", String("text"), Integer("height"), Integer("width"), Strings("items")]),
+ }
+ item = unicode
+ number_of_titles = 2
+
+class Input(Simple):
+
+ """
+ An input dialogue, consisting of an input field.
+ Options: text, input, width (in characters), height (in characters)
+ Response: the text entered into the dialogue by the user
+ """
+
+ name = "input"
+ info = {
+ "kdialog" : (_readinput(_readfrom),
+ ["--inputbox", String("text"), String("data")]),
+ "zenity" : (_readinput(_readfrom),
+ ["--entry", StringKeyword("--text", "text"), StringKeyword("--entry-text", "data")]),
+ "Xdialog" : (_readinput(_readfrom),
+ ["--stdout", "--inputbox", String("text"), Integer("height"), Integer("width"), String("data")]),
+ }
+
+ def __init__(self, text, data="", width=None, height=None):
+ Simple.__init__(self, text, width, height)
+ self.data = data
+
+class Password(Input):
+
+ """
+ A password dialogue, consisting of a password entry field.
+ Options: text, width (in characters), height (in characters)
+ Response: the text entered into the dialogue by the user
+ """
+
+ name = "password"
+ info = {
+ "kdialog" : (_readinput(_readfrom),
+ ["--password", String("text")]),
+ "zenity" : (_readinput(_readfrom),
+ ["--entry", StringKeyword("--text", "text"), "--hide-text"]),
+ "Xdialog" : (_readinput(_readfrom),
+ ["--stdout", "--password", "--inputbox", String("text"), Integer("height"), Integer("width")]),
+ }
+
+class TextFile(Simple):
+
+ """
+ A text file input box.
+ Options: filename, text, width (in characters), height (in characters)
+ Response: any text returned by the dialogue program (typically an empty
+ string)
+ """
+
+ name = "textfile"
+ info = {
+ "kdialog" : (_readfrom, ["--textbox", String("filename"), Integer("width", pixels=1), Integer("height", pixels=1)]),
+ "zenity" : (_readfrom, ["--text-info", StringKeyword("--filename", "filename"), IntegerKeyword("--width", "width", pixels=1),
+ IntegerKeyword("--height", "height", pixels=1)]
+ ),
+ "Xdialog" : (_readfrom, ["--stdout", "--textbox", String("filename"), Integer("height"), Integer("width")]),
+ }
+
+ def __init__(self, filename, text="", width=None, height=None):
+ Simple.__init__(self, text, width, height)
+ self.filename = filename
+
+# Available dialogues.
+
+available = [Question, Warning, Message, Error, Menu, CheckList, RadioList, Input, Password, Pulldown, TextFile]
+
+# Supported desktop environments.
+
+supported = Dialogue.commands.keys()
+
+# vim: tabstop=4 expandtab shiftwidth=4
View
273 desktop/windows.py
@@ -0,0 +1,273 @@
+#!/usr/bin/env python
+
+"""
+Simple desktop window enumeration for Python.
+
+Copyright (C) 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk>
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free
+Software Foundation; either version 3 of the License, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+
+--------
+
+Finding Open Windows on the Desktop
+-----------------------------------
+
+To obtain a list of windows, use the desktop.windows.list function as follows:
+
+windows = desktop.windows.list()
+
+To obtain the root window, typically the desktop background, use the
+desktop.windows.root function as follows:
+
+root = desktop.windows.root()
+
+Each window object can be inspected through a number of methods. For example:
+
+name = window.name()
+width, height = window.size()
+x, y = window.position()
+child_windows = window.children()
+
+See the desktop.windows.Window class for more information.
+"""
+
+from desktop import _is_x11, _get_x11_vars, _readfrom, use_desktop
+import re
+
+# System functions.
+
+def _xwininfo(identifier, action):
+ if identifier is None:
+ args = "-root"
+ else:
+ args = "-id " + identifier
+
+ s = _readfrom(_get_x11_vars() + "xwininfo %s -%s" % (args, action), shell=1)
+
+ # Return a mapping of keys to values for the "stats" action.
+
+ if action == "stats":
+ d = {}
+ for line in s.split("\n"):
+ fields = line.split(":")
+ if len(fields) < 2:
+ continue
+ key, value = fields[0].strip(), ":".join(fields[1:]).strip()
+ d[key] = value
+
+ return d
+
+ # Otherwise, return the raw output.
+
+ else:
+ return s
+
+def _get_int_properties(d, properties):
+ results = []
+ for property in properties:
+ results.append(int(d[property]))
+ return results
+
+# Finder functions.
+
+def find_all(name):
+ return 1
+
+def find_named(name):
+ return name is not None
+
+def find_by_name(name):
+ return lambda n, t=name: n == t
+
+# Window classes.
+# NOTE: X11 is the only supported desktop so far.
+
+class Window:
+
+ "A window on the desktop."
+
+ _name_pattern = re.compile(r':\s+\(.*?\)\s+[-0-9x+]+\s+[-0-9+]+$')
+ _absent_names = "(has no name)", "(the root window) (has no name)"
+
+ def __init__(self, identifier):
+
+ "Initialise the window with the given 'identifier'."
+
+ self.identifier = identifier
+
+ # Finder methods (from above).
+
+ self.find_all = find_all
+ self.find_named = find_named
+ self.find_by_name = find_by_name
+
+ def __repr__(self):
+ return "Window(%r)" % self.identifier
+
+ # Methods which deal with the underlying commands.
+
+ def _get_handle_and_name(self, text):
+ fields = text.strip().split(" ")
+ handle = fields[0]
+
+ # Get the "<name>" part, stripping off the quotes.
+
+ name = " ".join(fields[1:])
+ if len(name) > 1 and name[0] == '"' and name[-1] == '"':
+ name = name[1:-1]
+
+ if name in self._absent_names:
+ return handle, None
+ else:
+ return handle, name
+
+ def _get_this_handle_and_name(self, line):
+ fields = line.split(":")
+ return self._get_handle_and_name(":".join(fields[1:]))
+
+ def _get_descendant_handle_and_name(self, line):
+ match = self._name_pattern.search(line)
+ if match:
+ return self._get_handle_and_name(line[:match.start()].strip())
+ else:
+ raise OSError, "Window information from %r did not contain window details." % line
+
+ def _descendants(self, s, fn):
+ handles = []
+ adding = 0
+ for line in s.split("\n"):
+ if line.endswith("child:") or line.endswith("children:"):
+ if not adding:
+ adding = 1
+ elif adding and line:
+ handle, name = self._get_descendant_handle_and_name(line)
+ if fn(name):
+ handles.append(handle)
+ return [Window(handle) for handle in handles]
+
+ # Public methods.
+
+ def children(self, all=0):
+
+ """
+ Return a list of windows which are children of this window. If the
+ optional 'all' parameter is set to a true value, all such windows will
+ be returned regardless of whether they have any name information.
+ """
+
+ s = _xwininfo(self.identifier, "children")
+ return self._descendants(s, all and self.find_all or self.find_named)
+
+ def descendants(self, all=0):
+
+ """
+ Return a list of windows which are descendants of this window. If the
+ optional 'all' parameter is set to a true value, all such windows will
+ be returned regardless of whether they have any name information.
+ """
+
+ s = _xwininfo(self.identifier, "tree")
+ return self._descendants(s, all and self.find_all or self.find_named)
+
+ def find(self, callable):
+
+ """
+ Return windows using the given 'callable' (returning a true or a false
+ value when invoked with a window name) for descendants of this window.
+ """
+
+ s = _xwininfo(self.identifier, "tree")
+ return self._descendants(s, callable)
+
+ def name(self):
+
+ "Return the name of the window."
+
+ d = _xwininfo(self.identifier, "stats")
+
+ # Format is 'xwininfo: Window id: <handle> "<name>"
+
+ return self._get_this_handle_and_name(d["xwininfo"])[1]
+
+ def size(self):
+
+ "Return a tuple containing the width and height of this window."
+
+ d = _xwininfo(self.identifier, "stats")
+ return _get_int_properties(d, ["Width", "Height"])
+
+ def position(self):
+
+ "Return a tuple containing the upper left co-ordinates of this window."
+
+ d = _xwininfo(self.identifier, "stats")
+ return _get_int_properties(d, ["Absolute upper-left X", "Absolute upper-left Y"])
+
+ def displayed(self):
+
+ """
+ Return whether the window is displayed in some way (but not necessarily
+ visible on the current screen).
+ """
+
+ d = _xwininfo(self.identifier, "stats")
+ return d["Map State"] != "IsUnviewable"
+
+ def visible(self):
+
+ "Return whether the window is displayed and visible."
+
+ d = _xwininfo(self.identifier, "stats")
+ return d["Map State"] == "IsViewable"
+
+def list(desktop=None):
+
+ """
+ Return a list of windows for the current desktop. If the optional 'desktop'
+ parameter is specified then attempt to use that particular desktop
+ environment's mechanisms to look for windows.
+ """
+
+ root_window = root(desktop)
+ window_list = [window for window in root_window.descendants() if window.displayed()]
+ window_list.insert(0, root_window)
+ return window_list
+
+def root(desktop=None):
+
+ """
+ Return the root window for the current desktop. If the optional 'desktop'
+ parameter is specified then attempt to use that particular desktop
+ environment's mechanisms to look for windows.
+ """
+
+ # NOTE: The desktop parameter is currently ignored and X11 is tested for
+ # NOTE: directly.
+
+ if _is_x11():
+ return Window(None)
+ else:
+ raise OSError, "Desktop '%s' not supported" % use_desktop(desktop)
+
+def find(callable, desktop=None):
+
+ """
+ Find and return windows using the given 'callable' for the current desktop.
+ If the optional 'desktop' parameter is specified then attempt to use that
+ particular desktop environment's mechanisms to look for windows.
+ """
+
+ return root(desktop).find(callable)
+
+# vim: tabstop=4 expandtab shiftwidth=4
View
91 pygments/__init__.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+"""
+ Pygments
+ ~~~~~~~~
+
+ Pygments is a syntax highlighting package written in Python.
+
+ It is a generic syntax highlighter for general use in all kinds of software
+ such as forum systems, wikis or other applications that need to prettify
+ source code. Highlights are:
+
+ * a wide range of common languages and markup formats is supported
+ * special attention is paid to details, increasing quality by a fair amount
+ * support for new languages and formats are added easily
+ * a number of output formats, presently HTML, LaTeX, RTF, SVG, all image
+ formats that PIL supports, and ANSI sequences
+ * it is usable as a command-line tool and as a library
+ * ... and it highlights even Brainfuck!
+
+ The `Pygments tip`_ is installable with ``easy_install Pygments==dev``.
+
+ .. _Pygments tip:
+ http://bitbucket.org/birkenfeld/pygments-main/get/tip.zip#egg=Pygments-dev
+
+ :copyright: Copyright 2006-2012 by the Pygments team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+__version__ = '1.5'
+__docformat__ = 'restructuredtext'
+
+__all__ = ['lex', 'format', 'highlight']
+
+
+import sys
+
+from pygments.util import StringIO, BytesIO
+
+
+def lex(code, lexer):
+ """
+ Lex ``code`` with ``lexer`` and return an iterable of tokens.
+ """
+ try:
+ return lexer.get_tokens(code)
+ except TypeError, err:
+ if isinstance(err.args[0], str) and \
+ 'unbound method get_tokens' in err.args[0]:
+ raise TypeError('lex() argument must be a lexer instance, '
+ 'not a class')
+ raise
+
+
+def format(tokens, formatter, outfile=None):
+ """
+ Format a tokenlist ``tokens`` with the formatter ``formatter``.
+
+ If ``outfile`` is given and a valid file object (an object
+ with a ``write`` method), the result will be written to it, otherwise
+ it is returned as a string.
+ """
+ try:
+ if not outfile:
+ #print formatter, 'using', formatter.encoding
+ realoutfile = formatter.encoding and BytesIO() or StringIO()
+ formatter.format(tokens, realoutfile)
+ return realoutfile.getvalue()
+ else:
+ formatter.format(tokens, outfile)
+ except TypeError, err:
+ if isinstance(err.args[0], str) and \
+ 'unbound method format' in err.args[0]:
+ raise TypeError('format() argument must be a formatter instance, '
+ 'not a class')
+ raise
+
+
+def highlight(code, lexer, formatter, outfile=None):
+ """
+ Lex ``code`` with ``lexer`` and format it with the formatter ``formatter``.
+
+ If ``outfile`` is given and a valid file object (an object
+ with a ``write`` method), the result will be written to it, otherwise
+ it is returned as a string.
+ """
+ return format(lex(code, lexer), formatter, outfile)
+
+
+if __name__ == '__main__':
+ from pygments.cmdline import main
+ sys.exit(main(sys.argv))
View
433 pygments/cmdline.py
@@ -0,0 +1,433 @@
+# -*- coding: utf-8 -*-
+"""
+ pygments.cmdline
+ ~~~~~~~~~~~~~~~~
+
+ Command line interface.
+
+ :copyright: Copyright 2006-2012 by the Pygments team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import sys
+import getopt
+from textwrap import dedent
+
+from pygments import __version__, highlight
+from pygments.util import ClassNotFound, OptionError, docstring_headline
+from pygments.lexers import get_all_lexers, get_lexer_by_name, get_lexer_for_filename, \
+ find_lexer_class, guess_lexer, TextLexer
+from pygments.formatters import get_all_formatters, get_formatter_by_name, \
+ get_formatter_for_filename, find_formatter_class, \
+ TerminalFormatter # pylint:disable-msg=E0611
+from pygments.filters import get_all_filters, find_filter_class
+from pygments.styles import get_all_styles, get_style_by_name
+
+
+USAGE = """\
+Usage: %s [-l <lexer> | -g] [-F <filter>[:<options>]] [-f <formatter>]
+ [-O <options>] [-P <option=value>] [-o <outfile>] [<infile>]
+
+ %s -S <style> -f <formatter> [-a <arg>] [-O <options>] [-P <option=value>]
+ %s -L [<which> ...]
+ %s -N <filename>
+ %s -H <type> <name>
+ %s -h | -V
+
+Highlight the input file and write the result to <outfile>.
+
+If no input file is given, use stdin, if -o is not given, use stdout.
+
+<lexer> is a lexer name (query all lexer names with -L). If -l is not
+given, the lexer is guessed from the extension of the input file name
+(this obviously doesn't work if the input is stdin). If -g is passed,
+attempt to guess the lexer from the file contents, or pass through as
+plain text if this fails (this can work for stdin).
+
+Likewise, <formatter> is a formatter name, and will be guessed from
+the extension of the output file name. If no output file is given,
+the terminal formatter will be used by default.
+
+With the -O option, you can give the lexer and formatter a comma-
+separated list of options, e.g. ``-O bg=light,python=cool``.
+
+The -P option adds lexer and formatter options like the -O option, but
+you can only give one option per -P. That way, the option value may
+contain commas and equals signs, which it can't with -O, e.g.
+``-P "heading=Pygments, the Python highlighter".
+
+With the -F option, you can add filters to the token stream, you can
+give options in the same way as for -O after a colon (note: there must
+not be spaces around the colon).
+
+The -O, -P and -F options can be given multiple times.
+
+With the -S option, print out style definitions for style <style>
+for formatter <formatter>. The argument given by -a is formatter
+dependent.
+
+The -L option lists lexers, formatters, styles or filters -- set
+`which` to the thing you want to list (e.g. "styles"), or omit it to
+list everything.
+
+The -N option guesses and prints out a lexer name based solely on
+the given filename. It does not take input or highlight anything.
+If no specific lexer can be determined "text" is returned.
+
+The -H option prints detailed help for the object <name> of type <type>,
+where <type> is one of "lexer", "formatter" or "filter".
+
+The -h option prints this help.
+The -V option prints the package version.
+"""
+
+
+def _parse_options(o_strs):
+ opts = {}
+ if not o_strs:
+ return opts
+ for o_str in o_strs:
+ if not o_str:
+ continue
+ o_args = o_str.split(',')
+ for o_arg in o_args:
+ o_arg = o_arg.strip()
+ try:
+ o_key, o_val = o_arg.split('=')
+ o_key = o_key.strip()
+ o_val = o_val.strip()
+ except ValueError:
+ opts[o_arg] = True
+ else:
+ opts[o_key] = o_val
+ return opts
+
+
+def _parse_filters(f_strs):
+ filters = []
+ if not f_strs:
+ return filters
+ for f_str in f_strs:
+ if ':' in f_str:
+ fname, fopts = f_str.split(':', 1)
+ filters.append((fname, _parse_options([fopts])))
+ else:
+ filters.append((f_str, {}))
+ return filters
+
+
+def _print_help(what, name):
+ try:
+ if what == 'lexer':
+ cls = find_lexer_class(name)
+ print "Help on the %s lexer:" % cls.name
+ print dedent(cls.__doc__)
+ elif what == 'formatter':
+ cls = find_formatter_class(name)
+ print "Help on the %s formatter:" % cls.name
+ print dedent(cls.__doc__)
+ elif what == 'filter':
+ cls = find_filter_class(name)
+ print "Help on the %s filter:" % name
+ print dedent(cls.__doc__)
+ except AttributeError:
+ print >>sys.stderr, "%s not found!" % what
+
+
+def _print_list(what):
+ if what == 'lexer':
+ print
+ print "Lexers:"
+ print "~~~~~~~"
+
+ info = []
+ for fullname, names, exts, _ in get_all_lexers():
+ tup = (', '.join(names)+':', fullname,
+ exts and '(filenames ' + ', '.join(exts) + ')' or '')
+ info.append(tup)
+ info.sort()
+ for i in info:
+ print ('* %s\n %s %s') % i
+
+ elif what == 'formatter':
+ print
+ print "Formatters:"
+ print "~~~~~~~~~~~"
+
+ info = []
+ for cls in get_all_formatters():
+ doc = docstring_headline(cls)
+ tup = (', '.join(cls.aliases) + ':', doc, cls.filenames and
+ '(filenames ' + ', '.join(cls.filenames) + ')' or '')
+ info.append(tup)
+ info.sort()
+ for i in info:
+ print ('* %s\n %s %s') % i
+
+ elif what == 'filter':
+ print
+ print "Filters:"
+ print "~~~~~~~~"
+
+ for name in get_all_filters():
+ cls = find_filter_class(name)
+ print "* " + name + ':'
+ print " %s" % docstring_headline(cls)
+
+ elif what == 'style':
+ print
+ print "Styles:"
+ print "~~~~~~~"
+
+ for name in get_all_styles():
+ cls = get_style_by_name(name)
+ print "* " + name + ':'
+ print " %s" % docstring_headline(cls)
+
+
+def main(args=sys.argv):
+ """
+ Main command line entry point.
+ """
+ # pylint: disable-msg=R0911,R0912,R0915
+
+ usage = USAGE % ((args[0],) * 6)
+
+ try:
+ popts, args = getopt.getopt(args[1:], "l:f:F:o:O:P:LS:a:N:hVHg")
+ except getopt.GetoptError, err:
+ print >>sys.stderr, usage
+ return 2
+ opts = {}
+ O_opts = []
+ P_opts = []
+ F_opts = []
+ for opt, arg in popts:
+ if opt == '-O':
+ O_opts.append(arg)
+ elif opt == '-P':
+ P_opts.append(arg)
+ elif opt == '-F':
+ F_opts.append(arg)
+ opts[opt] = arg
+
+ if not opts and not args:
+ print usage
+ return 0
+
+ if opts.pop('-h', None) is not None:
+ print usage
+ return 0
+
+ if opts.pop('-V', None) is not None:
+ print 'Pygments version %s, (c) 2006-2011 by Georg Brandl.' % __version__
+ return 0
+
+ # handle ``pygmentize -L``
+ L_opt = opts.pop('-L', None)
+ if L_opt is not None:
+ if opts:
+ print >>sys.stderr, usage
+ return 2
+
+ # print version
+ main(['', '-V'])
+ if not args:
+ args = ['lexer', 'formatter', 'filter', 'style']
+ for arg in args:
+ _print_list(arg.rstrip('s'))
+ return 0
+
+ # handle ``pygmentize -H``
+ H_opt = opts.pop('-H', None)
+ if H_opt is not None:
+ if opts or len(args) != 2:
+ print >>sys.stderr, usage
+ return 2
+
+ what, name = args
+ if what not in ('lexer', 'formatter', 'filter'):
+ print >>sys.stderr, usage
+ return 2
+
+ _print_help(what, name)
+ return 0
+
+ # parse -O options
+ parsed_opts = _parse_options(O_opts)
+ opts.pop('-O', None)
+
+ # parse -P options
+ for p_opt in P_opts:
+ try:
+ name, value = p_opt.split('=', 1)
+ except ValueError:
+ parsed_opts[p_opt] = True
+ else:
+ parsed_opts[name] = value
+ opts.pop('-P', None)
+
+ # handle ``pygmentize -N``
+ infn = opts.pop('-N', None)
+ if infn is not None:
+ try:
+ lexer = get_lexer_for_filename(infn, **parsed_opts)
+ except ClassNotFound, err:
+ lexer = TextLexer()
+ except OptionError, err:
+ print >>sys.stderr, 'Error:', err
+ return 1
+
+ print lexer.aliases[0]
+ return 0
+
+ # handle ``pygmentize -S``
+ S_opt = opts.pop('-S', None)
+ a_opt = opts.pop('-a', None)
+ if S_opt is not None:
+ f_opt = opts.pop('-f', None)
+ if not f_opt:
+ print >>sys.stderr, usage
+ return 2
+ if opts or args:
+ print >>sys.stderr, usage
+ return 2
+
+ try:
+ parsed_opts['style'] = S_opt
+ fmter = get_formatter_by_name(f_opt, **parsed_opts)
+ except ClassNotFound, err:
+ print >>sys.stderr, err
+ return 1
+
+ arg = a_opt or ''
+ try:
+ print fmter.get_style_defs(arg)
+ except Exception, err:
+ print >>sys.stderr, 'Error:', err
+ return 1
+ return 0
+
+ # if no -S is given, -a is not allowed
+ if a_opt is not None:
+ print >>sys.stderr, usage
+ return 2
+
+ # parse -F options
+ F_opts = _parse_filters(F_opts)
+ opts.pop('-F', None)
+
+ # select formatter
+ outfn = opts.pop('-o', None)
+ fmter = opts.pop('-f', None)
+ if fmter:
+ try:
+ fmter = get_formatter_by_name(fmter, **parsed_opts)
+ except (OptionError, ClassNotFound), err:
+ print >>sys.stderr, 'Error:', err
+ return 1
+
+ if outfn:
+ if not fmter:
+ try:
+ fmter = get_formatter_for_filename(outfn, **parsed_opts)
+ except (OptionError, ClassNotFound), err:
+ print >>sys.stderr, 'Error:', err
+ return 1
+ try:
+ outfile = open(outfn, 'wb')
+ except Exception, err:
+ print >>sys.stderr, 'Error: cannot open outfile:', err
+ return 1
+ else:
+ if not fmter:
+ fmter = TerminalFormatter(**parsed_opts)
+ outfile = sys.stdout
+
+ # select lexer
+ lexer = opts.pop('-l', None)
+ if lexer:
+ try:
+ lexer = get_lexer_by_name(lexer, **parsed_opts)
+ except (OptionError, ClassNotFound), err:
+ print >>sys.stderr, 'Error:', err
+ return 1
+
+ if args:
+ if len(args) > 1:
+ print >>sys.stderr, usage
+ return 2
+
+ infn = args[0]
+ try:
+ code = open(infn, 'rb').read()
+ except Exception, err:
+ print >>sys.stderr, 'Error: cannot read infile:', err
+ return 1
+
+ if not lexer:
+ try:
+ lexer = get_lexer_for_filename(infn, code, **parsed_opts)
+ except ClassNotFound, err:
+ if '-g' in opts:
+ try:
+ lexer = guess_lexer(code)
+ except ClassNotFound:
+ lexer = TextLexer()
+ else:
+ print >>sys.stderr, 'Error:', err
+ return 1
+ except OptionError, err:
+ print >>sys.stderr, 'Error:', err
+ return 1
+
+ else:
+ if '-g' in opts:
+ code = sys.stdin.read()
+ try:
+ lexer = guess_lexer(code)
+ except ClassNotFound:
+ lexer = TextLexer()
+ elif not lexer:
+ print >>sys.stderr, 'Error: no lexer name given and reading ' + \
+ 'from stdin (try using -g or -l <lexer>)'
+ return 2
+ else:
+ code = sys.stdin.read()
+
+ # No encoding given? Use latin1 if output file given,
+ # stdin/stdout encoding otherwise.
+ # (This is a compromise, I'm not too happy with it...)
+ if 'encoding' not in parsed_opts and 'outencoding' not in parsed_opts:
+ if outfn:
+ # encoding pass-through
+ fmter.encoding = 'latin1'
+ else:
+ if sys.version_info < (3,):
+ # use terminal encoding; Python 3's terminals already do that
+ lexer.encoding = getattr(sys.stdin, 'encoding',
+ None) or 'ascii'
+ fmter.encoding = getattr(sys.stdout, 'encoding',
+ None) or 'ascii'
+ elif not outfn and sys.version_info > (3,):
+ # output to terminal with encoding -> use .buffer
+ outfile = sys.stdout.buffer
+
+ # ... and do it!
+ try:
+ # process filters
+ for fname, fopts in F_opts:
+ lexer.add_filter(fname, **fopts)
+ highlight(code, lexer, fmter, outfile)
+ except Exception, err:
+ import traceback
+ info = traceback.format_exception(*sys.exc_info())
+ msg = info[-1].strip()
+ if len(info) >= 3:
+ # extract relevant file and position info
+ msg += '\n (f%s)' % info[-2].split('\n')[0].strip()[1:]
+ print >>sys.stderr
+ print >>sys.stderr, '*** Error while highlighting:'
+ print >>sys.stderr, msg
+ return 1
+
+ return 0
View
74 pygments/console.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+"""
+ pygments.console
+ ~~~~~~~~~~~~~~~~
+
+ Format colored console output.
+
+ :copyright: Copyright 2006-2012 by the Pygments team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+esc = "\x1b["
+
+codes = {}
+codes[""] = ""
+codes["reset"] = esc + "39;49;00m"
+
+codes["bold"] = esc + "01m"
+codes["faint"] = esc + "02m"
+codes["standout"] = esc + "03m"
+codes["underline"] = esc + "04m"
+codes["blink"] = esc + "05m"
+codes["overline"] = esc + "06m"
+
+dark_colors = ["black", "darkred", "darkgreen", "brown", "darkblue",
+ "purple", "teal", "lightgray"]
+light_colors = ["darkgray", "red", "green", "yellow", "blue",
+ "fuchsia", "turquoise", "white"]
+
+x = 30
+for d, l in zip(dark_colors, light_colors):
+ codes[d] = esc + "%im" % x
+ codes[l] = esc + "%i;01m" % x
+ x += 1
+
+del d, l, x
+
+codes["darkteal"] = codes["turquoise"]
+codes["darkyellow"] = codes["brown"]
+codes["fuscia"] = codes["fuchsia"]
+codes["white"] = codes["bold"]
+
+
+def reset_color():
+ return codes["reset"]
+
+
+def colorize(color_key, text):
+ return codes[color_key] + text + codes["reset"]
+
+
+def ansiformat(attr, text):
+ """
+ Format ``text`` with a color and/or some attributes::
+
+ color normal color
+ *color* bold color
+ _color_ underlined color
+ +color+ blinking color
+ """
+ result = []
+ if attr[:1] == attr[-1:] == '+':
+ result.append(codes['blink'])
+ attr = attr[1:-1]
+ if attr[:1] == attr[-1:] == '*':
+ result.append(codes['bold'])
+ attr = attr[1:-1]
+ if attr[:1] == attr[-1:] == '_':
+ result.append(codes['underline'])
+ attr = attr[1:-1]
+ result.append(codes[attr])
+ result.append(text)
+ result.append(codes['reset'])
+ return ''.join(result)
View
74 pygments/filter.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+"""
+ pygments.filter
+ ~~~~~~~~~~~~~~~
+
+ Module that implements the default filter.
+
+ :copyright: Copyright 2006-2012 by the Pygments team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+
+def apply_filters(stream, filters, lexer=None):
+ """
+ Use this method to apply an iterable of filters to
+ a stream. If lexer is given it's forwarded to the
+ filter, otherwise the filter receives `None`.
+ """
+ def _apply(filter_, stream):
+ for token in filter_.filter(lexer, stream):
+ yield token
+ for filter_ in filters:
+ stream = _apply(filter_, stream)
+ return stream
+
+
+def simplefilter(f):
+ """
+ Decorator that converts a function into a filter::
+
+ @simplefilter
+ def lowercase(lexer, stream, options):
+ for ttype, value in stream:
+ yield ttype, value.lower()
+ """
+ return type(f.__name__, (FunctionFilter,), {
+ 'function': f,
+ '__module__': getattr(f, '__module__'),
+ '__doc__': f.__doc__
+ })
+
+
+class Filter(object):
+ """
+ Default filter. Subclass this class or use the `simplefilter`
+ decorator to create own filters.
+ """
+
+ def __init__(self, **options):
+ self.options = options
+
+ def filter(self, lexer, stream):
+ raise NotImplementedError()
+
+
+class FunctionFilter(Filter):
+ """
+ Abstract class used by `simplefilter` to create simple
+ function filters on the fly. The `simplefilter` decorator
+ automatically creates subclasses of this class for
+ functions passed to it.
+ """
+ function = None
+
+ def __init__(self, **options):
+ if not hasattr(self, 'function'):
+ raise TypeError('%r used without bound function' %
+ self.__class__.__name__)
+ Filter.__init__(self, **options)
+
+ def filter(self, lexer, stream):
+ # pylint: disable-msg=E1102
+ for ttype, value in self.function(lexer, stream, self.options):
+ yield ttype, value
View
357 pygments/filters/__init__.py
@@ -0,0 +1,357 @@
+# -*- coding: utf-8 -*-
+"""
+ pygments.filters
+ ~~~~~~~~~~~~~~~~
+
+ Module containing filter lookup functions and default
+ filters.
+
+ :copyright: Copyright 2006-2012 by the Pygments team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+
+from pygments.token import String, Comment, Keyword, Name, Error, Whitespace, \
+ string_to_tokentype
+from pygments.filter import Filter
+from pygments.util import get_list_opt, get_int_opt, get_bool_opt, \
+ get_choice_opt, ClassNotFound, OptionError
+from pygments.plugin import find_plugin_filters
+
+
+def find_filter_class(filtername):
+ """
+ Lookup a filter by name. Return None if not found.
+ """
+ if filtername in FILTERS:
+ return FILTERS[filtername]
+ for name, cls in find_plugin_filters():
+ if name == filtername:
+ return cls
+ return None
+
+
+def get_filter_by_name(filtername, **options):
+ """
+ Return an instantiated filter. Options are passed to the filter
+ initializer if wanted. Raise a ClassNotFound if not found.
+ """
+ cls = find_filter_class(filtername)
+ if cls:
+ return cls(**options)
+ else:
+ raise ClassNotFound('filter %r not found' % filtername)
+
+
+def get_all_filters():
+ """
+ Return a generator of all filter names.
+ """
+ for name in FILTERS:
+ yield name
+ for name, _ in find_plugin_filters():
+ yield name
+
+
+def _replace_special(ttype, value, regex, specialttype,
+ replacefunc=lambda x: x):
+ last = 0
+ for match in regex.finditer(value):
+ start, end = match.start(), match.end()
+ if start != last:
+ yield ttype, value[last:start]
+ yield specialttype, replacefunc(value[start:end])
+ last = end
+ if last != len(value):
+ yield ttype, value[last:]
+
+
+class CodeTagFilter(Filter):
+ """
+ Highlight special code tags in comments and docstrings.
+
+ Options accepted:
+
+ `codetags` : list of strings
+ A list of strings that are flagged as code tags. The default is to
+ highlight ``XXX``, ``TODO``, ``BUG`` and ``NOTE``.
+ """
+
+ def __init__(self, **options):
+ Filter.__init__(self, **options)
+ tags = get_list_opt(options, 'codetags',
+ ['XXX', 'TODO', 'BUG', 'NOTE'])
+ self.tag_re = re.compile(r'\b(%s)\b' % '|'.join([
+ re.escape(tag) for tag in tags if tag
+ ]))
+
+ def filter(self, lexer, stream):
+ regex = self.tag_re
+ for ttype, value in stream:
+ if ttype in String.Doc or \
+ ttype in Comment and \
+ ttype not in Comment.Preproc:
+ for sttype, svalue in _replace_special(ttype, value, regex,
+ Comment.Special):
+ yield sttype, svalue
+ else:
+ yield ttype, value
+
+
+class KeywordCaseFilter(Filter):
+ """
+ Convert keywords to lowercase or uppercase or capitalize them, which
+ means first letter uppercase, rest lowercase.
+
+ This can be useful e.g. if you highlight Pascal code and want to adapt the
+ code to your styleguide.
+
+ Options accepted:
+
+ `case` : string
+ The casing to convert keywords to. Must be one of ``'lower'``,
+ ``'upper'`` or ``'capitalize'``. The default is ``'lower'``.
+ """
+
+ def __init__(self, **options):
+ Filter.__init__(self, **options)
+ case = get_choice_opt(options, 'case', ['lower', 'upper', 'capitalize'], 'lower')
+ self.convert = getattr(unicode, case)
+
+ def filter(self, lexer, stream):
+ for ttype, value in stream:
+ if ttype in Keyword:
+ yield ttype, self.convert(value)
+ else:
+ yield ttype, value
+
+
+class NameHighlightFilter(Filter):
+ """
+ Highlight a normal Name token with a different token type.
+
+ Example::
+
+ filter = NameHighlightFilter(
+ names=['foo', 'bar', 'baz'],
+ tokentype=Name.Function,
+ )
+
+ This would highlight the names "foo", "bar" and "baz"
+ as functions. `Name.Function` is the default token type.
+
+ Options accepted:
+
+ `names` : list of strings
+ A list of names that should be given the different token type.
+ There is no default.
+ `tokentype` : TokenType or string
+ A token type or a string containing a token type name that is
+ used for highlighting the strings in `names`. The default is
+ `Name.Function`.
+ """
+
+ def __init__(self, **options):
+ Filter.__init__(self, **options)
+ self.names = set(get_list_opt(options, 'names', []))
+ tokentype = options.get('tokentype')
+ if tokentype:
+ self.tokentype = string_to_tokentype(tokentype)
+ else:
+ self.tokentype = Name.Function
+
+ def filter(self, lexer, stream):
+ for ttype, value in stream:
+ if ttype is Name and value in self.names:
+ yield self.tokentype, value
+ else:
+ yield ttype, value
+
+
+class ErrorToken(Exception):
+ pass
+
+class RaiseOnErrorTokenFilter(Filter):
+ """
+ Raise an exception when the lexer generates an error token.
+
+ Options accepted:
+
+ `excclass` : Exception class
+ The exception class to raise.
+ The default is `pygments.filters.ErrorToken`.
+
+ *New in Pygments 0.8.*
+ """
+
+ def __init__(self, **options):
+ Filter.__init__(self, **options)
+ self.exception = options.get('excclass', ErrorToken)
+ try:
+ # issubclass() will raise TypeError if first argument is not a class
+ if not issubclass(self.exception, Exception):
+ raise TypeError
+ except TypeError:
+ raise OptionError('excclass option is not an exception class')
+
+ def filter(self, lexer, stream):
+ for ttype, value in stream:
+ if ttype is Error:
+ raise self.exception(value)
+ yield ttype, value
+
+
+class VisibleWhitespaceFilter(Filter):
+ """
+ Convert tabs, newlines and/or spaces to visible characters.
+
+ Options accepted:
+
+ `spaces` : string or bool
+ If this is a one-character string, spaces will be replaces by this string.
+ If it is another true value, spaces will be replaced by ``·`` (unicode
+ MIDDLE DOT). If it is a false value, spaces will not be replaced. The
+ default is ``False``.
+ `tabs` : string or bool
+ The same as for `spaces`, but the default replacement character is ``»``
+ (unicode RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK). The default value
+ is ``False``. Note: this will not work if the `tabsize` option for the
+ lexer is nonzero, as tabs will already have been expanded then.
+ `tabsize` : int
+ If tabs are to be replaced by this filter (see the `tabs` option), this
+ is the total number of characters that a tab should be expanded to.
+ The default is ``8``.
+ `newlines` : string or bool
+ The same as for `spaces`, but the default replacement character is ``¶``
+ (unicode PILCROW SIGN). The default value is ``False``.
+ `wstokentype` : bool
+ If true, give whitespace the special `Whitespace` token type. This allows
+ styling the visible whitespace differently (e.g. greyed out), but it can
+ disrupt background colors. The default is ``True``.
+
+ *New in Pygments 0.8.*
+ """
+
+ def __init__(self, **options):
+ Filter.__init__(self, **options)
+ for name, default in {'spaces': u'·', 'tabs': u'»', 'newlines': u''}.items():
+ opt = options.get(name, False)
+ if isinstance(opt, basestring) and len(opt) == 1:
+ setattr(self, name, opt)
+ else:
+ setattr(self, name, (opt and default or ''))
+ tabsize = get_int_opt(options, 'tabsize', 8)
+ if self.tabs:
+ self.tabs += ' '*(tabsize-1)
+ if self.newlines:
+ self.newlines += '\n'
+ self.wstt = get_bool_opt(options, 'wstokentype', True)
+
+ def filter(self, lexer, stream):
+ if self.wstt:
+ spaces = self.spaces or ' '
+ tabs = self.tabs or '\t'
+ newlines = self.newlines or '\n'
+ regex = re.compile(r'\s')
+ def replacefunc(wschar):
+ if wschar == ' ':
+ return spaces
+ elif wschar == '\t':
+ return tabs
+ elif wschar == '\n':
+ return newlines
+ return wschar
+
+ for ttype, value in stream:
+ for sttype, svalue in _replace_special(ttype, value, regex,
+ Whitespace, replacefunc):
+ yield sttype, svalue
+ else:
+ spaces, tabs, newlines = self.spaces, self.tabs, self.newlines
+ # simpler processing
+ for ttype, value in stream:
+ if spaces:
+ value = value.replace(' ', spaces)
+ if tabs:
+ value = value.replace('\t', tabs)
+ if newlines:
+ value = value.replace('\n', newlines)
+ yield ttype, value
+
+
+class GobbleFilter(Filter):
+ """
+ Gobbles source code lines (eats initial characters).
+
+ This filter drops the first ``n`` characters off every line of code. This
+ may be useful when the source code fed to the lexer is indented by a fixed
+ amount of space that isn't desired in the output.
+
+ Options accepted:
+
+ `n` : int
+ The number of characters to gobble.
+
+ *New in Pygments 1.2.*
+ """
+ def __init__(self, **options):
+ Filter.__init__(self, **options)
+ self.n = get_int_opt(options, 'n', 0)
+
+ def gobble(self, value, left):
+ if left < len(value):
+ return value[left:], 0
+ else:
+ return '', left - len(value)
+
+ def filter(self, lexer, stream):
+ n = self.n