Merge pull request #45 from gandaro/pygments-lexers

Use the Pygments HTTP and JSON lexers
This commit is contained in:
Jakub Roztocil 2012-06-13 06:09:11 -07:00
commit 126130455e
7 changed files with 38 additions and 125 deletions

View File

@ -1,8 +1,11 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys import sys
import json import json
import requests import requests
from requests.compat import str from requests.compat import str
from . import httpmessage from . import httpmessage
from . import cliparse from . import cliparse
from . import cli from . import cli

View File

@ -3,15 +3,19 @@ CLI argument parsing logic.
""" """
import os import os
import json
import re import re
import json
import argparse
from collections import namedtuple from collections import namedtuple
try: try:
from collections import OrderedDict from collections import OrderedDict
except ImportError: except ImportError:
OrderedDict = dict OrderedDict = dict
import argparse
from requests.structures import CaseInsensitiveDict from requests.structures import CaseInsensitiveDict
from . import __version__ from . import __version__

View File

@ -38,7 +38,7 @@ def from_response(response):
return HTTPMessage( return HTTPMessage(
line='HTTP/{version} {status} {reason}'.format( line='HTTP/{version} {status} {reason}'.format(
version='.'.join(str(original.version)), version='.'.join(str(original.version)),
status=original.status, reason=original.reason,), status=original.status, reason=original.reason),
headers=str(original.msg), headers=str(original.msg),
body=response.content.decode(encoding) if response.content else '', body=response.content.decode(encoding) if response.content else '',
content_type=response_headers.get('Content-Type')) content_type=response_headers.get('Content-Type'))
@ -47,20 +47,21 @@ def from_response(response):
def format(message, prettifier=None, def format(message, prettifier=None,
with_headers=True, with_body=True): with_headers=True, with_body=True):
"""Return a `unicode` representation of `message`. """ """Return a `unicode` representation of `message`. """
pretty = prettifier is not None
bits = [] bits = []
if with_headers: if with_headers:
if prettifier: bits.append(message.line)
bits.append(prettifier.headers(message.line)) bits.append(message.headers)
bits.append(prettifier.headers(message.headers)) if pretty:
else: bits = [prettifier.headers('\n'.join(bits))]
bits.append(message.line)
bits.append(message.headers)
if with_body and message.body: if with_body and message.body:
bits.append('\n') bits.append('\n')
if with_body and message.body: if with_body and message.body:
if prettifier and message.content_type: if pretty and message.content_type:
bits.append(prettifier.body(message.body, message.content_type)) bits.append(prettifier.body(message.body, message.content_type))
else: else:
bits.append(message.body) bits.append(message.body)
bits.append('\n')
return '\n'.join(bit.strip() for bit in bits) return '\n'.join(bit.strip() for bit in bits)

View File

@ -1,14 +1,14 @@
import os import os
import json import json
import pygments import pygments
from pygments import token
from pygments.util import ClassNotFound from pygments.util import ClassNotFound
from pygments.lexers import get_lexer_for_mimetype from pygments.styles import get_style_by_name, STYLE_MAP
from pygments.lexers import get_lexer_for_mimetype, HttpLexer
from pygments.formatters.terminal256 import Terminal256Formatter from pygments.formatters.terminal256 import Terminal256Formatter
from pygments.formatters.terminal import TerminalFormatter from pygments.formatters.terminal import TerminalFormatter
from pygments.lexer import RegexLexer, bygroups
from pygments.styles import get_style_by_name, STYLE_MAP
from .pygson import JSONLexer
from . import solarized from . import solarized
@ -19,24 +19,6 @@ FORMATTER = (Terminal256Formatter
else TerminalFormatter) else TerminalFormatter)
class HTTPLexer(RegexLexer):
name = 'HTTP'
aliases = ['http']
filenames = ['*.http']
tokens = {
'root': [
(r'\s+', token.Text),
# Request-Line
(r'([A-Z]+\s+)(/.*?)(\s+HTTP/[\d.]+)', bygroups(
token.Keyword, token.String, token.Keyword)),
# Status-Line
(r'(HTTP/[\d.]+\s+)(\d+)(\s+.+)', bygroups(
token.Keyword, token.Number, token.String)),
# Header
(r'(.*?:)(.+)', bygroups(token.Name, token.Keyword))
]}
class PrettyHttp(object): class PrettyHttp(object):
def __init__(self, style_name): def __init__(self, style_name):
@ -47,22 +29,21 @@ class PrettyHttp(object):
self.formatter = FORMATTER(style=style) self.formatter = FORMATTER(style=style)
def headers(self, content): def headers(self, content):
return pygments.highlight(content, HTTPLexer(), self.formatter) return pygments.highlight(content, HttpLexer(), self.formatter)
def body(self, content, content_type): def body(self, content, content_type):
lexer = None
content_type = content_type.split(';')[0] content_type = content_type.split(';')[0]
if 'json' in content_type: try:
lexer = JSONLexer() lexer = get_lexer_for_mimetype(content_type)
except ClassNotFound:
return content
if content_type == 'application/json':
try: try:
# Indent the JSON data. # Indent and sort the JSON data.
content = json.dumps(json.loads(content), content = json.dumps(json.loads(content),
sort_keys=True, indent=4) sort_keys=True, indent=4)
except Exception: except:
pass pass
if not lexer:
try:
lexer = get_lexer_for_mimetype(content_type)
except ClassNotFound:
return content
return pygments.highlight(content, lexer, self.formatter) return pygments.highlight(content, lexer, self.formatter)

View File

@ -1,77 +0,0 @@
"""
JSON lexer by Norman Richards
It's already been merged into Pygments but not released yet,
so we are temporarily bundling it with HTTPie.
It can be removed once Pygments > 1.4 has been released.
See <https://github.com/jkbr/httpie/pull/25> for more details.
"""
import re
from pygments import token
from pygments.lexer import RegexLexer, include
class JSONLexer(RegexLexer):
name = 'JSON Lexer'
aliases = ['json']
filenames = ['*.json']
mimetypes = []
flags = re.DOTALL
tokens = {
'whitespace': [
(r'\s+', token.Text),
],
# represents a simple terminal value
'simplevalue':[
(r'(true|false|null)\b', token.Keyword.Constant),
(r'-?[0-9]+', token.Number.Integer),
(r'"(\\\\|\\"|[^"])*"', token.String.Double),
],
# the right hand side of an object, after the attribute name
'objectattribute': [
include('value'),
(r':', token.Punctuation),
# comma terminates the attribute but expects more
(r',', token.Punctuation, '#pop'),
# a closing bracket terminates the entire object, so pop twice
(r'}', token.Punctuation, ('#pop', '#pop')),
],
# a json object - { attr, attr, ... }
'objectvalue': [
include('whitespace'),
(r'"(\\\\|\\"|[^"])*"', token.Name.Tag, 'objectattribute'),
(r'}', token.Punctuation, '#pop'),
],
# json array - [ value, value, ... }
'arrayvalue': [
include('whitespace'),
include('value'),
(r',', token.Punctuation),
(r']', token.Punctuation, '#pop'),
],
# a json value - either a simple value or a complex value (object or array)
'value': [
include('whitespace'),
include('simplevalue'),
(r'{', token.Punctuation, 'objectvalue'),
(r'\[', token.Punctuation, 'arrayvalue'),
],
# the root of a json document would be a value
'root': [
include('value'),
],
}

View File

@ -27,7 +27,8 @@ THE SOFTWARE.
""" """
from pygments.style import Style from pygments.style import Style
from pygments.token import Token, Comment, Name, Keyword, Generic, Number, Operator, String from pygments.token import (Token, Comment, Name, Keyword, Generic, Number,
Operator, String)
BASE03 = '#002B36' BASE03 = '#002B36'

View File

@ -9,7 +9,7 @@ if sys.argv[-1] == 'test':
sys.exit() sys.exit()
requirements = ['requests>=0.10.1', 'Pygments>=1.4'] requirements = ['requests>=0.10.1', 'Pygments>=1.5']
if sys.version_info[:2] in ((2, 6), (3, 1)): if sys.version_info[:2] in ((2, 6), (3, 1)):
# argparse has been added in Python 3.2 / 2.7 # argparse has been added in Python 3.2 / 2.7
requirements.append('argparse>=1.2.1') requirements.append('argparse>=1.2.1')