mirror of
https://github.com/httpie/cli.git
synced 2025-01-25 23:08:49 +01:00
Added better JSON highlighting
A JSON-specific lexer for Pygments by Norman Richards (@orb) has been added. It attempts to provide more interesting syntax highlighting which correctly distinguishes between attribute names and values. Closes #25.
This commit is contained in:
parent
78e20c6e85
commit
31c28807c9
@ -1,20 +1,19 @@
|
|||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import pygments
|
import pygments
|
||||||
import re
|
|
||||||
from pygments import token
|
from pygments import token
|
||||||
from pygments.util import ClassNotFound
|
from pygments.util import ClassNotFound
|
||||||
from pygments.lexers import get_lexer_for_mimetype
|
from pygments.lexers import get_lexer_for_mimetype
|
||||||
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 include, RegexLexer, bygroups
|
from pygments.lexer import RegexLexer, bygroups
|
||||||
from pygments.styles import get_style_by_name, STYLE_MAP
|
from pygments.styles import get_style_by_name, STYLE_MAP
|
||||||
from . import solarized
|
from . import solarized
|
||||||
|
from .pygson import JSONLexer
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_STYLE = 'solarized'
|
DEFAULT_STYLE = 'solarized'
|
||||||
AVAILABLE_STYLES = [DEFAULT_STYLE] + STYLE_MAP.keys()
|
AVAILABLE_STYLES = [DEFAULT_STYLE] + STYLE_MAP.keys()
|
||||||
TYPE_JS = 'application/javascript'
|
|
||||||
FORMATTER = (Terminal256Formatter
|
FORMATTER = (Terminal256Formatter
|
||||||
if '256color' in os.environ.get('TERM', '')
|
if '256color' in os.environ.get('TERM', '')
|
||||||
else TerminalFormatter)
|
else TerminalFormatter)
|
||||||
@ -32,68 +31,6 @@ class HTTPLexer(RegexLexer):
|
|||||||
(r'(.*?:)(.+)', bygroups(token.Name, token.String))
|
(r'(.*?:)(.+)', bygroups(token.Name, token.String))
|
||||||
]}
|
]}
|
||||||
|
|
||||||
# Stolen from https://github.com/orb/pygments-json
|
|
||||||
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'),
|
|
||||||
],
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class PrettyHttp(object):
|
class PrettyHttp(object):
|
||||||
|
|
||||||
@ -108,20 +45,19 @@ class PrettyHttp(object):
|
|||||||
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:
|
if 'json' in content_type:
|
||||||
content_type = TYPE_JS
|
lexer = JSONLexer()
|
||||||
try:
|
try:
|
||||||
# Indent JSON
|
# Indent 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)
|
||||||
lexer = JSONLexer()
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
else:
|
if not lexer:
|
||||||
try:
|
try:
|
||||||
lexer = get_lexer_for_mimetype(content_type)
|
lexer = get_lexer_for_mimetype(content_type)
|
||||||
except ClassNotFound:
|
except ClassNotFound:
|
||||||
return content
|
return content
|
||||||
content = pygments.highlight(content, lexer, self.formatter)
|
return pygments.highlight(content, lexer, self.formatter)
|
||||||
return content
|
|
||||||
|
77
httpie/pygson.py
Normal file
77
httpie/pygson.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
"""
|
||||||
|
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'),
|
||||||
|
],
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user