Move Python commands to separate library
This commit is contained in:
parent
82a7d84572
commit
00019a1e90
2 changed files with 203 additions and 167 deletions
|
@ -137,16 +137,6 @@ 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)
|
||||
|
@ -211,15 +201,6 @@ But only if it is a maildir inbox."
|
|||
(funcall regfunc (point) (- (point) num))
|
||||
(funcall wordfunc -1))))
|
||||
|
||||
(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")
|
||||
|
@ -298,25 +279,6 @@ But only if it is a maildir inbox."
|
|||
(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))
|
||||
|
@ -708,13 +670,6 @@ For `python-mode' I prefer `python-imenu-create-flat-index'."
|
|||
(interactive)
|
||||
(find-file "~/documents/org/index.org"))
|
||||
|
||||
(defun oni:sort-imports ()
|
||||
"Sort python multiline imports using `()'."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(sort-lines nil (1+ (search-backward "("))
|
||||
(1- (search-forward ")")))))
|
||||
|
||||
(defun oni:split-window-interactive (dir)
|
||||
"Split windows in direction DIR.
|
||||
|
||||
|
@ -801,128 +756,6 @@ If no direction is given, don't split."
|
|||
(projectile-rails-root))
|
||||
(rvm-activate-ruby-for (projectile-rails-root))))
|
||||
|
||||
;;;; 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,
|
||||
)")))))
|
||||
|
||||
;;;; Module-specific settings
|
||||
|
||||
(auto-init appt)
|
||||
|
|
203
emacs/.emacs.d/site-lisp/oni-python.el
Normal file
203
emacs/.emacs.d/site-lisp/oni-python.el
Normal file
|
@ -0,0 +1,203 @@
|
|||
;;; oni-python.el --- Extra Python commands -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2015 Tom Willemse
|
||||
|
||||
;; Author: Tom Willemse <tom@ryuslash.org>
|
||||
;; Keywords:
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Here are some extra Emacs commands for working with Python source
|
||||
;; code.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'python)
|
||||
|
||||
;;;###autoload
|
||||
(defun oni:add-import-from (package import)
|
||||
"Add a Python import statement at the beginning of the module."
|
||||
(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:collect-from-imports ()
|
||||
"Find all modules from which names are imported in the current file."
|
||||
(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))
|
||||
|
||||
;;;###autoload
|
||||
(defun oni:make-import-multiline (from-point to-point)
|
||||
"Turn an import statement into a multi-line import statement."
|
||||
(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)))
|
||||
|
||||
;;;###autoload
|
||||
(defun oni:sort-imports ()
|
||||
"Sort python multiline imports using `()'."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(sort-lines nil (1+ (search-backward "("))
|
||||
(1- (search-forward ")")))))
|
||||
|
||||
;;; Tests
|
||||
|
||||
(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,
|
||||
)"))))
|
||||
|
||||
(provide 'oni-python)
|
||||
;;; oni-python.el ends here
|
Loading…
Reference in a new issue