229 lines
8.7 KiB
EmacsLisp
229 lines
8.7 KiB
EmacsLisp
;;; paradox.el --- A modern Packages Menu. Colored, with package ratings, and customizable. -*- lexical-binding:t -*-
|
||
|
||
;; Copyright (C) 2014-2015 Artur Malabarba <emacs@endlessparentheses.com>
|
||
|
||
;; Author: Artur Malabarba <emacs@endlessparentheses.com>
|
||
;; URL: https://github.com/Malabarba/paradox
|
||
;; Version: 2.5.1
|
||
;; Keywords: package packages
|
||
;; Package-Requires: ((emacs "24.4") (seq "1.7") (let-alist "1.0.3") (spinner "1.7.3") (hydra "0.13.2"))
|
||
;; Prefix: paradox
|
||
;; Separator: -
|
||
|
||
;;; Commentary:
|
||
;;
|
||
;; Paradox can be installed from Melpa with M-x `package-install' RET
|
||
;; paradox.
|
||
;; It can also be installed manually in the usual way, just be mindful of
|
||
;; the dependencies.
|
||
;;
|
||
;; To use it, simply call M-x `paradox-list-packages' (instead of the
|
||
;; regular `list-packages').
|
||
;; This will give you most features out of the box. If you want to be
|
||
;; able to star packages as well, just configure the
|
||
;; `paradox-github-token' variable then call `paradox-list-packages'
|
||
;; again.
|
||
;;
|
||
;; If you'd like to stop using Paradox, you may call `paradox-disable'
|
||
;; and go back to using the regular `list-packages'.
|
||
;;
|
||
;; ## Current Features ##
|
||
;;
|
||
;; ### Several Improvements ###
|
||
;;
|
||
;; Paradox implements many small improvements to the package menu
|
||
;; itself. They all work out of the box and are completely customizable!
|
||
;; *(Also, hit `h' to see all keys.)*
|
||
;;
|
||
;; * Visit the package's homepage with `v' (or just use the provided buttons).
|
||
;; * Shortcuts for package filtering:
|
||
;; * <f r> filters by regexp (`occur');
|
||
;; * <f u> display only packages with upgrades;
|
||
;; * <f k> filters by keyword (Emacs 24.4 only).
|
||
;; * `hl-line-mode' enabled by default.
|
||
;; * Display useful information on the mode-line and cleanup a bunch of
|
||
;; useless stuff.
|
||
;; * **Customization!** Just call M-x `paradox-customize' to see what you can
|
||
;; do.
|
||
;; * Customize column widths.
|
||
;; * Customize faces (`paradox-star-face', `paradox-status-face-alist' and `paradox-archive-face').
|
||
;; * Customize local variables.
|
||
;;
|
||
;; ### Package Ratings ###
|
||
;;
|
||
;; Paradox also integrates with
|
||
;; **GitHub Stars**, which works as **rough** package rating system.
|
||
;; That is, Paradox package menu will:
|
||
;;
|
||
;; 1. Display the number of GitHub Stars each package has (assuming it's
|
||
;; in a github repo, of course);
|
||
;; 2. Possibly automatically star packages you install, and unstar
|
||
;; packages you delete (you will be asked the first time whether you
|
||
;; want this);
|
||
;; 3. Let you star and unstar packages by hitting the `s' key;
|
||
;; 4. Let you star all packages you have installed with M-x `paradox-star-all-installed-packages'.
|
||
;;
|
||
;; Item **1.** will work out of the box, the other items obviously
|
||
;; require a github account (Paradox will help you generate a token the
|
||
;; first time you call `paradox-list-packages').
|
||
;;
|
||
;; ## How Star Displaying Works ##
|
||
;;
|
||
;; We generate a map of Package Name -> Repository from
|
||
;; [Melpa](https://github.com/milkypostman/melpa.git)'s `recipe'
|
||
;; directory, some repos may correspond to more than one package.
|
||
;; This map is used count the stars a given package has.
|
||
;; _This doesn't mean you need Melpa to see the star counts, the numbers
|
||
;; will be displayed regardless of what archives you use._
|
||
;;
|
||
;; Currently, packages that are not hosted on GitHub are listed with a
|
||
;; blank star count, which is clearly different from 0-star packages
|
||
;; (which are displayed with a 0, obviously).
|
||
;; If you know of an alternative that could be used for these packages,
|
||
;; [open an issue](https://github.com/Bruce-Connor/paradox/issues/new)
|
||
;; here, I'd love to hear.
|
||
|
||
;;; License:
|
||
;;
|
||
;; This file is NOT part of GNU Emacs.
|
||
;;
|
||
;; 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 2
|
||
;; 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.
|
||
|
||
|
||
;;; Code:
|
||
|
||
(require 'package)
|
||
(require 'cl-lib)
|
||
|
||
(require 'paradox-core)
|
||
(require 'paradox-execute)
|
||
(require 'paradox-menu)
|
||
|
||
(defconst paradox-version "2.5.1" "Version of the paradox.el package.")
|
||
(defun paradox-bug-report ()
|
||
"Opens github issues page in a web browser. Please send any bugs you find.
|
||
Please include your Emacs and paradox versions."
|
||
(interactive)
|
||
(message "Your paradox-version is: %s, and your emacs version is: %s.\nPlease include this in your report!"
|
||
paradox-version emacs-version)
|
||
(browse-url "https://github.com/Bruce-Connor/paradox/issues/new"))
|
||
(defun paradox-customize ()
|
||
"Open the customization menu in the `paradox' group."
|
||
(interactive)
|
||
(customize-group 'paradox t))
|
||
(defgroup paradox nil
|
||
"Customization group for paradox."
|
||
:prefix "paradox-"
|
||
:group 'emacs
|
||
:package-version '(paradox . "0.1"))
|
||
|
||
|
||
;;; External Commands
|
||
;;;###autoload
|
||
(defun paradox-list-packages (no-fetch)
|
||
"Improved version of `package-list-packages'. The heart of Paradox.
|
||
Function is equivalent to `package-list-packages' (including the
|
||
prefix NO-FETCH), but the resulting Package Menu is improved in
|
||
several ways.
|
||
|
||
Among them:
|
||
|
||
1. Uses `paradox-menu-mode', which has more functionality and
|
||
keybinds than `package-menu-mode'.
|
||
|
||
2. Uses some font-locking to improve readability.
|
||
|
||
3. Optionally shows the number GitHub stars and Melpa downloads
|
||
for packages.
|
||
|
||
4. Adds useful information in the mode-line."
|
||
(interactive "P")
|
||
(when (paradox--check-github-token)
|
||
(paradox-enable)
|
||
(let ((is-25 (fboundp 'package--with-response-buffer)))
|
||
(unless no-fetch
|
||
(if is-25
|
||
(add-to-list 'package--downloads-in-progress 'paradox--data)
|
||
(paradox--refresh-remote-data)))
|
||
(package-list-packages no-fetch)
|
||
(unless no-fetch
|
||
(when (stringp paradox-github-token)
|
||
(paradox--refresh-user-starred-list
|
||
(bound-and-true-p package-menu-async)))
|
||
(when is-25
|
||
(paradox--refresh-remote-data))))))
|
||
|
||
;;;###autoload
|
||
(defun paradox-upgrade-packages (&optional no-fetch)
|
||
"Upgrade all packages. No questions asked.
|
||
This function is equivalent to `list-packages', followed by a
|
||
`package-menu-mark-upgrades' and a `package-menu-execute'. Except
|
||
the user isn't asked to confirm deletion of packages.
|
||
|
||
If `paradox-execute-asynchronously' is non-nil, part of this
|
||
operation may be performed in the background.
|
||
|
||
The NO-FETCH prefix argument is passed to `list-packages'. It
|
||
prevents re-download of information about new versions. It does
|
||
not prevent downloading the actual packages (obviously)."
|
||
(interactive "P")
|
||
(save-window-excursion
|
||
(let ((package-menu-async nil))
|
||
(paradox-list-packages no-fetch))
|
||
(package-menu-mark-upgrades)
|
||
(paradox-menu-execute 'noquery)))
|
||
|
||
(defun paradox-enable ()
|
||
"Enable paradox, overriding the default package-menu."
|
||
(interactive)
|
||
(when (and (fboundp 'package--update-downloads-in-progress)
|
||
(not (fboundp 'package--with-response-buffer)))
|
||
(message "[Paradox] Your Emacs snapshot is outdated, please install a more recent one.")
|
||
(setq package-menu-async nil))
|
||
(paradox--override-definition 'package-menu--print-info 'paradox--print-info)
|
||
(when (fboundp 'package-menu--print-info-simple)
|
||
(paradox--override-definition 'package-menu--print-info-simple 'paradox--print-info))
|
||
(paradox--override-definition 'package-menu--generate 'paradox--generate-menu)
|
||
;; Tough it may not look like it, this is totally necessary too.
|
||
(paradox--override-definition 'package-menu-mode 'paradox-menu-mode)
|
||
(paradox--core-enable))
|
||
|
||
;;;###autoload
|
||
(defun paradox-require (feature &optional filename noerror package refresh)
|
||
"Like `require', but also install FEATURE if it is absent.
|
||
FILENAME is passed to `require'.
|
||
If NOERROR is non-nil, don't complain if the feature couldn't be
|
||
installed, just return nil.
|
||
|
||
- If FEATURE is present, `require' it and return t.
|
||
|
||
- If FEATURE is not present, install PACKAGE with `package-install'.
|
||
If PACKAGE is nil, assume FEATURE is the package name.
|
||
After installation, `require' FEATURE.
|
||
|
||
By default, the current package database is only updated if it is
|
||
empty. Passing a non-nil REFRESH argument forces this update."
|
||
(or (require feature filename t)
|
||
(let ((package (or package
|
||
(if (stringp feature)
|
||
(intern feature)
|
||
feature))))
|
||
(require 'package)
|
||
(unless (and package-archive-contents (null refresh))
|
||
(package-refresh-contents))
|
||
(and (condition-case e
|
||
(package-install package)
|
||
(error (if noerror nil (error (cadr e)))))
|
||
(require feature filename noerror)))))
|
||
|
||
(provide 'paradox)
|
||
;;; paradox.el ends here
|