mirror of
https://github.com/DarrenOfficial/dpaste.git
synced 2024-11-15 08:02:54 +11:00
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:
parent
fbe6aeedb7
commit
3bc2eb0c84
3 changed files with 102 additions and 6 deletions
26
docs/api.rst
26
docs/api.rst
|
@ -62,6 +62,32 @@ values. Default: ``2592000``. In the default configuration valid values are:
|
||||||
* 604800
|
* 604800
|
||||||
* 2592000
|
* 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
|
.. 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`.
|
to generate the full qualified URL in the API response. See :doc:`settings`.
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.test.client import Client
|
from django.test.client import Client
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.utils import override_settings
|
|
||||||
|
|
||||||
from ..models import Snippet
|
from ..models import Snippet
|
||||||
|
from ..highlight import PLAIN_CODE
|
||||||
|
|
||||||
class SnippetAPITestCase(TestCase):
|
class SnippetAPITestCase(TestCase):
|
||||||
|
|
||||||
|
@ -188,3 +188,53 @@ class SnippetAPITestCase(TestCase):
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(Snippet.objects.count(), 1)
|
self.assertEqual(Snippet.objects.count(), 1)
|
||||||
self.assertTrue(Snippet.objects.all()[0].expires)
|
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')
|
||||||
|
|
|
@ -16,10 +16,13 @@ from django.views.defaults import (page_not_found as django_page_not_found,
|
||||||
server_error as django_server_error)
|
server_error as django_server_error)
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
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.forms import SnippetForm, get_expire_values, EXPIRE_CHOICES
|
||||||
from dpaste.models import Snippet, ONETIME_LIMIT
|
from dpaste.models import Snippet, ONETIME_LIMIT
|
||||||
from dpaste.highlight import LEXER_WORDWRAP, LEXER_LIST
|
from dpaste.highlight import (LEXER_DEFAULT, LEXER_KEYS, LEXER_WORDWRAP,
|
||||||
from dpaste.highlight import LEXER_DEFAULT, LEXER_KEYS
|
LEXER_LIST, PLAIN_CODE)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Snippet Handling
|
# Snippet Handling
|
||||||
|
@ -285,15 +288,32 @@ FORMAT_MAPPING = {
|
||||||
def snippet_api(request):
|
def snippet_api(request):
|
||||||
content = request.POST.get('content', '').strip()
|
content = request.POST.get('content', '').strip()
|
||||||
lexer = request.REQUEST.get('lexer', LEXER_DEFAULT).strip()
|
lexer = request.REQUEST.get('lexer', LEXER_DEFAULT).strip()
|
||||||
|
filename = request.REQUEST.get('filename', '').strip()
|
||||||
expires = request.REQUEST.get('expires', '').strip()
|
expires = request.REQUEST.get('expires', '').strip()
|
||||||
format = request.REQUEST.get('format', 'default').strip()
|
format = request.REQUEST.get('format', 'default').strip()
|
||||||
|
|
||||||
if not content:
|
if not content:
|
||||||
return HttpResponseBadRequest('No content given')
|
return HttpResponseBadRequest('No content given')
|
||||||
|
|
||||||
if not lexer in LEXER_KEYS:
|
# We need at least a lexer or a filename
|
||||||
return HttpResponseBadRequest('Invalid lexer given. Valid lexers are: %s' %
|
if not lexer and not filename:
|
||||||
', '.join(LEXER_KEYS))
|
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:
|
if expires:
|
||||||
expire_options = [str(i) for i in dict(EXPIRE_CHOICES).keys()]
|
expire_options = [str(i) for i in dict(EXPIRE_CHOICES).keys()]
|
||||||
|
|
Loading…
Reference in a new issue