;;; paradox.el --- A modern Packages Menu. Colored, with package ratings, and customizable. -*- lexical-binding:t -*- ;; Copyright (C) 2014-2015 Artur Malabarba ;; Author: Artur Malabarba ;; 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: ;; * filters by regexp (`occur'); ;; * display only packages with upgrades; ;; * 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