Huge cleanup. Simplified lexer massively. Cleaned up view code. Cleaned up syntax highlighting.

This commit is contained in:
Martin Mahner 2013-08-15 20:42:02 +02:00
parent 03dc21c550
commit 2c072e2789
10 changed files with 206 additions and 562 deletions

View file

@ -1,24 +1,23 @@
import datetime
from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from dpaste.models import Snippet
from dpaste.highlight import LEXER_LIST, LEXER_DEFAULT
import datetime
#===============================================================================
# Snippet Form and Handling
#===============================================================================
EXPIRE_CHOICES = (
(3600, _(u'In one hour')),
(3600 * 24 * 7, _(u'In one week')),
(3600 * 24 * 30, _(u'In one month')),
)
EXPIRE_DEFAULT = 3600 * 24 * 30
EXPIRE_DEFAULT = EXPIRE_CHOICES[2][0]
MAX_CONTENT_LENGTH = getattr(settings, 'DPASTE_MAX_CONTENT_LENGTH', 250*1024*1024)
MAX_SNIPPETS_PER_USER = getattr(settings, 'DPASTE_MAX_SNIPPETS_PER_USER', 15)
\
class SnippetForm(forms.ModelForm):
content = forms.CharField(
label=_('Content'),
@ -29,7 +28,7 @@ class SnippetForm(forms.ModelForm):
lexer = forms.ChoiceField(
label=_(u'Lexer'),
initial=LEXER_DEFAULT,
widget=forms.TextInput,
choices=LEXER_LIST,
)
expire_options = forms.ChoiceField(
@ -55,35 +54,23 @@ class SnippetForm(forms.ModelForm):
def __init__(self, request, *args, **kwargs):
super(SnippetForm, self).__init__(*args, **kwargs)
self.request = request
self.fields['lexer'].choices = LEXER_LIST
self.fields['lexer'].widget.attrs = {
'autocomplete': 'off',
'data-provide': 'typeahead',
'data-source': '["%s"]' % '","'.join(dict(LEXER_LIST).keys())
}
# Set the recently used lexer if we have any
session_lexer = self.request.session.get('lexer')
if session_lexer and session_lexer in dict(LEXER_LIST).keys():
self.fields['lexer'].initial = session_lexer
def clean_lexer(self):
lexer = self.cleaned_data.get('lexer')
if not lexer:
return LEXER_DEFAULT
lexer = dict(LEXER_LIST).get(lexer, LEXER_DEFAULT)
return lexer
def clean_content(self):
return self.cleaned_data.get('content', '').strip()
def clean(self):
# The `title` field is a hidden honeypot field. If its filled,
# this is likely spam.
if self.cleaned_data.get('title'):
raise forms.ValidationError('This snippet was identified as Spam.')
return self.cleaned_data
def save(self, parent=None, *args, **kwargs):
# Set parent snippet
if parent:
self.instance.parent = parent
@ -97,7 +84,7 @@ class SnippetForm(forms.ModelForm):
# Add the snippet to the user session list
if self.request.session.get('snippet_list', False):
if len(self.request.session['snippet_list']) >= getattr(settings, 'MAX_SNIPPETS_PER_USER', 10):
if len(self.request.session['snippet_list']) >= MAX_SNIPPETS_PER_USER:
self.request.session['snippet_list'].pop(0)
self.request.session['snippet_list'] += [self.instance.pk]
else:
@ -106,4 +93,4 @@ class SnippetForm(forms.ModelForm):
# Save the lexer in the session so we can use it later again
self.request.session['lexer'] = self.cleaned_data['lexer']
return self.request, self.instance
return self.instance

View file

@ -1,23 +1,102 @@
from pygments import highlight
from pygments.lexers import *
from pygments.lexers import get_all_lexers
from pygments.formatters import HtmlFormatter
from django.conf import settings
from django.utils.html import escape
"""
# Get a list of all lexer, and then remove all lexer which have '-' or '+'
# or 'with' in the name. Those are too specific and never used. This produces a
# tuple list of [(lexer, Lexer Display Name) ...] lexers.
from pygments.lexers import get_all_lexers
ALL_LEXER = set([(i[1][0], i[0]) for i in get_all_lexers()])
LEXER_LIST = [l for l in ALL_LEXER if not (
'-' in l[0]
or '+' in l[0]
or '+' in l[1]
or 'with' in l[1].lower()
or ' ' in l[1]
or l[0] in IGNORE_LEXER
)]
LEXER_LIST = sorted(LEXER_LIST)
"""
import logging
logger = logging.getLogger(__name__)
# The list of lexers. Its not worth to autogenerate this. See above how to
# retrieve this.
LEXER_LIST = getattr(settings, 'DPASTE_LEXER_LIST', (
('text', 'Text'),
('text', '----------'),
('apacheconf', 'ApacheConf'),
('applescript', 'AppleScript'),
('as', 'ActionScript'),
('bash', 'Bash'),
('bbcode', 'BBCode'),
('c', 'C'),
('clojure', 'Clojure'),
('cobol', 'COBOL'),
('css', 'CSS'),
('cuda', 'CUDA'),
('dart', 'Dart'),
('delphi', 'Delphi'),
('diff', 'Diff'),
('django', 'Django'),
('erlang', 'Erlang'),
('fortran', 'Fortran'),
('go', 'Go'),
('groovy', 'Groovy'),
('haml', 'Haml'),
('haskell', 'Haskell'),
('html', 'HTML'),
('http', 'HTTP'),
('ini', 'INI'),
('java', 'Java'),
('js', 'JavaScript'),
('json', 'JSON'),
('lua', 'Lua'),
('make', 'Makefile'),
('mako', 'Mako'),
('mason', 'Mason'),
('matlab', 'Matlab'),
('modula2', 'Modula'),
('monkey', 'Monkey'),
('mysql', 'MySQL'),
('numpy', 'NumPy'),
('ocaml', 'OCaml'),
('perl', 'Perl'),
('php', 'PHP'),
('postscript', 'PostScript'),
('powershell', 'PowerShell'),
('prolog', 'Prolog'),
('properties', 'Properties'),
('puppet', 'Puppet'),
('python', 'Python'),
('rb', 'Ruby'),
('rst', 'reStructuredText'),
('rust', 'Rust'),
('sass', 'Sass'),
('scala', 'Scala'),
('scheme', 'Scheme'),
('scilab', 'Scilab'),
('scss', 'SCSS'),
('smalltalk', 'Smalltalk'),
('smarty', 'Smarty'),
('sql', 'SQL'),
('tcl', 'Tcl'),
('tcsh', 'Tcsh'),
('tex', 'TeX'),
('vb.net', 'VB.net'),
('vim', 'VimL'),
('xml', 'XML'),
('xquery', 'XQuery'),
('xslt', 'XSLT'),
('yaml', 'YAML'),
))
# Python 3: python3
LEXER_LIST = sorted([(i[0], i[0]) for i in get_all_lexers() if not (
'+' in i[0] or
'with' in i[0].lower() or
i[0].islower()
)])
LEXER_LIST_NAME = dict([(i[0], i[1][0]) for i in get_all_lexers()])
# The default lexer is python
LEXER_DEFAULT = getattr(settings, 'DPASTE_LEXER_DEFAULT', 'python')
# Lexers which have wordwrap enabled by default
LEXER_WORDWRAP = getattr(settings, 'DPASTE_LEXER_WORDWRAP', ('text', 'rst'))
LEXER_DEFAULT = 'Python'
LEXER_WORDWRAP = ('text', 'rst')
class NakedHtmlFormatter(HtmlFormatter):
def wrap(self, source, outfile):
@ -28,25 +107,6 @@ class NakedHtmlFormatter(HtmlFormatter):
yield i, t
def pygmentize(code_string, lexer_name=LEXER_DEFAULT):
lexer_name = LEXER_LIST_NAME.get(lexer_name, None)
try:
if lexer_name:
lexer = get_lexer_by_name(lexer_name)
else:
raise Exception
except:
try:
lexer = guess_lexer(code_string)
except:
lexer = PythonLexer()
try:
lexer = lexer_name and get_lexer_by_name(lexer_name) \
or PythonLexer()
return highlight(code_string, lexer, NakedHtmlFormatter())
except:
return escape(code_string)
def guess_code_lexer(code_string, default_lexer='unknown'):
try:
return guess_lexer(code_string).name
except ValueError:
return default_lexer

View file

@ -1,404 +0,0 @@
body{
margin: 0;
padding: 0;
font-family: Helvetica, Arial, sans-serif;
font-size: 13px;
}
a:link,
a:visited{
color: #3D813A;
text-decoration: none;
}
a:hover{
color: #52AA4D;
text-decoration: underline;
}
p.hint{
color: #333;
margin-top: 30px;
}
p.hint em{
color: black;
background-color: #c9f8b4;
display: inline-block;
padding: 2px 3px;
font-style: normal;
}
hr.clear{
clear: both;
border: none;
margin: 0;
padding: 0;
height: 0;
overflow: hidden;
font-size: 0;
line-height: 0;
visibility: hidden;
}
div.success{
background-color: green;
color: White;
margin: 10px 0;
padding: 10px 20px;
}
div.success a{
color: White;
text-decoration: underline;
}
div.hint{
padding: 5px 20px;
background-color: #F7F1C9;
margin: 20px 0;
}
/* *******************************************
* Header
******************************************* */
#header{
background-color: #D6F1B7;
border-bottom: 1px solid #C6EB9A;
padding: 10px 20px;
font-size: 14px;
}
#header span.new_snippet{
float: right;
}
#header h1{
margin: 0;
color: #555555;
font-size: 14px;
}
#header h1 span.date{
color: gray;
color: #666;
padding-left: 15px;
}
#header a:link,
#header a:visited{
text-decoration: none;
color: #333;
font-weight: Bold;
}
#header a:hover{
text-decoration: underline;
}
/* *******************************************
* Content
******************************************* */
#content{
padding: 0 20px;
margin: 0;
width: 70%;
float: left;
}
#content h2{
font-size: 1.3em;
line-height: 1.6em;
}
#content h2.divider{
font-size: 1em;
padding: 5px 20px;
background-color: #f8f8f8;
margin: 40px 0 20px 0;
}
#content h2 span{
font-weight: normal;
}
div.accordion h2{
cursor: pointer;
color: #3D813A;
}
div.accordion h2:hover{
text-decoration: underline;
}
/* *******************************************
* Snippet table
******************************************* */
div.snippet{
overflow: auto;
}
div.snippet-options{
float: right;
font-size: 0.9em;
margin-top: 5px;
}
div.snippet table{
margin: 0;
padding: 0;
border-collapse: collapse;
}
div.snippet table td{
margin: 0;
padding: 0 4px;
vertical-align: top;
}
div.snippet table th{
border-right: 1px solid #ccc;
vertical-align: top;
}
div.snippet table th a{
display: block;
text-decoration: none;
color: #888;
text-align: right;
padding: 0 4px 0 18px;
}
/* *******************************************
* Form
******************************************* */
form.snippetform ol{
margin: 0;
padding: 0;
list-style: none;
}
form.snippetform ol li{
margin: 0;
padding: 5px 10px;
border-bottom: 1px solid #EEE;
clear: left;
}
form.snippetform label{
width: 125px;
display: inline-block;
}
form.snippetform #id_content{
width: 80%;
height: 320px;
font-family: monospace;
font-size: 0.9em;
}
form.snippetform #id_author,
form.snippetform #id_title{
width: 60%;
opacity: 0.7;
}
form.snippetform li.submit input{
margin-left: 125px;
}
form.snippetform ul.errorlist,
form.snippetform ul.errorlist li{
margin: 0;
padding: 0;
list-style: none;
color: #c00;
font-weight: bold;
border: none;
}
form.snippetform ul.errorlist li{
padding: 10px 0 5px 0;
}
/* *******************************************
* History + Tree
******************************************* */
#sidebar{
padding: 0 20px 0 10px;
margin: 20px 0 0 0;
float: right;
width: 20%;
overflow: auto;
border-left: 1px solid #DDD;
}
#sidebar h2{
font-size: 1em;
border-bottom: 1px solid #DDD;
color: #888;
margin-top: 0;
text-transform: uppercase;
width: auto !important;
}
div.tree{
margin: 0 0 15px 0;
line-height: 1.8em;
}
div.tree ul,
div.tree ul li{
margin: 0;
padding: 0;
list-style: none;
}
div.tree ul li{
clear: both;
}
div.tree ul li div{
border-bottom: 1px solid #EEE;
}
div.tree span.diff{
float: right;
}
div.tree strong{
color: #111;
font-weight: normal;
}
div.tree ul li li{
padding-left: 0;
margin-left: 15px;
color: #ccc;
list-style: circle;
}
div.tree div.submit{
margin: 8px 0 0 0;
text-align: right;
}
div.tree div.submit input{
font-size: 0.8em;
}
/* *******************************************
* Footer
******************************************* */
#footer{
position: fixed;
right: 1em;
bottom: 1em;
}
#footer form.setlang{
display: inline;
padding-right: 15px;
}
#footer form.setlang input,
#footer form.setlang select{
font-size: 0.8em;
}
#footer a:link,
#footer a:visited{
background-color: #D6F1B7;
color: #555;
text-decoration: none;
padding: 3px 6px;
}
#footer a:hover,
#footer a:active{
background-color: #D6F1B7;
color: #000;
text-decoration: none;
}
/* *******************************************
* Pygments
******************************************* */
pre.code {
font-family: "Bitstream Vera Sans Mono", Monaco, Consolas, monospace;
font-size: 12px;
line-height: 17px;
margin: 0;
padding: 0;
}
pre.code div.line:hover{
background-color: #FFFFE6;
}
pre.code div.line.marked,
pre.code div.line.marked *{
background-color: #BAE688 !important;
}
.code .c { color: #999988; font-style: italic } /* Comment */
/* .code .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.code .k { font-weight: bold } /* Keyword */
.code .o { font-weight: bold } /* Operator */
.code .cm { color: #999988; font-style: italic } /* Comment.Multiline */
.code .cp { color: #999999; font-weight: bold } /* Comment..codeproc */
.code .c1 { color: #999988; font-style: italic } /* Comment.Single */
.code .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.code .ge { font-style: italic } /* Generic.Emph */
.code .gr { color: #aa0000 } /* Generic.Error */
.code .gh { color: #999999 } /* Generic.Heading */
.code .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.code .go { color: #888888 } /* Generic.Output */
.code .gp { color: #555555 } /* Generic.Prompt */
.code .gs { font-weight: bold } /* Generic.Strong */
.code .gu { color: #aaaaaa } /* Generic.Subheading */
.code .gt { color: #aa0000 } /* Generic.Traceback */
.code .kc { font-weight: bold } /* Keyword.Constant */
.code .kd { font-weight: bold } /* Keyword.Declaration */
.code .kp { font-weight: bold } /* Keyword.Pseudo */
.code .kr { font-weight: bold } /* Keyword.Reserved */
.code .kt { color: #445588; font-weight: bold } /* Keyword.Type */
.code .m { color: #009999 } /* Literal.Number */
.code .s { color: #bb8844 } /* Literal.String */
.code .na { color: #008080 } /* Name.Attribute */
.code .nb { color: #999999 } /* Name.Builtin */
.code .nc { color: #445588; font-weight: bold } /* Name.Class */
.code .no { color: #ff99ff } /* Name.Constant */
.code .ni { color: #800080 } /* Name.Entity */
.code .ne { color: #990000; font-weight: bold } /* Name.Exception */
.code .nf { color: #990000; font-weight: bold } /* Name.Function */
.code .nn { color: #555555 } /* Name.Namespace */
.code .nt { color: #000080 } /* Name.Tag */
.code .nv { color: purple } /* Name.Variable */
.code .ow { font-weight: bold } /* Operator.Word */
.code .mf { color: #009999 } /* Literal.Number.Float */
.code .mh { color: #009999 } /* Literal.Number.Hex */
.code .mi { color: #009999 } /* Literal.Number.Integer */
.code .mo { color: #009999 } /* Literal.Number.Oct */
.code .sb { color: #bb8844 } /* Literal.String.Backtick */
.code .sc { color: #bb8844 } /* Literal.String.Char */
.code .sd { color: #bb8844 } /* Literal.String.Doc */
.code .s2 { color: #bb8844 } /* Literal.String.Double */
.code .se { color: #bb8844 } /* Literal.String.Escape */
.code .sh { color: #bb8844 } /* Literal.String.Heredoc */
.code .si { color: #bb8844 } /* Literal.String.Interpol */
.code .sx { color: #bb8844 } /* Literal.String.Other */
.code .sr { color: #808000 } /* Literal.String.Regex */
.code .s1 { color: #bb8844 } /* Literal.String.Single */
.code .ss { color: #bb8844 } /* Literal.String.Symbol */
.code .bp { color: #999999 } /* Name.Builtin.Pseudo */
.code .vc { color: #ff99ff } /* Name.Variable.Class */
.code .vg { color: #ff99ff } /* Name.Variable.Global */
.code .vi { color: #ff99ff } /* Name.Variable.Instance */
.code .il { color: #009999 } /* Literal.Number.Integer.Long */

7
dpaste/static/dpaste/typeahead.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -28,33 +28,6 @@
{% block script_footer %}
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
<script src="{% static "dpaste/bootstrap/js/bootstrap.min.js" %}"></script>
<script>
jQuery(function($) {
var lexerReq;
$('#guess_lexer_btn').click(function() {
// Cancel previous request if it is still pending
if (lexerReq) {
lexerReq.abort();
}
lexerReq = $.getJSON('{% url "snippet_guess_lexer" %}', {
codestring: $('#id_content').val()
}).done(function(data) {
if (data.lexer === 'unknown') {
$('#guess_lexer_btn').css('color', 'red');
} else {
$('#id_lexer').val(data.lexer);
$('#guess_lexer_btn').css('color', 'inherit');
}
}).complete(function() {
lexerReq = null;
});
});
$('.autofocus input:text, .autofocus textarea').first().focus();
});
</script>
{% endblock %}
</body>

View file

@ -81,15 +81,15 @@
{{ block.super }}
<script>
jQuery(function($) {
var diffReq;
$('.snippet-reply-hidden').click(function(e) {
$(this).removeClass('snippet-reply-hidden');
});
/**
* Diff Ajax Call
*/
/* ------------------------------------------------------------------------
Diff Ajax Call
------------------------------------------------------------------------ */
var diffReq;
$('.snippet-diff-trigger').click(function(e) {
e.preventDefault();
$('#snippet-diff').slideDown('fast');
@ -134,10 +134,9 @@ jQuery(function($) {
}
}
/**
* Line Highlighting
*/
/* ------------------------------------------------------------------------
Line Highlighting
------------------------------------------------------------------------ */
if (curLine.substring(0, 2) === '#L') {
hashlist = curLine.substring(2).split(',');
if (hashlist.length > 0 && hashlist[0] !== '') {

View file

@ -19,7 +19,6 @@
{% if snippet_form.lexer.errors %}control-group error{% endif %}">
<div class="input-append">
{{ snippet_form.lexer }}
<button class="btn" id="guess_lexer_btn" type="button">{% trans "Guess lexer" %}</button>
</div>
{% for error in snippet_form.lexer.errors %}
<span class="help-inline">{{ error }}</span>

View file

@ -1,4 +1,5 @@
{% extends "dpaste/base.html" %}
{% load i18n %}
{% load dpaste_tags %}

View file

@ -1,10 +1,7 @@
from django.conf.urls.defaults import url, patterns
from . import views
urlpatterns = patterns('dpaste.views',
url(r'^$', 'snippet_new', name='snippet_new'),
url(r'^guess/$', 'guess_lexer', name='snippet_guess_lexer'),
url(r'^diff/$', 'snippet_diff', name='snippet_diff'),
url(r'^history/$', 'snippet_history', name='snippet_history'),
url(r'^(?P<snippet_id>[a-zA-Z0-9]+)/$', 'snippet_details', name='snippet_details'),

View file

@ -2,12 +2,13 @@ import datetime
import difflib
import requests
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404
from django.shortcuts import (render_to_response, get_object_or_404,
get_list_or_404)
from django.template.context import RequestContext
from django.http import (Http404, HttpResponseRedirect, HttpResponseBadRequest,
HttpResponse, HttpResponseForbidden)
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from django.utils import simplejson
@ -17,30 +18,20 @@ from django.views.defaults import (page_not_found as django_page_not_found,
from dpaste.forms import SnippetForm
from dpaste.models import Snippet
from dpaste.highlight import guess_code_lexer, \
LEXER_WORDWRAP, LEXER_LIST
from dpaste.highlight import LEXER_WORDWRAP, LEXER_LIST
def about(request, template_name='dpaste/about.html'):
template_context = {
'total': Snippet.objects.count(),
'stats': Snippet.objects.values('lexer').annotate(
count=Count('lexer')).order_by('-count')[:5],
}
return render_to_response(
template_name,
template_context,
RequestContext(request)
)
# -----------------------------------------------------------------------------
# Snippet Handling
# -----------------------------------------------------------------------------
def snippet_new(request, template_name='dpaste/snippet_new.html'):
"""
Create a new snippet.
"""
if request.method == "POST":
snippet_form = SnippetForm(data=request.POST, request=request)
if snippet_form.is_valid():
request, new_snippet = snippet_form.save()
new_snippet = snippet_form.save()
url = new_snippet.get_absolute_url()
return HttpResponseRedirect(url)
else:
@ -48,6 +39,7 @@ def snippet_new(request, template_name='dpaste/snippet_new.html'):
template_context = {
'snippet_form': snippet_form,
'lexer_list': LEXER_LIST,
'is_new': True,
}
@ -58,31 +50,13 @@ def snippet_new(request, template_name='dpaste/snippet_new.html'):
)
def snippet_api(request, enclose_quotes=True):
content = request.POST.get('content', '').strip()
if not content:
return HttpResponseBadRequest()
s = Snippet.objects.create(
content=content,
expires=datetime.datetime.now()+datetime.timedelta(seconds=60*60*24*30)
)
s.save()
response = 'http://dpaste.de%s' % s.get_absolute_url()
if enclose_quotes:
return HttpResponse('"%s"' % response)
return HttpResponse(response)
def snippet_details(request, snippet_id, template_name='dpaste/snippet_details.html', is_raw=False):
"""
Details list view of a snippet. Handles the actual view, reply and
tree/diff view.
"""
try:
snippet = Snippet.objects.get(secret_id=snippet_id)
except MultipleObjectsReturned:
raise Http404('Multiple snippets exist for this slug. This should never '
'happen but its likely that you are a spam bot, so I dont '
'care.')
except ObjectDoesNotExist:
raise Http404('This snippet does not exist anymore. Its likely that its '
'lifetime is expired.')
@ -98,7 +72,7 @@ def snippet_details(request, snippet_id, template_name='dpaste/snippet_details.h
if request.method == "POST":
snippet_form = SnippetForm(data=request.POST, request=request, initial=new_snippet_initial)
if snippet_form.is_valid():
request, new_snippet = snippet_form.save(parent=snippet)
new_snippet = snippet_form.save(parent=snippet)
url = new_snippet.get_absolute_url()
return HttpResponseRedirect(url)
else:
@ -106,8 +80,8 @@ def snippet_details(request, snippet_id, template_name='dpaste/snippet_details.h
template_context = {
'snippet_form': snippet_form,
'lexer_list': LEXER_LIST,
'snippet': snippet,
'lexers': LEXER_LIST,
'lines': range(snippet.get_linecount()),
'tree': tree,
'wordwrap': snippet.lexer in LEXER_WORDWRAP and 'True' or 'False',
@ -125,26 +99,31 @@ def snippet_details(request, snippet_id, template_name='dpaste/snippet_details.h
else:
return response
def snippet_delete(request, snippet_id):
"""
Delete a snippet. This is allowed by anybody as long as he knows the
snippet id. I got too many manual requests to do this, mostly for legal
reasons and the chance to abuse this is not given anyway, since snippets
always expire.
"""
snippet = get_object_or_404(Snippet, secret_id=snippet_id)
try:
snippet_list = request.session['snippet_list']
except KeyError:
return HttpResponseForbidden('You have no recent snippet list, cookie error?')
if not snippet.pk in snippet_list:
return HttpResponseForbidden('That\'s not your snippet!')
snippet.delete()
return HttpResponseRedirect(reverse('snippet_new'))
def snippet_history(request, template_name='dpaste/snippet_list.html'):
def snippet_history(request, template_name='dpaste/snippet_list.html'):
"""
Display the last `n` snippets created by this user (and saved in his
session).
"""
try:
snippet_list = get_list_or_404(Snippet, pk__in=request.session.get('snippet_list', None))
except ValueError:
snippet_list = None
template_context = {
'snippets_max': getattr(settings, 'MAX_SNIPPETS_PER_USER', 10),
'snippets_max': getattr(settings, 'DPASTE_MAX_SNIPPETS_PER_USER', 10),
'snippet_list': snippet_list,
}
@ -156,7 +135,9 @@ def snippet_history(request, template_name='dpaste/snippet_list.html'):
def snippet_diff(request, template_name='dpaste/snippet_diff.html'):
"""
Display a diff between two given snippet secret ids.
"""
if request.GET.get('a') and request.GET.get('a').isdigit() \
and request.GET.get('b') and request.GET.get('b').isdigit():
try:
@ -199,6 +180,7 @@ def snippet_diff(request, template_name='dpaste/snippet_diff.html'):
RequestContext(request)
)
def snippet_gist(request, snippet_id):
"""
Put a snippet on Github Gist.
@ -227,15 +209,58 @@ def snippet_gist(request, snippet_id):
return HttpResponseRedirect(gist_url)
# -----------------------------------------------------------------------------
# Static pages
# -----------------------------------------------------------------------------
def guess_lexer(request):
code_string = request.GET.get('codestring', False)
response = simplejson.dumps({'lexer': guess_code_lexer(code_string)})
def about(request, template_name='dpaste/about.html'):
"""
A rather static page, we need a view just to display a couple of
statistics.
"""
template_context = {
'total': Snippet.objects.count(),
'stats': Snippet.objects.values('lexer').annotate(
count=Count('lexer')).order_by('-count')[:5],
}
return render_to_response(
template_name,
template_context,
RequestContext(request)
)
# -----------------------------------------------------------------------------
# API Handling
# -----------------------------------------------------------------------------
def snippet_api(request, enclose_quotes=True):
content = request.POST.get('content', '').strip()
if not content:
return HttpResponseBadRequest()
s = Snippet.objects.create(
content=content,
expires=datetime.datetime.now()+datetime.timedelta(seconds=60*60*24*30)
)
s.save()
response = 'http://dpaste.de%s' % s.get_absolute_url()
if enclose_quotes:
return HttpResponse('"%s"' % response)
return HttpResponse(response)
# -----------------------------------------------------------------------------
# Custom 404 and 500 views. Its easier to integrate this as a app if we
# handle them here.
# -----------------------------------------------------------------------------
def page_not_found(request, template_name='dpaste/404.html'):
return django_page_not_found(request, template_name)
def server_error(request, template_name='dpaste/500.html'):
return django_server_error(request, template_name)