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:
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
lexer = lexer_name and get_lexer_by_name(lexer_name) \
or PythonLexer()
return highlight(code_string, lexer, NakedHtmlFormatter())

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>
@ -42,4 +41,4 @@
{% endif %}
<input tabindex="0" type="submit"class="btn btn-primary" value="{% trans "Paste it" %}">
</div>
</form>
</form>

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,45 +2,36 @@ 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)
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
from django.db.models import Count
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 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)