From 35a7bb5d57b5564119ea414a0e334cb700f42516 Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Tue, 15 Apr 2014 23:53:52 +0200 Subject: Add some python editing functions, with tests --- .emacs.d/init.el | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) (limited to '.emacs.d') diff --git a/.emacs.d/init.el b/.emacs.d/init.el index ac73282..0f69cbd 100644 --- a/.emacs.d/init.el +++ b/.emacs.d/init.el @@ -126,6 +126,16 @@ MODE1 is enabled and vice-versa." ;;;; Functions +(defun oni:add-import-from (package import) + (interactive + (list (completing-read "From package: " (oni:collect-from-imports)) + (read-string "Import: "))) + (save-excursion + (goto-char (point-min)) + (search-forward (concat "from " package " import (")) + (insert "\n " import ",") + (oni:sort-imports))) + (defun oni:after-save-func () "Function for `after-save-hook'." (executable-make-buffer-file-executable-if-script-p) @@ -196,6 +206,15 @@ MODE1 is enabled and vice-versa." (oni:shorten-dir (abbreviate-file-name (eshell/pwd)))))))) +(defun oni:collect-from-imports () + (let (results) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "from \\(.+\\) import" nil :noerror) + (push (buffer-substring-no-properties (match-beginning 1) + (match-end 1)) results))) + results)) + (defun oni:current-jabber-status () "Return a string representing the current jabber status." (or (and (not *jabber-connected*) "Offline") @@ -335,6 +354,25 @@ If COUNT has been specified indent by that much, otherwise look at (local-unset-key (kbd "]")) (local-unset-key (kbd "}"))) +(defun oni:make-import-multiline (from-point to-point) + (interactive (list (line-beginning-position) + (line-end-position))) + (goto-char from-point) + (search-forward "import" to-point) + (insert " (\n") + (delete-horizontal-space) + (let ((imports-start (point)) imports-end) + (while (search-forward "," to-point :noeror) + (insert "\n") + (delete-horizontal-space)) + (end-of-line) + (insert ",\n") + (setf imports-end (point)) + (insert ")") + (python-indent-shift-right imports-start imports-end) + (forward-line -1) + (oni:sort-imports))) + (defun oni:make-readable () "Make non-programming buffers a little more readable." (setq line-spacing .2)) @@ -804,6 +842,128 @@ If no direction is given, don't split." (setq-default electric-pair-mode nil) ; But keep it globally disabled. ))) +;;;; Tests + +(stante-after ert + (ert-deftest oni:add-import-from () + (with-temp-buffer + (python-mode) + (insert "from myaethon2.core.administration.models import ( + Client, + Contact, + Individual, + Location, +)") + (oni:add-import-from "myaethon2.core.administration.models" "Debtor") + (should (equal (buffer-substring-no-properties (point-min) (point-max)) + "from myaethon2.core.administration.models import ( + Client, + Contact, + Debtor, + Individual, + Location, +)")))) + + (ert-deftest oni:collect-from-imports () + (with-temp-buffer + (python-mode) + (insert "import calendar as cal +import datetime + +from django.conf import settings +from django.contrib import messages +from django.contrib.auth.decorators import login_required, permission_required +from django.core.context_processors import csrf +from django.core.exceptions import PermissionDenied +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger +from django.core.urlresolvers import reverse +from django.db import transaction +from django.db.models import Q +from django.shortcuts import get_object_or_404, render +from django.utils import formats +from django.utils.translation import ugettext as _ + +from myaethon2.core.business_units import BU +from myaethon2.core.forms import MultiFormWrapper +from myaethon2.core.models import AUser, Service +from myaethon2.core.planning.models import Booking, JOB_TYPES +from myaethon2.core.util import simplify_timedelta +from myaethon2.core.views import SearchAndSortListView +from myaethon2.jobs import forms, status +from myaethon2.jobs.models import Assignment, Job, JobGroup +from myaethon2.jobs.util import JobFactory +from myaethon2.workers.models import Worker +from myaethon2.export import Exporter, XLSGenerator + +from django.http import ( + HttpResponseForbidden, + HttpResponseNotAllowed, + HttpResponseRedirect, +) + +from django.views.generic import ( + CreateView, + DeleteView, + DetailView, + ListView, + UpdateView, +) + +from myaethon2.core.administration.models import ( + Client, + Contact, + Debtor, + Individual, + Location, +) + +from myaethon2.core.decorators import ( + json_response, + protect_with, + with_help_text, +)") + (should (equal (sort (oni:collect-from-imports) #'string-lessp) + '("django.conf" + "django.contrib" + "django.contrib.auth.decorators" + "django.core.context_processors" + "django.core.exceptions" + "django.core.paginator" + "django.core.urlresolvers" + "django.db" + "django.db.models" + "django.http" + "django.shortcuts" + "django.utils" + "django.utils.translation" + "django.views.generic" + "myaethon2.core.administration.models" + "myaethon2.core.business_units" + "myaethon2.core.decorators" + "myaethon2.core.forms" + "myaethon2.core.models" + "myaethon2.core.planning.models" + "myaethon2.core.util" + "myaethon2.core.views" + "myaethon2.export" + "myaethon2.jobs" + "myaethon2.jobs.models" + "myaethon2.jobs.util" + "myaethon2.workers.models"))))) + + (ert-deftest oni:make-import-multiline () + (with-temp-buffer + (python-mode) + (insert "from myaethon2.core.administration.models import Contact, Individual, Client, Location") + (oni:make-import-multiline (line-beginning-position) (line-end-position)) + (should (equal (buffer-substring-no-properties (point-min) (point-max)) + "from myaethon2.core.administration.models import ( + Client, + Contact, + Individual, + Location, +)"))))) + ;;;; Aliases (defalias 'yes-or-no-p 'y-or-n-p) -- cgit v1.2.3-54-g00ecf