Add support to set a lexer with a given filename. Closes issue #63.

This allows third-party API utils to set the lexer automatically based on the open filename.
This commit is contained in:
Martin Mahner 2014-06-09 20:18:08 +02:00
parent fbe6aeedb7
commit 3bc2eb0c84
3 changed files with 102 additions and 6 deletions

View file

@ -62,6 +62,32 @@ values. Default: ``2592000``. In the default configuration valid values are:
* 604800
* 2592000
``filename`` (optional)
~~~~~~~~~~~~~~~~~~~~~~~
Can also be set via GET. A filename which we use to determine a lexer, if
``lexer`` is not set. In case we can't determine a file, the lexer will fallback
to ``plain`` code (no highlighting). A given ``lexer`` will overwrite any
filename! Example::
{
"url": "https://dpaste.de/xsWd",
"lexer": "",
"filename": "python",
"conent": "The text body of the snippet."
}
This will create a ``python`` highlighted snippet. However in this example::
{
"url": "https://dpaste.de/xsWd",
"lexer": "php",
"filename": "python",
"conent": "The text body of the snippet."
}
Since the lexer is set too, we will create a ``php`` highlighted snippet.
.. hint:: You need to adjust the setting ``DPASTE_BASE_URL`` which is used
to generate the full qualified URL in the API response. See :doc:`settings`.

View file

@ -3,9 +3,9 @@
from django.core.urlresolvers import reverse
from django.test.client import Client
from django.test import TestCase
from django.test.utils import override_settings
from ..models import Snippet
from ..highlight import PLAIN_CODE
class SnippetAPITestCase(TestCase):
@ -188,3 +188,53 @@ class SnippetAPITestCase(TestCase):
self.assertEqual(response.status_code, 200)
self.assertEqual(Snippet.objects.count(), 1)
self.assertTrue(Snippet.objects.all()[0].expires)
def test_filename_not_given(self):
"""
No lexer and no filename given returns a BadRequest.
"""
response = self.client.post(self.api_url, {
'content': u"Hello Wörld.\n\tGood Bye",
'lexer': '',
'filename': ''
})
self.assertEqual(response.status_code, 400)
def test_filename_given(self):
"""
No lexer and a Python filename will set a 'python' lexer.
"""
response = self.client.post(self.api_url, {
'content': u"Hello Wörld.\n\tGood Bye",
'lexer': '',
'filename': 'helloworld.py'
})
self.assertEqual(response.status_code, 200)
self.assertEqual(Snippet.objects.count(), 1)
self.assertEqual(Snippet.objects.all()[0].lexer, 'python')
def test_awkward_filename_given(self):
"""
A unknown filename will create a 'plain' code snippet.
"""
response = self.client.post(self.api_url, {
'content': u"Hello Wörld.\n\tGood Bye",
'lexer': '',
'filename': 'helloworld.helloworld'
})
self.assertEqual(response.status_code, 200)
self.assertEqual(Snippet.objects.count(), 1)
self.assertEqual(Snippet.objects.all()[0].lexer, PLAIN_CODE)
def test_filename_and_lexer_given(self):
"""
A given lexer will overwrite whats the filename guessing.
"""
response = self.client.post(self.api_url, {
'content': u"Hello Wörld.\n\tGood Bye",
'lexer': 'php',
'filename': 'helloworld.py'
})
self.assertEqual(response.status_code, 200)
self.assertEqual(Snippet.objects.count(), 1)
self.assertEqual(Snippet.objects.all()[0].lexer, 'php')

View file

@ -16,10 +16,13 @@ from django.views.defaults import (page_not_found as django_page_not_found,
server_error as django_server_error)
from django.views.decorators.csrf import csrf_exempt
from pygments.lexers import get_lexer_for_filename
from pygments.util import ClassNotFound
from dpaste.forms import SnippetForm, get_expire_values, EXPIRE_CHOICES
from dpaste.models import Snippet, ONETIME_LIMIT
from dpaste.highlight import LEXER_WORDWRAP, LEXER_LIST
from dpaste.highlight import LEXER_DEFAULT, LEXER_KEYS
from dpaste.highlight import (LEXER_DEFAULT, LEXER_KEYS, LEXER_WORDWRAP,
LEXER_LIST, PLAIN_CODE)
# -----------------------------------------------------------------------------
# Snippet Handling
@ -285,15 +288,32 @@ FORMAT_MAPPING = {
def snippet_api(request):
content = request.POST.get('content', '').strip()
lexer = request.REQUEST.get('lexer', LEXER_DEFAULT).strip()
filename = request.REQUEST.get('filename', '').strip()
expires = request.REQUEST.get('expires', '').strip()
format = request.REQUEST.get('format', 'default').strip()
if not content:
return HttpResponseBadRequest('No content given')
if not lexer in LEXER_KEYS:
return HttpResponseBadRequest('Invalid lexer given. Valid lexers are: %s' %
', '.join(LEXER_KEYS))
# We need at least a lexer or a filename
if not lexer and not filename:
return HttpResponseBadRequest('No lexer or filename given. Unable to '
'determine a highlight. Valid lexers are: %s' % ', '.join(LEXER_KEYS))
# A lexer is given, check if its valid at all
if lexer and lexer not in LEXER_KEYS:
return HttpResponseBadRequest('Invalid lexer "%s" given. Valid lexers are: %s' % (
lexer, ', '.join(LEXER_KEYS)))
# No lexer is given, but we have a filename, try to get the lexer out of it.
# In case Pygments cannot determine the lexer of the filename, we fallback
# to 'plain' code.
if not lexer and filename:
try:
lexer_cls = get_lexer_for_filename(filename)
lexer = lexer_cls.aliases[0]
except (ClassNotFound, IndexError):
lexer = PLAIN_CODE
if expires:
expire_options = [str(i) for i in dict(EXPIRE_CHOICES).keys()]