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 import forms
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from dpaste.models import Snippet from dpaste.models import Snippet
from dpaste.highlight import LEXER_LIST, LEXER_DEFAULT from dpaste.highlight import LEXER_LIST, LEXER_DEFAULT
import datetime
#===============================================================================
# Snippet Form and Handling
#===============================================================================
EXPIRE_CHOICES = ( EXPIRE_CHOICES = (
(3600, _(u'In one hour')), (3600, _(u'In one hour')),
(3600 * 24 * 7, _(u'In one week')), (3600 * 24 * 7, _(u'In one week')),
(3600 * 24 * 30, _(u'In one month')), (3600 * 24 * 30, _(u'In one month')),
) )
EXPIRE_DEFAULT = EXPIRE_CHOICES[2][0]
EXPIRE_DEFAULT = 3600 * 24 * 30
MAX_CONTENT_LENGTH = getattr(settings, 'DPASTE_MAX_CONTENT_LENGTH', 250*1024*1024) 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): class SnippetForm(forms.ModelForm):
content = forms.CharField( content = forms.CharField(
label=_('Content'), label=_('Content'),
@ -29,7 +28,7 @@ class SnippetForm(forms.ModelForm):
lexer = forms.ChoiceField( lexer = forms.ChoiceField(
label=_(u'Lexer'), label=_(u'Lexer'),
initial=LEXER_DEFAULT, initial=LEXER_DEFAULT,
widget=forms.TextInput, choices=LEXER_LIST,
) )
expire_options = forms.ChoiceField( expire_options = forms.ChoiceField(
@ -55,35 +54,23 @@ class SnippetForm(forms.ModelForm):
def __init__(self, request, *args, **kwargs): def __init__(self, request, *args, **kwargs):
super(SnippetForm, self).__init__(*args, **kwargs) super(SnippetForm, self).__init__(*args, **kwargs)
self.request = request 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 # Set the recently used lexer if we have any
session_lexer = self.request.session.get('lexer') session_lexer = self.request.session.get('lexer')
if session_lexer and session_lexer in dict(LEXER_LIST).keys(): if session_lexer and session_lexer in dict(LEXER_LIST).keys():
self.fields['lexer'].initial = session_lexer 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): def clean_content(self):
return self.cleaned_data.get('content', '').strip() return self.cleaned_data.get('content', '').strip()
def clean(self): def clean(self):
# The `title` field is a hidden honeypot field. If its filled,
# this is likely spam.
if self.cleaned_data.get('title'): if self.cleaned_data.get('title'):
raise forms.ValidationError('This snippet was identified as Spam.') raise forms.ValidationError('This snippet was identified as Spam.')
return self.cleaned_data return self.cleaned_data
def save(self, parent=None, *args, **kwargs): def save(self, parent=None, *args, **kwargs):
# Set parent snippet # Set parent snippet
if parent: if parent:
self.instance.parent = parent self.instance.parent = parent
@ -97,7 +84,7 @@ class SnippetForm(forms.ModelForm):
# Add the snippet to the user session list # Add the snippet to the user session list
if self.request.session.get('snippet_list', False): 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'].pop(0)
self.request.session['snippet_list'] += [self.instance.pk] self.request.session['snippet_list'] += [self.instance.pk]
else: else:
@ -106,4 +93,4 @@ class SnippetForm(forms.ModelForm):
# Save the lexer in the session so we can use it later again # Save the lexer in the session so we can use it later again
self.request.session['lexer'] = self.cleaned_data['lexer'] 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 import highlight
from pygments.lexers import * from pygments.lexers import *
from pygments.lexers import get_all_lexers
from pygments.formatters import HtmlFormatter 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 # The list of lexers. Its not worth to autogenerate this. See above how to
logger = logging.getLogger(__name__) # 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 # The default lexer is python
LEXER_LIST = sorted([(i[0], i[0]) for i in get_all_lexers() if not ( LEXER_DEFAULT = getattr(settings, 'DPASTE_LEXER_DEFAULT', 'python')
'+' in i[0] or
'with' in i[0].lower() or # Lexers which have wordwrap enabled by default
i[0].islower() LEXER_WORDWRAP = getattr(settings, 'DPASTE_LEXER_WORDWRAP', ('text', 'rst'))
)])
LEXER_LIST_NAME = dict([(i[0], i[1][0]) for i in get_all_lexers()])
LEXER_DEFAULT = 'Python'
LEXER_WORDWRAP = ('text', 'rst')
class NakedHtmlFormatter(HtmlFormatter): class NakedHtmlFormatter(HtmlFormatter):
def wrap(self, source, outfile): def wrap(self, source, outfile):
@ -28,25 +107,6 @@ class NakedHtmlFormatter(HtmlFormatter):
yield i, t yield i, t
def pygmentize(code_string, lexer_name=LEXER_DEFAULT): def pygmentize(code_string, lexer_name=LEXER_DEFAULT):
lexer_name = LEXER_LIST_NAME.get(lexer_name, None) lexer = lexer_name and get_lexer_by_name(lexer_name) \
try: or PythonLexer()
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()) 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 %} {% block script_footer %}
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script> <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 %} {% endblock %}
</body> </body>

View file

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

View file

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

View file

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

View file

@ -1,10 +1,7 @@
from django.conf.urls.defaults import url, patterns from django.conf.urls.defaults import url, patterns
from . import views
urlpatterns = patterns('dpaste.views', urlpatterns = patterns('dpaste.views',
url(r'^$', 'snippet_new', name='snippet_new'), 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'^diff/$', 'snippet_diff', name='snippet_diff'),
url(r'^history/$', 'snippet_history', name='snippet_history'), url(r'^history/$', 'snippet_history', name='snippet_history'),
url(r'^(?P<snippet_id>[a-zA-Z0-9]+)/$', 'snippet_details', name='snippet_details'), 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 difflib
import requests 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.template.context import RequestContext
from django.http import (Http404, HttpResponseRedirect, HttpResponseBadRequest, from django.http import (Http404, HttpResponseRedirect, HttpResponseBadRequest,
HttpResponse, HttpResponseForbidden) HttpResponse, HttpResponseForbidden)
from django.conf import settings 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.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils import simplejson 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.forms import SnippetForm
from dpaste.models import Snippet from dpaste.models import Snippet
from dpaste.highlight import guess_code_lexer, \ from dpaste.highlight import LEXER_WORDWRAP, LEXER_LIST
LEXER_WORDWRAP, LEXER_LIST
# -----------------------------------------------------------------------------
# Snippet Handling
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)
)
def snippet_new(request, template_name='dpaste/snippet_new.html'): def snippet_new(request, template_name='dpaste/snippet_new.html'):
"""
Create a new snippet.
"""
if request.method == "POST": if request.method == "POST":
snippet_form = SnippetForm(data=request.POST, request=request) snippet_form = SnippetForm(data=request.POST, request=request)
if snippet_form.is_valid(): if snippet_form.is_valid():
request, new_snippet = snippet_form.save() new_snippet = snippet_form.save()
url = new_snippet.get_absolute_url() url = new_snippet.get_absolute_url()
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else: else:
@ -48,6 +39,7 @@ def snippet_new(request, template_name='dpaste/snippet_new.html'):
template_context = { template_context = {
'snippet_form': snippet_form, 'snippet_form': snippet_form,
'lexer_list': LEXER_LIST,
'is_new': True, '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): 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: try:
snippet = Snippet.objects.get(secret_id=snippet_id) 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: except ObjectDoesNotExist:
raise Http404('This snippet does not exist anymore. Its likely that its ' raise Http404('This snippet does not exist anymore. Its likely that its '
'lifetime is expired.') 'lifetime is expired.')
@ -98,7 +72,7 @@ def snippet_details(request, snippet_id, template_name='dpaste/snippet_details.h
if request.method == "POST": if request.method == "POST":
snippet_form = SnippetForm(data=request.POST, request=request, initial=new_snippet_initial) snippet_form = SnippetForm(data=request.POST, request=request, initial=new_snippet_initial)
if snippet_form.is_valid(): 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() url = new_snippet.get_absolute_url()
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else: else:
@ -106,8 +80,8 @@ def snippet_details(request, snippet_id, template_name='dpaste/snippet_details.h
template_context = { template_context = {
'snippet_form': snippet_form, 'snippet_form': snippet_form,
'lexer_list': LEXER_LIST,
'snippet': snippet, 'snippet': snippet,
'lexers': LEXER_LIST,
'lines': range(snippet.get_linecount()), 'lines': range(snippet.get_linecount()),
'tree': tree, 'tree': tree,
'wordwrap': snippet.lexer in LEXER_WORDWRAP and 'True' or 'False', '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: else:
return response return response
def snippet_delete(request, snippet_id): 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) 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() snippet.delete()
return HttpResponseRedirect(reverse('snippet_new')) 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: try:
snippet_list = get_list_or_404(Snippet, pk__in=request.session.get('snippet_list', None)) snippet_list = get_list_or_404(Snippet, pk__in=request.session.get('snippet_list', None))
except ValueError: except ValueError:
snippet_list = None snippet_list = None
template_context = { 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, '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'): 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() \ if request.GET.get('a') and request.GET.get('a').isdigit() \
and request.GET.get('b') and request.GET.get('b').isdigit(): and request.GET.get('b') and request.GET.get('b').isdigit():
try: try:
@ -199,6 +180,7 @@ def snippet_diff(request, template_name='dpaste/snippet_diff.html'):
RequestContext(request) RequestContext(request)
) )
def snippet_gist(request, snippet_id): def snippet_gist(request, snippet_id):
""" """
Put a snippet on Github Gist. Put a snippet on Github Gist.
@ -227,15 +209,58 @@ def snippet_gist(request, snippet_id):
return HttpResponseRedirect(gist_url) return HttpResponseRedirect(gist_url)
# -----------------------------------------------------------------------------
# Static pages
# -----------------------------------------------------------------------------
def guess_lexer(request): def about(request, template_name='dpaste/about.html'):
code_string = request.GET.get('codestring', False) """
response = simplejson.dumps({'lexer': guess_code_lexer(code_string)}) 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) 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'): def page_not_found(request, template_name='dpaste/404.html'):
return django_page_not_found(request, template_name) return django_page_not_found(request, template_name)
def server_error(request, template_name='dpaste/500.html'): def server_error(request, template_name='dpaste/500.html'):
return django_server_error(request, template_name) return django_server_error(request, template_name)