From 89462aceb363b06b74348bc5e12db1d4e7dd976e Mon Sep 17 00:00:00 2001 From: Rmys Date: Tue, 9 May 2017 12:25:35 +0300 Subject: [PATCH] emacs:Version bump --- editor/emacs/emacs/actions.py | 34 + editor/emacs/emacs/comar/pakhandler.py | 29 + editor/emacs/emacs/files/80-nxml-mode.el | 11 + .../emacs/files/emacs-24.3-giflib5.patch | 26 + editor/emacs/emacs/files/emacs.desktop | 97 + editor/emacs/emacs/files/git/80-git.el | 1 + editor/emacs/emacs/files/git/git-blame.el | 482 +++++ editor/emacs/emacs/files/git/git.el | 1698 +++++++++++++++++ editor/emacs/emacs/files/pisi-spec.rnc | 1071 +++++++++++ editor/emacs/emacs/files/site-start.el | 97 + editor/emacs/emacs/pspec.xml | 118 ++ editor/emacs/emacs/translations.xml | 8 + 12 files changed, 3672 insertions(+) create mode 100644 editor/emacs/emacs/actions.py create mode 100644 editor/emacs/emacs/comar/pakhandler.py create mode 100644 editor/emacs/emacs/files/80-nxml-mode.el create mode 100644 editor/emacs/emacs/files/emacs-24.3-giflib5.patch create mode 100644 editor/emacs/emacs/files/emacs.desktop create mode 100644 editor/emacs/emacs/files/git/80-git.el create mode 100644 editor/emacs/emacs/files/git/git-blame.el create mode 100644 editor/emacs/emacs/files/git/git.el create mode 100644 editor/emacs/emacs/files/pisi-spec.rnc create mode 100644 editor/emacs/emacs/files/site-start.el create mode 100644 editor/emacs/emacs/pspec.xml create mode 100644 editor/emacs/emacs/translations.xml diff --git a/editor/emacs/emacs/actions.py b/editor/emacs/emacs/actions.py new file mode 100644 index 0000000000..77a3d5f2ae --- /dev/null +++ b/editor/emacs/emacs/actions.py @@ -0,0 +1,34 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Licensed under the GNU General Public License, version 3. +# See the file http://www.gnu.org/licenses/gpl.txt + +from pisi.actionsapi import autotools +from pisi.actionsapi import pisitools +from pisi.actionsapi import shelltools +from pisi.actionsapi import get +import os + +def removeCruft(): + for root, dirs, files in os.walk(get.installDIR()): + for name in files: + if name.endswith(".el.gz"): + shelltools.unlink(os.path.join(root, name)) + +def setup(): + #autotools.autoreconf("-fvi") + autotools.configure("--with-x-toolkit=gtk \ + --with-xft") + +def build(): + autotools.make() + +def install(): + autotools.rawInstall("DESTDIR=%s" % get.installDIR()) + + # Remove versioned copy + #pisitools.remove("/usr/bin/emacs-*") + #removeCruft() + + pisitools.dodoc("ChangeLog", "BUGS", "README", "COPYING") diff --git a/editor/emacs/emacs/comar/pakhandler.py b/editor/emacs/emacs/comar/pakhandler.py new file mode 100644 index 0000000000..7a0bf20190 --- /dev/null +++ b/editor/emacs/emacs/comar/pakhandler.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +import piksemel +import os +import subprocess + +def byteCompile(filepath): + doc = piksemel.parse(filepath) + for item in doc.tags("File"): + path = item.getTagData("Path") + if path.endswith(".el") and not os.path.exists("/%sc" % path): + subprocess.call(["/usr/bin/emacs", "--no-init-file", "--no-site-file", "--multibyte", "-batch", "-f", "batch-byte-compile", "/%s" % path]) + +def removeByteCompiled(filepath): + doc = piksemel.parse(filepath) + for item in doc.tags("File"): + path = item.getTagData("Path") + if path.endswith(".el"): + try: + # Remove .elc + os.unlink("/%sc" % path) + except OSError: + pass + +def setupPackage(metapath, filepath): + byteCompile(filepath) + +def cleanupPackage(metapath, filepath): + removeByteCompiled(filepath) diff --git a/editor/emacs/emacs/files/80-nxml-mode.el b/editor/emacs/emacs/files/80-nxml-mode.el new file mode 100644 index 0000000000..814e588ed5 --- /dev/null +++ b/editor/emacs/emacs/files/80-nxml-mode.el @@ -0,0 +1,11 @@ +;;; nxml site-lisp configuration + +(require 'nxml-mode) +(fset 'xml-mode 'nxml-mode) +(setq nxml-child-indent 4) +(add-hook 'nxml-mode-hook + (lambda () + (setq indent-tabs-mode nil))) +(setq auto-mode-alist + (cons '("\\.\\(xml\\|xsl\\|rng\\|xhtml\\)\\'" . nxml-mode) + auto-mode-alist)) diff --git a/editor/emacs/emacs/files/emacs-24.3-giflib5.patch b/editor/emacs/emacs/files/emacs-24.3-giflib5.patch new file mode 100644 index 0000000000..b8571abb2c --- /dev/null +++ b/editor/emacs/emacs/files/emacs-24.3-giflib5.patch @@ -0,0 +1,26 @@ +--- src/image.c ++++ src/image.c 2013-05-21 15:49:41.945819346 +0000 +@@ -7192,7 +7192,11 @@ gif_load (struct frame *f, struct image + } + + /* Open the GIF file. */ ++#if GIFLIB_MAJOR < 5 + gif = fn_DGifOpenFileName (SSDATA (file)); ++#else ++ gif = fn_DGifOpenFileName (SSDATA (file), NULL); ++#endif + if (gif == NULL) + { + image_error ("Cannot open `%s'", file, Qnil); +@@ -7213,7 +7217,11 @@ gif_load (struct frame *f, struct image + memsrc.len = SBYTES (specified_data); + memsrc.index = 0; + ++#if GIFLIB_MAJOR < 5 + gif = fn_DGifOpen (&memsrc, gif_read_from_memory); ++#else ++ gif = fn_DGifOpen (&memsrc, gif_read_from_memory, NULL); ++#endif + if (!gif) + { + image_error ("Cannot open memory source `%s'", img->spec, Qnil); diff --git a/editor/emacs/emacs/files/emacs.desktop b/editor/emacs/emacs/files/emacs.desktop new file mode 100644 index 0000000000..a69d6b2fe5 --- /dev/null +++ b/editor/emacs/emacs/files/emacs.desktop @@ -0,0 +1,97 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Emacs +Name[bn]=ইম্যাক্স +Name[eo]=Emakso +Name[hi]=ईमेक्स +Name[ko]=이맥스 +Name[ne]=इमाक्स +Name[te]=ఈమెక్స్ +GenericName=Text Editor +GenericName[af]=Teks Redigeerder +GenericName[az]=Mətn Editoru +GenericName[be]=Тэкставы рэдактар +GenericName[bg]=Текстов редактор +GenericName[bn]=টেক্সট সম্পাদক +GenericName[br]=Aozer skrid +GenericName[bs]=Tekst editor +GenericName[ca]=Editor de text +GenericName[cs]=Textový editor +GenericName[csb]=Tekstowi editora +GenericName[cy]=Golygydd Testun +GenericName[da]= Teksteditor +GenericName[de]=Texteditor +GenericName[el]=Επεξεργαστής κειμένου +GenericName[eo]=Tekstredaktilo +GenericName[es]=Editor de texto +GenericName[et]=Tekstiredaktor +GenericName[eu]=Testu editorea +GenericName[fa]=ویرایشگر متن +GenericName[fi]=Tekstieditori +GenericName[fo]=Tekstritil +GenericName[fr]=Éditeur de texte +GenericName[fy]=Tekstbewurker +GenericName[ga]=Eagarthóir Téacs +GenericName[gl]=Editor de Textos +GenericName[he]=עורך טקסט +GenericName[hi]=पाठ संपादक +GenericName[hr]=Uređivač teksta +GenericName[hsb]=Wobdźěłar tekstow +GenericName[hu]=Szövegszerkesztő +GenericName[is]=Textaritill +GenericName[it]=Editor di testi +GenericName[ja]=テキストエディタ +GenericName[kk]=Мәтін редакторы +GenericName[km]=កម្មវិធី​វាយ​អត្ថបទ +GenericName[ko]=글월 편집기 +GenericName[lo]=ເຄື່ອງມືແກ້ໄຂຂໍ້ຄວາມ +GenericName[lt]=Teksto rengyklė +GenericName[lv]=Teksta Redaktors +GenericName[mk]=Уредувач на текст +GenericName[mn]=Текст боловсруулагч +GenericName[ms]=Penyunting Teks +GenericName[mt]=Editur tat-test +GenericName[nb]=Skriveprogram +GenericName[nds]=Texteditor +GenericName[ne]=पाठ सम्पादक +GenericName[nl]=Teksteditor +GenericName[nn]=Skriveprogram +GenericName[nso]=Mofetosi wa Sengwalwana +GenericName[pa]=ਪਾਠ ਸੰਪਾਦਕ +GenericName[pl]=Edytor tekstu +GenericName[pt]=Editor de Texto +GenericName[pt_BR]=Editor de Texto +GenericName[ro]=Editor de text +GenericName[ru]=Текстовый редактор +GenericName[rw]=Muhinduzi Umwandiko +GenericName[se]=Čállinprográmma +GenericName[sk]=Textový editor +GenericName[sl]=Urejevalnik besedil +GenericName[sr]=Уређивач текста +GenericName[sr@Latn]=Uređivač teksta +GenericName[ss]=Sihleli sembhalo +GenericName[sv]=Texteditor +GenericName[ta]=உரை தொகுப்பாளர் +GenericName[te]=వచన ఎడిటర్ +GenericName[tg]=Муҳаррири матн +GenericName[th]=โปรแกรมแก้ไขข้อความ +GenericName[tr]=Metin Düzenleyici +GenericName[tt]=Mäten Tözätkeçe +GenericName[uk]=Редактор текстів +GenericName[uz]=Матн таҳрирчи +GenericName[ven]=Musengulusi wa Manwalwa +GenericName[vi]=Trình soạn văn bản +GenericName[wa]=Aspougneu di tecse +GenericName[xh]=Umhleli Wombhalo +GenericName[zh_CN]=文本编辑器 +GenericName[zh_TW]=文字編輯器 +GenericName[zu]=Umlungisi wombhalo +MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++; +Exec=emacs %f +Icon=/usr/share/icons/hicolor/48x48/apps/emacs.png +Path= +Type=Application +Terminal=false +X-KDE-StartupNotify=false +X-StandardInstall=true +Categories=Qt;KDE;TextEditor; diff --git a/editor/emacs/emacs/files/git/80-git.el b/editor/emacs/emacs/files/git/80-git.el new file mode 100644 index 0000000000..2627ff1cd9 --- /dev/null +++ b/editor/emacs/emacs/files/git/80-git.el @@ -0,0 +1 @@ +(add-to-list 'vc-handled-backends 'GIT) diff --git a/editor/emacs/emacs/files/git/git-blame.el b/editor/emacs/emacs/files/git/git-blame.el new file mode 100644 index 0000000000..7f4c792978 --- /dev/null +++ b/editor/emacs/emacs/files/git/git-blame.el @@ -0,0 +1,482 @@ +;;; git-blame.el --- Minor mode for incremental blame for Git -*- coding: utf-8 -*- +;; +;; Copyright (C) 2007 David Kågedal +;; +;; Authors: David Kågedal +;; Created: 31 Jan 2007 +;; Message-ID: <87iren2vqx.fsf@morpheus.local> +;; License: GPL +;; Keywords: git, version control, release management +;; +;; Compatibility: Emacs21, Emacs22 and EmacsCVS +;; Git 1.5 and up + +;; This file is *NOT* part of GNU Emacs. +;; This file is distributed under the same terms as 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. + +;; You should have received a copy of the GNU General Public +;; License along with this program; if not, write to the Free +;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, +;; MA 02111-1307 USA + +;; http://www.fsf.org/copyleft/gpl.html + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Commentary: +;; +;; Here is an Emacs implementation of incremental git-blame. When you +;; turn it on while viewing a file, the editor buffer will be updated by +;; setting the background of individual lines to a color that reflects +;; which commit it comes from. And when you move around the buffer, a +;; one-line summary will be shown in the echo area. + +;;; Installation: +;; +;; To use this package, put it somewhere in `load-path' (or add +;; directory with git-blame.el to `load-path'), and add the following +;; line to your .emacs: +;; +;; (require 'git-blame) +;; +;; If you do not want to load this package before it is necessary, you +;; can make use of the `autoload' feature, e.g. by adding to your .emacs +;; the following lines +;; +;; (autoload 'git-blame-mode "git-blame" +;; "Minor mode for incremental blame for Git." t) +;; +;; Then first use of `M-x git-blame-mode' would load the package. + +;;; Compatibility: +;; +;; It requires GNU Emacs 21 or later and Git 1.5.0 and up +;; +;; If you'are using Emacs 20, try changing this: +;; +;; (overlay-put ovl 'face (list :background +;; (cdr (assq 'color (cddddr info))))) +;; +;; to +;; +;; (overlay-put ovl 'face (cons 'background-color +;; (cdr (assq 'color (cddddr info))))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Code: + +(eval-when-compile (require 'cl)) ; to use `push', `pop' + +(defface git-blame-prefix-face + '((((background dark)) (:foreground "gray" + :background "black")) + (((background light)) (:foreground "gray" + :background "white")) + (t (:weight bold))) + "The face used for the hash prefix." + :group 'git-blame) + +(defgroup git-blame nil + "A minor mode showing Git blame information." + :group 'git + :link '(function-link git-blame-mode)) + + +(defcustom git-blame-use-colors t + "Use colors to indicate commits in `git-blame-mode'." + :type 'boolean + :group 'git-blame) + +(defcustom git-blame-prefix-format + "%h %20A:" + "The format of the prefix added to each line in `git-blame' +mode. The format is passed to `format-spec' with the following format keys: + + %h - the abbreviated hash + %H - the full hash + %a - the author name + %A - the author email + %c - the committer name + %C - the committer email + %s - the commit summary +" + :group 'git-blame) + +(defcustom git-blame-mouseover-format + "%h %a %A: %s" + "The format of the description shown when pointing at a line in +`git-blame' mode. The format string is passed to `format-spec' +with the following format keys: + + %h - the abbreviated hash + %H - the full hash + %a - the author name + %A - the author email + %c - the committer name + %C - the committer email + %s - the commit summary +" + :group 'git-blame) + + +(defun git-blame-color-scale (&rest elements) + "Given a list, returns a list of triples formed with each +elements of the list. + +a b => bbb bba bab baa abb aba aaa aab" + (let (result) + (dolist (a elements) + (dolist (b elements) + (dolist (c elements) + (setq result (cons (format "#%s%s%s" a b c) result))))) + result)) + +;; (git-blame-color-scale "0c" "04" "24" "1c" "2c" "34" "14" "3c") => +;; ("#3c3c3c" "#3c3c14" "#3c3c34" "#3c3c2c" "#3c3c1c" "#3c3c24" +;; "#3c3c04" "#3c3c0c" "#3c143c" "#3c1414" "#3c1434" "#3c142c" ...) + +(defmacro git-blame-random-pop (l) + "Select a random element from L and returns it. Also remove +selected element from l." + ;; only works on lists with unique elements + `(let ((e (elt ,l (random (length ,l))))) + (setq ,l (remove e ,l)) + e)) + +(defvar git-blame-log-oneline-format + "format:[%cr] %cn: %s" + "*Formatting option used for describing current line in the minibuffer. + +This option is used to pass to git log --pretty= command-line option, +and describe which commit the current line was made.") + +(defvar git-blame-dark-colors + (git-blame-color-scale "0c" "04" "24" "1c" "2c" "34" "14" "3c") + "*List of colors (format #RGB) to use in a dark environment. + +To check out the list, evaluate (list-colors-display git-blame-dark-colors).") + +(defvar git-blame-light-colors + (git-blame-color-scale "c4" "d4" "cc" "dc" "f4" "e4" "fc" "ec") + "*List of colors (format #RGB) to use in a light environment. + +To check out the list, evaluate (list-colors-display git-blame-light-colors).") + +(defvar git-blame-colors '() + "Colors used by git-blame. The list is built once when activating git-blame +minor mode.") + +(defvar git-blame-ancient-color "dark green" + "*Color to be used for ancient commit.") + +(defvar git-blame-autoupdate t + "*Automatically update the blame display while editing") + +(defvar git-blame-proc nil + "The running git-blame process") +(make-variable-buffer-local 'git-blame-proc) + +(defvar git-blame-overlays nil + "The git-blame overlays used in the current buffer.") +(make-variable-buffer-local 'git-blame-overlays) + +(defvar git-blame-cache nil + "A cache of git-blame information for the current buffer") +(make-variable-buffer-local 'git-blame-cache) + +(defvar git-blame-idle-timer nil + "An idle timer that updates the blame") +(make-variable-buffer-local 'git-blame-cache) + +(defvar git-blame-update-queue nil + "A queue of update requests") +(make-variable-buffer-local 'git-blame-update-queue) + +;; FIXME: docstrings +(defvar git-blame-file nil) +(defvar git-blame-current nil) + +(defvar git-blame-mode nil) +(make-variable-buffer-local 'git-blame-mode) + +(defvar git-blame-mode-line-string " blame" + "String to display on the mode line when git-blame is active.") + +(or (assq 'git-blame-mode minor-mode-alist) + (setq minor-mode-alist + (cons '(git-blame-mode git-blame-mode-line-string) minor-mode-alist))) + +;;;###autoload +(defun git-blame-mode (&optional arg) + "Toggle minor mode for displaying Git blame + +With prefix ARG, turn the mode on if ARG is positive." + (interactive "P") + (cond + ((null arg) + (if git-blame-mode (git-blame-mode-off) (git-blame-mode-on))) + ((> (prefix-numeric-value arg) 0) (git-blame-mode-on)) + (t (git-blame-mode-off)))) + +(defun git-blame-mode-on () + "Turn on git-blame mode. + +See also function `git-blame-mode'." + (make-local-variable 'git-blame-colors) + (if git-blame-autoupdate + (add-hook 'after-change-functions 'git-blame-after-change nil t) + (remove-hook 'after-change-functions 'git-blame-after-change t)) + (git-blame-cleanup) + (let ((bgmode (cdr (assoc 'background-mode (frame-parameters))))) + (if (eq bgmode 'dark) + (setq git-blame-colors git-blame-dark-colors) + (setq git-blame-colors git-blame-light-colors))) + (setq git-blame-cache (make-hash-table :test 'equal)) + (setq git-blame-mode t) + (git-blame-run)) + +(defun git-blame-mode-off () + "Turn off git-blame mode. + +See also function `git-blame-mode'." + (git-blame-cleanup) + (if git-blame-idle-timer (cancel-timer git-blame-idle-timer)) + (setq git-blame-mode nil)) + +;;;###autoload +(defun git-reblame () + "Recalculate all blame information in the current buffer" + (interactive) + (unless git-blame-mode + (error "Git-blame is not active")) + + (git-blame-cleanup) + (git-blame-run)) + +(defun git-blame-run (&optional startline endline) + (if git-blame-proc + ;; Should maybe queue up a new run here + (message "Already running git blame") + (let ((display-buf (current-buffer)) + (blame-buf (get-buffer-create + (concat " git blame for " (buffer-name)))) + (args '("--incremental" "--contents" "-"))) + (if startline + (setq args (append args + (list "-L" (format "%d,%d" startline endline))))) + (setq args (append args + (list (file-name-nondirectory buffer-file-name)))) + (setq git-blame-proc + (apply 'start-process + "git-blame" blame-buf + "git" "blame" + args)) + (with-current-buffer blame-buf + (erase-buffer) + (make-local-variable 'git-blame-file) + (make-local-variable 'git-blame-current) + (setq git-blame-file display-buf) + (setq git-blame-current nil)) + (set-process-filter git-blame-proc 'git-blame-filter) + (set-process-sentinel git-blame-proc 'git-blame-sentinel) + (process-send-region git-blame-proc (point-min) (point-max)) + (process-send-eof git-blame-proc)))) + +(defun remove-git-blame-text-properties (start end) + (let ((modified (buffer-modified-p)) + (inhibit-read-only t)) + (remove-text-properties start end '(point-entered nil)) + (set-buffer-modified-p modified))) + +(defun git-blame-cleanup () + "Remove all blame properties" + (mapcar 'delete-overlay git-blame-overlays) + (setq git-blame-overlays nil) + (remove-git-blame-text-properties (point-min) (point-max))) + +(defun git-blame-update-region (start end) + "Rerun blame to get updates between START and END" + (let ((overlays (overlays-in start end))) + (while overlays + (let ((overlay (pop overlays))) + (if (< (overlay-start overlay) start) + (setq start (overlay-start overlay))) + (if (> (overlay-end overlay) end) + (setq end (overlay-end overlay))) + (setq git-blame-overlays (delete overlay git-blame-overlays)) + (delete-overlay overlay)))) + (remove-git-blame-text-properties start end) + ;; We can be sure that start and end are at line breaks + (git-blame-run (1+ (count-lines (point-min) start)) + (count-lines (point-min) end))) + +(defun git-blame-sentinel (proc status) + (with-current-buffer (process-buffer proc) + (with-current-buffer git-blame-file + (setq git-blame-proc nil) + (if git-blame-update-queue + (git-blame-delayed-update)))) + ;;(kill-buffer (process-buffer proc)) + ;;(message "git blame finished") + ) + +(defvar in-blame-filter nil) + +(defun git-blame-filter (proc str) + (save-excursion + (set-buffer (process-buffer proc)) + (goto-char (process-mark proc)) + (insert-before-markers str) + (goto-char 0) + (unless in-blame-filter + (let ((more t) + (in-blame-filter t)) + (while more + (setq more (git-blame-parse))))))) + +(defun git-blame-parse () + (cond ((looking-at "\\([0-9a-f]\\{40\\}\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\)\n") + (let ((hash (match-string 1)) + (src-line (string-to-number (match-string 2))) + (res-line (string-to-number (match-string 3))) + (num-lines (string-to-number (match-string 4)))) + (delete-region (point) (match-end 0)) + (setq git-blame-current (list (git-blame-new-commit hash) + src-line res-line num-lines))) + t) + ((looking-at "\\([a-z-]+\\) \\(.+\\)\n") + (let ((key (match-string 1)) + (value (match-string 2))) + (delete-region (point) (match-end 0)) + (git-blame-add-info (car git-blame-current) key value) + (when (string= key "filename") + (git-blame-create-overlay (car git-blame-current) + (caddr git-blame-current) + (cadddr git-blame-current)) + (setq git-blame-current nil))) + t) + (t + nil))) + +(defun git-blame-new-commit (hash) + (with-current-buffer git-blame-file + (or (gethash hash git-blame-cache) + ;; Assign a random color to each new commit info + ;; Take care not to select the same color multiple times + (let* ((color (if git-blame-colors + (git-blame-random-pop git-blame-colors) + git-blame-ancient-color)) + (info `(,hash (color . ,color)))) + (puthash hash info git-blame-cache) + info)))) + +(defun git-blame-create-overlay (info start-line num-lines) + (save-excursion + (set-buffer git-blame-file) + (let ((inhibit-point-motion-hooks t) + (inhibit-modification-hooks t)) + (goto-line start-line) + (let* ((start (point)) + (end (progn (forward-line num-lines) (point))) + (ovl (make-overlay start end)) + (hash (car info)) + (spec `((?h . ,(substring hash 0 6)) + (?H . ,hash) + (?a . ,(git-blame-get-info info 'author)) + (?A . ,(git-blame-get-info info 'author-mail)) + (?c . ,(git-blame-get-info info 'committer)) + (?C . ,(git-blame-get-info info 'committer-mail)) + (?s . ,(git-blame-get-info info 'summary))))) + (push ovl git-blame-overlays) + (overlay-put ovl 'git-blame info) + (overlay-put ovl 'help-echo + (format-spec git-blame-mouseover-format spec)) + (if git-blame-use-colors + (overlay-put ovl 'face (list :background + (cdr (assq 'color (cdr info)))))) + (overlay-put ovl 'line-prefix + (propertize (format-spec git-blame-prefix-format spec) + 'face 'git-blame-prefix-face)))))) + +(defun git-blame-add-info (info key value) + (nconc info (list (cons (intern key) value)))) + +(defun git-blame-get-info (info key) + (cdr (assq key (cdr info)))) + +(defun git-blame-current-commit () + (let ((info (get-char-property (point) 'git-blame))) + (if info + (car info) + (error "No commit info")))) + +(defun git-describe-commit (hash) + (with-temp-buffer + (call-process "git" nil t nil + "log" "-1" + (concat "--pretty=" git-blame-log-oneline-format) + hash) + (buffer-substring (point-min) (point-max)))) + +(defvar git-blame-last-identification nil) +(make-variable-buffer-local 'git-blame-last-identification) +(defun git-blame-identify (&optional hash) + (interactive) + (let ((info (gethash (or hash (git-blame-current-commit)) git-blame-cache))) + (when (and info (not (eq info git-blame-last-identification))) + (message "%s" (nth 4 info)) + (setq git-blame-last-identification info)))) + +;; (defun git-blame-after-save () +;; (when git-blame-mode +;; (git-blame-cleanup) +;; (git-blame-run))) +;; (add-hook 'after-save-hook 'git-blame-after-save) + +(defun git-blame-after-change (start end length) + (when git-blame-mode + (git-blame-enq-update start end))) + +(defvar git-blame-last-update nil) +(make-variable-buffer-local 'git-blame-last-update) +(defun git-blame-enq-update (start end) + "Mark the region between START and END as needing blame update" + ;; Try to be smart and avoid multiple callouts for sequential + ;; editing + (cond ((and git-blame-last-update + (= start (cdr git-blame-last-update))) + (setcdr git-blame-last-update end)) + ((and git-blame-last-update + (= end (car git-blame-last-update))) + (setcar git-blame-last-update start)) + (t + (setq git-blame-last-update (cons start end)) + (setq git-blame-update-queue (nconc git-blame-update-queue + (list git-blame-last-update))))) + (unless (or git-blame-proc git-blame-idle-timer) + (setq git-blame-idle-timer + (run-with-idle-timer 0.5 nil 'git-blame-delayed-update)))) + +(defun git-blame-delayed-update () + (setq git-blame-idle-timer nil) + (if git-blame-update-queue + (let ((first (pop git-blame-update-queue)) + (inhibit-point-motion-hooks t)) + (git-blame-update-region (car first) (cdr first))))) + +(provide 'git-blame) + +;;; git-blame.el ends here diff --git a/editor/emacs/emacs/files/git/git.el b/editor/emacs/emacs/files/git/git.el new file mode 100644 index 0000000000..214930a021 --- /dev/null +++ b/editor/emacs/emacs/files/git/git.el @@ -0,0 +1,1698 @@ +;;; git.el --- A user interface for git + +;; Copyright (C) 2005, 2006, 2007, 2008, 2009 Alexandre Julliard + +;; Version: 1.0 + +;; 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. +;; +;; You should have received a copy of the GNU General Public +;; License along with this program; if not, write to the Free +;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, +;; MA 02111-1307 USA + +;;; Commentary: + +;; This file contains an interface for the git version control +;; system. It provides easy access to the most frequently used git +;; commands. The user interface is as far as possible identical to +;; that of the PCL-CVS mode. +;; +;; To install: put this file on the load-path and place the following +;; in your .emacs file: +;; +;; (require 'git) +;; +;; To start: `M-x git-status' +;; +;; TODO +;; - diff against other branch +;; - renaming files from the status buffer +;; - creating tags +;; - fetch/pull +;; - revlist browser +;; - git-show-branch browser +;; + +;;; Compatibility: +;; +;; This file works on GNU Emacs 21 or later. It may work on older +;; versions but this is not guaranteed. +;; +;; It may work on XEmacs 21, provided that you first install the ewoc +;; and log-edit packages. +;; + +(eval-when-compile (require 'cl)) +(require 'ewoc) +(require 'log-edit) +(require 'easymenu) + + +;;;; Customizations +;;;; ------------------------------------------------------------ + +(defgroup git nil + "A user interface for the git versioning system." + :group 'tools) + +(defcustom git-committer-name nil + "User name to use for commits. +The default is to fall back to the repository config, +then to `add-log-full-name' and then to `user-full-name'." + :group 'git + :type '(choice (const :tag "Default" nil) + (string :tag "Name"))) + +(defcustom git-committer-email nil + "Email address to use for commits. +The default is to fall back to the git repository config, +then to `add-log-mailing-address' and then to `user-mail-address'." + :group 'git + :type '(choice (const :tag "Default" nil) + (string :tag "Email"))) + +(defcustom git-commits-coding-system nil + "Default coding system for the log message of git commits." + :group 'git + :type '(choice (const :tag "From repository config" nil) + (coding-system))) + +(defcustom git-append-signed-off-by nil + "Whether to append a Signed-off-by line to the commit message before editing." + :group 'git + :type 'boolean) + +(defcustom git-reuse-status-buffer t + "Whether `git-status' should try to reuse an existing buffer +if there is already one that displays the same directory." + :group 'git + :type 'boolean) + +(defcustom git-per-dir-ignore-file ".gitignore" + "Name of the per-directory ignore file." + :group 'git + :type 'string) + +(defcustom git-show-uptodate nil + "Whether to display up-to-date files." + :group 'git + :type 'boolean) + +(defcustom git-show-ignored nil + "Whether to display ignored files." + :group 'git + :type 'boolean) + +(defcustom git-show-unknown t + "Whether to display unknown files." + :group 'git + :type 'boolean) + + +(defface git-status-face + '((((class color) (background light)) (:foreground "purple")) + (((class color) (background dark)) (:foreground "salmon"))) + "Git mode face used to highlight added and modified files." + :group 'git) + +(defface git-unmerged-face + '((((class color) (background light)) (:foreground "red" :bold t)) + (((class color) (background dark)) (:foreground "red" :bold t))) + "Git mode face used to highlight unmerged files." + :group 'git) + +(defface git-unknown-face + '((((class color) (background light)) (:foreground "goldenrod" :bold t)) + (((class color) (background dark)) (:foreground "goldenrod" :bold t))) + "Git mode face used to highlight unknown files." + :group 'git) + +(defface git-uptodate-face + '((((class color) (background light)) (:foreground "grey60")) + (((class color) (background dark)) (:foreground "grey40"))) + "Git mode face used to highlight up-to-date files." + :group 'git) + +(defface git-ignored-face + '((((class color) (background light)) (:foreground "grey60")) + (((class color) (background dark)) (:foreground "grey40"))) + "Git mode face used to highlight ignored files." + :group 'git) + +(defface git-mark-face + '((((class color) (background light)) (:foreground "red" :bold t)) + (((class color) (background dark)) (:foreground "tomato" :bold t))) + "Git mode face used for the file marks." + :group 'git) + +(defface git-header-face + '((((class color) (background light)) (:foreground "blue")) + (((class color) (background dark)) (:foreground "blue"))) + "Git mode face used for commit headers." + :group 'git) + +(defface git-separator-face + '((((class color) (background light)) (:foreground "brown")) + (((class color) (background dark)) (:foreground "brown"))) + "Git mode face used for commit separator." + :group 'git) + +(defface git-permission-face + '((((class color) (background light)) (:foreground "green" :bold t)) + (((class color) (background dark)) (:foreground "green" :bold t))) + "Git mode face used for permission changes." + :group 'git) + + +;;;; Utilities +;;;; ------------------------------------------------------------ + +(defconst git-log-msg-separator "--- log message follows this line ---") + +(defvar git-log-edit-font-lock-keywords + `(("^\\(Author:\\|Date:\\|Merge:\\|Signed-off-by:\\)\\(.*\\)$" + (1 font-lock-keyword-face) + (2 font-lock-function-name-face)) + (,(concat "^\\(" (regexp-quote git-log-msg-separator) "\\)$") + (1 font-lock-comment-face)))) + +(defun git-get-env-strings (env) + "Build a list of NAME=VALUE strings from a list of environment strings." + (mapcar (lambda (entry) (concat (car entry) "=" (cdr entry))) env)) + +(defun git-call-process (buffer &rest args) + "Wrapper for call-process that sets environment strings." + (apply #'call-process "git" nil buffer nil args)) + +(defun git-call-process-display-error (&rest args) + "Wrapper for call-process that displays error messages." + (let* ((dir default-directory) + (buffer (get-buffer-create "*Git Command Output*")) + (ok (with-current-buffer buffer + (let ((default-directory dir) + (buffer-read-only nil)) + (erase-buffer) + (eq 0 (apply #'git-call-process (list buffer t) args)))))) + (unless ok (display-message-or-buffer buffer)) + ok)) + +(defun git-call-process-string (&rest args) + "Wrapper for call-process that returns the process output as a string, +or nil if the git command failed." + (with-temp-buffer + (and (eq 0 (apply #'git-call-process t args)) + (buffer-string)))) + +(defun git-call-process-string-display-error (&rest args) + "Wrapper for call-process that displays error message and returns +the process output as a string, or nil if the git command failed." + (with-temp-buffer + (if (eq 0 (apply #'git-call-process (list t t) args)) + (buffer-string) + (display-message-or-buffer (current-buffer)) + nil))) + +(defun git-run-process-region (buffer start end program args) + "Run a git process with a buffer region as input." + (let ((output-buffer (current-buffer)) + (dir default-directory)) + (with-current-buffer buffer + (cd dir) + (apply #'call-process-region start end program + nil (list output-buffer t) nil args)))) + +(defun git-run-command-buffer (buffer-name &rest args) + "Run a git command, sending the output to a buffer named BUFFER-NAME." + (let ((dir default-directory) + (buffer (get-buffer-create buffer-name))) + (message "Running git %s..." (car args)) + (with-current-buffer buffer + (let ((default-directory dir) + (buffer-read-only nil)) + (erase-buffer) + (apply #'git-call-process buffer args))) + (message "Running git %s...done" (car args)) + buffer)) + +(defun git-run-command-region (buffer start end env &rest args) + "Run a git command with specified buffer region as input." + (with-temp-buffer + (if (eq 0 (if env + (git-run-process-region + buffer start end "env" + (append (git-get-env-strings env) (list "git") args)) + (git-run-process-region buffer start end "git" args))) + (buffer-string) + (display-message-or-buffer (current-buffer)) + nil))) + +(defun git-run-hook (hook env &rest args) + "Run a git hook and display its output if any." + (let ((dir default-directory) + (hook-name (expand-file-name (concat ".git/hooks/" hook)))) + (or (not (file-executable-p hook-name)) + (let (status (buffer (get-buffer-create "*Git Hook Output*"))) + (with-current-buffer buffer + (erase-buffer) + (cd dir) + (setq status + (if env + (apply #'call-process "env" nil (list buffer t) nil + (append (git-get-env-strings env) (list hook-name) args)) + (apply #'call-process hook-name nil (list buffer t) nil args)))) + (display-message-or-buffer buffer) + (eq 0 status))))) + +(defun git-get-string-sha1 (string) + "Read a SHA1 from the specified string." + (and string + (string-match "[0-9a-f]\\{40\\}" string) + (match-string 0 string))) + +(defun git-get-committer-name () + "Return the name to use as GIT_COMMITTER_NAME." + ; copied from log-edit + (or git-committer-name + (git-config "user.name") + (and (boundp 'add-log-full-name) add-log-full-name) + (and (fboundp 'user-full-name) (user-full-name)) + (and (boundp 'user-full-name) user-full-name))) + +(defun git-get-committer-email () + "Return the email address to use as GIT_COMMITTER_EMAIL." + ; copied from log-edit + (or git-committer-email + (git-config "user.email") + (and (boundp 'add-log-mailing-address) add-log-mailing-address) + (and (fboundp 'user-mail-address) (user-mail-address)) + (and (boundp 'user-mail-address) user-mail-address))) + +(defun git-get-commits-coding-system () + "Return the coding system to use for commits." + (let ((repo-config (git-config "i18n.commitencoding"))) + (or git-commits-coding-system + (and repo-config + (fboundp 'locale-charset-to-coding-system) + (locale-charset-to-coding-system repo-config)) + 'utf-8))) + +(defun git-get-logoutput-coding-system () + "Return the coding system used for git-log output." + (let ((repo-config (or (git-config "i18n.logoutputencoding") + (git-config "i18n.commitencoding")))) + (or git-commits-coding-system + (and repo-config + (fboundp 'locale-charset-to-coding-system) + (locale-charset-to-coding-system repo-config)) + 'utf-8))) + +(defun git-escape-file-name (name) + "Escape a file name if necessary." + (if (string-match "[\n\t\"\\]" name) + (concat "\"" + (mapconcat (lambda (c) + (case c + (?\n "\\n") + (?\t "\\t") + (?\\ "\\\\") + (?\" "\\\"") + (t (char-to-string c)))) + name "") + "\"") + name)) + +(defun git-success-message (text files) + "Print a success message after having handled FILES." + (let ((n (length files))) + (if (equal n 1) + (message "%s %s" text (car files)) + (message "%s %d files" text n)))) + +(defun git-get-top-dir (dir) + "Retrieve the top-level directory of a git tree." + (let ((cdup (with-output-to-string + (with-current-buffer standard-output + (cd dir) + (unless (eq 0 (git-call-process t "rev-parse" "--show-cdup")) + (error "cannot find top-level git tree for %s." dir)))))) + (expand-file-name (concat (file-name-as-directory dir) + (car (split-string cdup "\n")))))) + +;stolen from pcl-cvs +(defun git-append-to-ignore (file) + "Add a file name to the ignore file in its directory." + (let* ((fullname (expand-file-name file)) + (dir (file-name-directory fullname)) + (name (file-name-nondirectory fullname)) + (ignore-name (expand-file-name git-per-dir-ignore-file dir)) + (created (not (file-exists-p ignore-name)))) + (save-window-excursion + (set-buffer (find-file-noselect ignore-name)) + (goto-char (point-max)) + (unless (zerop (current-column)) (insert "\n")) + (insert "/" name "\n") + (sort-lines nil (point-min) (point-max)) + (save-buffer)) + (when created + (git-call-process nil "update-index" "--add" "--" (file-relative-name ignore-name))) + (git-update-status-files (list (file-relative-name ignore-name))))) + +; propertize definition for XEmacs, stolen from erc-compat +(eval-when-compile + (unless (fboundp 'propertize) + (defun propertize (string &rest props) + (let ((string (copy-sequence string))) + (while props + (put-text-property 0 (length string) (nth 0 props) (nth 1 props) string) + (setq props (cddr props))) + string)))) + +;;;; Wrappers for basic git commands +;;;; ------------------------------------------------------------ + +(defun git-rev-parse (rev) + "Parse a revision name and return its SHA1." + (git-get-string-sha1 + (git-call-process-string "rev-parse" rev))) + +(defun git-config (key) + "Retrieve the value associated to KEY in the git repository config file." + (let ((str (git-call-process-string "config" key))) + (and str (car (split-string str "\n"))))) + +(defun git-symbolic-ref (ref) + "Wrapper for the git-symbolic-ref command." + (let ((str (git-call-process-string "symbolic-ref" ref))) + (and str (car (split-string str "\n"))))) + +(defun git-update-ref (ref newval &optional oldval reason) + "Update a reference by calling git-update-ref." + (let ((args (and oldval (list oldval)))) + (when newval (push newval args)) + (push ref args) + (when reason + (push reason args) + (push "-m" args)) + (unless newval (push "-d" args)) + (apply 'git-call-process-display-error "update-ref" args))) + +(defun git-for-each-ref (&rest specs) + "Return a list of refs using git-for-each-ref. +Each entry is a cons of (SHORT-NAME . FULL-NAME)." + (let (refs) + (with-temp-buffer + (apply #'git-call-process t "for-each-ref" "--format=%(refname)" specs) + (goto-char (point-min)) + (while (re-search-forward "^[^/\n]+/[^/\n]+/\\(.+\\)$" nil t) + (push (cons (match-string 1) (match-string 0)) refs))) + (nreverse refs))) + +(defun git-read-tree (tree &optional index-file) + "Read a tree into the index file." + (let ((process-environment + (append (and index-file (list (concat "GIT_INDEX_FILE=" index-file))) process-environment))) + (apply 'git-call-process-display-error "read-tree" (if tree (list tree))))) + +(defun git-write-tree (&optional index-file) + "Call git-write-tree and return the resulting tree SHA1 as a string." + (let ((process-environment + (append (and index-file (list (concat "GIT_INDEX_FILE=" index-file))) process-environment))) + (git-get-string-sha1 + (git-call-process-string-display-error "write-tree")))) + +(defun git-commit-tree (buffer tree parent) + "Create a commit and possibly update HEAD. +Create a commit with the message in BUFFER using the tree with hash TREE. +Use PARENT as the parent of the new commit. If PARENT is the current \"HEAD\", +update the \"HEAD\" reference to the new commit." + (let ((author-name (git-get-committer-name)) + (author-email (git-get-committer-email)) + (subject "commit (initial): ") + author-date log-start log-end args coding-system-for-write) + (when parent + (setq subject "commit: ") + (push "-p" args) + (push parent args)) + (with-current-buffer buffer + (goto-char (point-min)) + (if + (setq log-start (re-search-forward (concat "^" (regexp-quote git-log-msg-separator) "\n") nil t)) + (save-restriction + (narrow-to-region (point-min) log-start) + (goto-char (point-min)) + (when (re-search-forward "^Author: +\\(.*?\\) *<\\(.*\\)> *$" nil t) + (setq author-name (match-string 1) + author-email (match-string 2))) + (goto-char (point-min)) + (when (re-search-forward "^Date: +\\(.*\\)$" nil t) + (setq author-date (match-string 1))) + (goto-char (point-min)) + (when (re-search-forward "^Merge: +\\(.*\\)" nil t) + (setq subject "commit (merge): ") + (dolist (parent (split-string (match-string 1) " +" t)) + (push "-p" args) + (push parent args)))) + (setq log-start (point-min))) + (setq log-end (point-max)) + (goto-char log-start) + (when (re-search-forward ".*$" nil t) + (setq subject (concat subject (match-string 0)))) + (setq coding-system-for-write buffer-file-coding-system)) + (let ((commit + (git-get-string-sha1 + (let ((env `(("GIT_AUTHOR_NAME" . ,author-name) + ("GIT_AUTHOR_EMAIL" . ,author-email) + ("GIT_COMMITTER_NAME" . ,(git-get-committer-name)) + ("GIT_COMMITTER_EMAIL" . ,(git-get-committer-email))))) + (when author-date (push `("GIT_AUTHOR_DATE" . ,author-date) env)) + (apply #'git-run-command-region + buffer log-start log-end env + "commit-tree" tree (nreverse args)))))) + (when commit (git-update-ref "HEAD" commit parent subject)) + commit))) + +(defun git-empty-db-p () + "Check if the git db is empty (no commit done yet)." + (not (eq 0 (git-call-process nil "rev-parse" "--verify" "HEAD")))) + +(defun git-get-merge-heads () + "Retrieve the merge heads from the MERGE_HEAD file if present." + (let (heads) + (when (file-readable-p ".git/MERGE_HEAD") + (with-temp-buffer + (insert-file-contents ".git/MERGE_HEAD" nil nil nil t) + (goto-char (point-min)) + (while (re-search-forward "[0-9a-f]\\{40\\}" nil t) + (push (match-string 0) heads)))) + (nreverse heads))) + +(defun git-get-commit-description (commit) + "Get a one-line description of COMMIT." + (let ((coding-system-for-read (git-get-logoutput-coding-system))) + (let ((descr (git-call-process-string "log" "--max-count=1" "--pretty=oneline" commit))) + (if (and descr (string-match "\\`\\([0-9a-f]\\{40\\}\\) *\\(.*\\)$" descr)) + (concat (substring (match-string 1 descr) 0 10) " - " (match-string 2 descr)) + descr)))) + +;;;; File info structure +;;;; ------------------------------------------------------------ + +; fileinfo structure stolen from pcl-cvs +(defstruct (git-fileinfo + (:copier nil) + (:constructor git-create-fileinfo (state name &optional old-perm new-perm rename-state orig-name marked)) + (:conc-name git-fileinfo->)) + marked ;; t/nil + state ;; current state + name ;; file name + old-perm new-perm ;; permission flags + rename-state ;; rename or copy state + orig-name ;; original name for renames or copies + needs-update ;; whether file needs to be updated + needs-refresh) ;; whether file needs to be refreshed + +(defvar git-status nil) + +(defun git-set-fileinfo-state (info state) + "Set the state of a file info." + (unless (eq (git-fileinfo->state info) state) + (setf (git-fileinfo->state info) state + (git-fileinfo->new-perm info) (git-fileinfo->old-perm info) + (git-fileinfo->rename-state info) nil + (git-fileinfo->orig-name info) nil + (git-fileinfo->needs-update info) nil + (git-fileinfo->needs-refresh info) t))) + +(defun git-status-filenames-map (status func files &rest args) + "Apply FUNC to the status files names in the FILES list. +The list must be sorted." + (when files + (let ((file (pop files)) + (node (ewoc-nth status 0))) + (while (and file node) + (let* ((info (ewoc-data node)) + (name (git-fileinfo->name info))) + (if (string-lessp name file) + (setq node (ewoc-next status node)) + (if (string-equal name file) + (apply func info args)) + (setq file (pop files)))))))) + +(defun git-set-filenames-state (status files state) + "Set the state of a list of named files. The list must be sorted" + (when files + (git-status-filenames-map status #'git-set-fileinfo-state files state) + (unless state ;; delete files whose state has been set to nil + (ewoc-filter status (lambda (info) (git-fileinfo->state info)))))) + +(defun git-state-code (code) + "Convert from a string to a added/deleted/modified state." + (case (string-to-char code) + (?M 'modified) + (?? 'unknown) + (?A 'added) + (?D 'deleted) + (?U 'unmerged) + (?T 'modified) + (t nil))) + +(defun git-status-code-as-string (code) + "Format a git status code as string." + (case code + ('modified (propertize "Modified" 'face 'git-status-face)) + ('unknown (propertize "Unknown " 'face 'git-unknown-face)) + ('added (propertize "Added " 'face 'git-status-face)) + ('deleted (propertize "Deleted " 'face 'git-status-face)) + ('unmerged (propertize "Unmerged" 'face 'git-unmerged-face)) + ('uptodate (propertize "Uptodate" 'face 'git-uptodate-face)) + ('ignored (propertize "Ignored " 'face 'git-ignored-face)) + (t "? "))) + +(defun git-file-type-as-string (old-perm new-perm) + "Return a string describing the file type based on its permissions." + (let* ((old-type (lsh (or old-perm 0) -9)) + (new-type (lsh (or new-perm 0) -9)) + (str (case new-type + (64 ;; file + (case old-type + (64 nil) + (80 " (type change symlink -> file)") + (112 " (type change subproject -> file)"))) + (80 ;; symlink + (case old-type + (64 " (type change file -> symlink)") + (112 " (type change subproject -> symlink)") + (t " (symlink)"))) + (112 ;; subproject + (case old-type + (64 " (type change file -> subproject)") + (80 " (type change symlink -> subproject)") + (t " (subproject)"))) + (72 nil) ;; directory (internal, not a real git state) + (0 ;; deleted or unknown + (case old-type + (80 " (symlink)") + (112 " (subproject)"))) + (t (format " (unknown type %o)" new-type))))) + (cond (str (propertize str 'face 'git-status-face)) + ((eq new-type 72) "/") + (t "")))) + +(defun git-rename-as-string (info) + "Return a string describing the copy or rename associated with INFO, or an empty string if none." + (let ((state (git-fileinfo->rename-state info))) + (if state + (propertize + (concat " (" + (if (eq state 'copy) "copied from " + (if (eq (git-fileinfo->state info) 'added) "renamed from " + "renamed to ")) + (git-escape-file-name (git-fileinfo->orig-name info)) + ")") 'face 'git-status-face) + ""))) + +(defun git-permissions-as-string (old-perm new-perm) + "Format a permission change as string." + (propertize + (if (or (not old-perm) + (not new-perm) + (eq 0 (logand ?\111 (logxor old-perm new-perm)))) + " " + (if (eq 0 (logand ?\111 old-perm)) "+x" "-x")) + 'face 'git-permission-face)) + +(defun git-fileinfo-prettyprint (info) + "Pretty-printer for the git-fileinfo structure." + (let ((old-perm (git-fileinfo->old-perm info)) + (new-perm (git-fileinfo->new-perm info))) + (insert (concat " " (if (git-fileinfo->marked info) (propertize "*" 'face 'git-mark-face) " ") + " " (git-status-code-as-string (git-fileinfo->state info)) + " " (git-permissions-as-string old-perm new-perm) + " " (git-escape-file-name (git-fileinfo->name info)) + (git-file-type-as-string old-perm new-perm) + (git-rename-as-string info))))) + +(defun git-update-node-fileinfo (node info) + "Update the fileinfo of the specified node. The names are assumed to match already." + (let ((data (ewoc-data node))) + (setf + ;; preserve the marked flag + (git-fileinfo->marked info) (git-fileinfo->marked data) + (git-fileinfo->needs-update data) nil) + (when (not (equal info data)) + (setf (git-fileinfo->needs-refresh info) t + (ewoc-data node) info)))) + +(defun git-insert-info-list (status infolist files) + "Insert a sorted list of file infos in the status buffer, replacing existing ones if any." + (let* ((info (pop infolist)) + (node (ewoc-nth status 0)) + (name (and info (git-fileinfo->name info))) + remaining) + (while info + (let ((nodename (and node (git-fileinfo->name (ewoc-data node))))) + (while (and files (string-lessp (car files) name)) + (push (pop files) remaining)) + (when (and files (string-equal (car files) name)) + (setq files (cdr files))) + (cond ((not nodename) + (setq node (ewoc-enter-last status info)) + (setq info (pop infolist)) + (setq name (and info (git-fileinfo->name info)))) + ((string-lessp nodename name) + (setq node (ewoc-next status node))) + ((string-equal nodename name) + ;; preserve the marked flag + (git-update-node-fileinfo node info) + (setq info (pop infolist)) + (setq name (and info (git-fileinfo->name info)))) + (t + (setq node (ewoc-enter-before status node info)) + (setq info (pop infolist)) + (setq name (and info (git-fileinfo->name info))))))) + (nconc (nreverse remaining) files))) + +(defun git-run-diff-index (status files) + "Run git-diff-index on FILES and parse the results into STATUS. +Return the list of files that haven't been handled." + (let (infolist) + (with-temp-buffer + (apply #'git-call-process t "diff-index" "-z" "-M" "HEAD" "--" files) + (goto-char (point-min)) + (while (re-search-forward + ":\\([0-7]\\{6\\}\\) \\([0-7]\\{6\\}\\) [0-9a-f]\\{40\\} [0-9a-f]\\{40\\} \\(\\([ADMUT]\\)\0\\([^\0]+\\)\\|\\([CR]\\)[0-9]*\0\\([^\0]+\\)\0\\([^\0]+\\)\\)\0" + nil t 1) + (let ((old-perm (string-to-number (match-string 1) 8)) + (new-perm (string-to-number (match-string 2) 8)) + (state (or (match-string 4) (match-string 6))) + (name (or (match-string 5) (match-string 7))) + (new-name (match-string 8))) + (if new-name ; copy or rename + (if (eq ?C (string-to-char state)) + (push (git-create-fileinfo 'added new-name old-perm new-perm 'copy name) infolist) + (push (git-create-fileinfo 'deleted name 0 0 'rename new-name) infolist) + (push (git-create-fileinfo 'added new-name old-perm new-perm 'rename name) infolist)) + (push (git-create-fileinfo (git-state-code state) name old-perm new-perm) infolist))))) + (setq infolist (sort (nreverse infolist) + (lambda (info1 info2) + (string-lessp (git-fileinfo->name info1) + (git-fileinfo->name info2))))) + (git-insert-info-list status infolist files))) + +(defun git-find-status-file (status file) + "Find a given file in the status ewoc and return its node." + (let ((node (ewoc-nth status 0))) + (while (and node (not (string= file (git-fileinfo->name (ewoc-data node))))) + (setq node (ewoc-next status node))) + node)) + +(defun git-run-ls-files (status files default-state &rest options) + "Run git-ls-files on FILES and parse the results into STATUS. +Return the list of files that haven't been handled." + (let (infolist) + (with-temp-buffer + (apply #'git-call-process t "ls-files" "-z" (append options (list "--") files)) + (goto-char (point-min)) + (while (re-search-forward "\\([^\0]*?\\)\\(/?\\)\0" nil t 1) + (let ((name (match-string 1))) + (push (git-create-fileinfo default-state name 0 + (if (string-equal "/" (match-string 2)) (lsh ?\110 9) 0)) + infolist)))) + (setq infolist (nreverse infolist)) ;; assume it is sorted already + (git-insert-info-list status infolist files))) + +(defun git-run-ls-files-cached (status files default-state) + "Run git-ls-files -c on FILES and parse the results into STATUS. +Return the list of files that haven't been handled." + (let (infolist) + (with-temp-buffer + (apply #'git-call-process t "ls-files" "-z" "-s" "-c" "--" files) + (goto-char (point-min)) + (while (re-search-forward "\\([0-7]\\{6\\}\\) [0-9a-f]\\{40\\} 0\t\\([^\0]+\\)\0" nil t) + (let* ((new-perm (string-to-number (match-string 1) 8)) + (old-perm (if (eq default-state 'added) 0 new-perm)) + (name (match-string 2))) + (push (git-create-fileinfo default-state name old-perm new-perm) infolist)))) + (setq infolist (nreverse infolist)) ;; assume it is sorted already + (git-insert-info-list status infolist files))) + +(defun git-run-ls-unmerged (status files) + "Run git-ls-files -u on FILES and parse the results into STATUS." + (with-temp-buffer + (apply #'git-call-process t "ls-files" "-z" "-u" "--" files) + (goto-char (point-min)) + (let (unmerged-files) + (while (re-search-forward "[0-7]\\{6\\} [0-9a-f]\\{40\\} [123]\t\\([^\0]+\\)\0" nil t) + (push (match-string 1) unmerged-files)) + (setq unmerged-files (nreverse unmerged-files)) ;; assume it is sorted already + (git-set-filenames-state status unmerged-files 'unmerged)))) + +(defun git-get-exclude-files () + "Get the list of exclude files to pass to git-ls-files." + (let (files + (config (git-config "core.excludesfile"))) + (when (file-readable-p ".git/info/exclude") + (push ".git/info/exclude" files)) + (when (and config (file-readable-p config)) + (push config files)) + files)) + +(defun git-run-ls-files-with-excludes (status files default-state &rest options) + "Run git-ls-files on FILES with appropriate --exclude-from options." + (let ((exclude-files (git-get-exclude-files))) + (apply #'git-run-ls-files status files default-state "--directory" "--no-empty-directory" + (concat "--exclude-per-directory=" git-per-dir-ignore-file) + (append options (mapcar (lambda (f) (concat "--exclude-from=" f)) exclude-files))))) + +(defun git-update-status-files (&optional files mark-files) + "Update the status of FILES from the index. +The FILES list must be sorted." + (unless git-status (error "Not in git-status buffer.")) + ;; set the needs-update flag on existing files + (if files + (git-status-filenames-map + git-status (lambda (info) (setf (git-fileinfo->needs-update info) t)) files) + (ewoc-map (lambda (info) (setf (git-fileinfo->needs-update info) t) nil) git-status) + (git-call-process nil "update-index" "--refresh") + (when git-show-uptodate + (git-run-ls-files-cached git-status nil 'uptodate))) + (let ((remaining-files + (if (git-empty-db-p) ; we need some special handling for an empty db + (git-run-ls-files-cached git-status files 'added) + (git-run-diff-index git-status files)))) + (git-run-ls-unmerged git-status files) + (when (or remaining-files (and git-show-unknown (not files))) + (setq remaining-files (git-run-ls-files-with-excludes git-status remaining-files 'unknown "-o"))) + (when (or remaining-files (and git-show-ignored (not files))) + (setq remaining-files (git-run-ls-files-with-excludes git-status remaining-files 'ignored "-o" "-i"))) + (unless files + (setq remaining-files (git-get-filenames (ewoc-collect git-status #'git-fileinfo->needs-update)))) + (when remaining-files + (setq remaining-files (git-run-ls-files-cached git-status remaining-files 'uptodate))) + (git-set-filenames-state git-status remaining-files nil) + (when mark-files (git-mark-files git-status files)) + (git-refresh-files) + (git-refresh-ewoc-hf git-status))) + +(defun git-mark-files (status files) + "Mark all the specified FILES, and unmark the others." + (let ((file (and files (pop files))) + (node (ewoc-nth status 0))) + (while node + (let ((info (ewoc-data node))) + (if (and file (string-equal (git-fileinfo->name info) file)) + (progn + (unless (git-fileinfo->marked info) + (setf (git-fileinfo->marked info) t) + (setf (git-fileinfo->needs-refresh info) t)) + (setq file (pop files)) + (setq node (ewoc-next status node))) + (when (git-fileinfo->marked info) + (setf (git-fileinfo->marked info) nil) + (setf (git-fileinfo->needs-refresh info) t)) + (if (and file (string-lessp file (git-fileinfo->name info))) + (setq file (pop files)) + (setq node (ewoc-next status node)))))))) + +(defun git-marked-files () + "Return a list of all marked files, or if none a list containing just the file at cursor position." + (unless git-status (error "Not in git-status buffer.")) + (or (ewoc-collect git-status (lambda (info) (git-fileinfo->marked info))) + (list (ewoc-data (ewoc-locate git-status))))) + +(defun git-marked-files-state (&rest states) + "Return a sorted list of marked files that are in the specified states." + (let ((files (git-marked-files)) + result) + (dolist (info files) + (when (memq (git-fileinfo->state info) states) + (push info result))) + (nreverse result))) + +(defun git-refresh-files () + "Refresh all files that need it and clear the needs-refresh flag." + (unless git-status (error "Not in git-status buffer.")) + (ewoc-map + (lambda (info) + (let ((refresh (git-fileinfo->needs-refresh info))) + (setf (git-fileinfo->needs-refresh info) nil) + refresh)) + git-status) + ; move back to goal column + (when goal-column (move-to-column goal-column))) + +(defun git-refresh-ewoc-hf (status) + "Refresh the ewoc header and footer." + (let ((branch (git-symbolic-ref "HEAD")) + (head (if (git-empty-db-p) "Nothing committed yet" + (git-get-commit-description "HEAD"))) + (merge-heads (git-get-merge-heads))) + (ewoc-set-hf status + (format "Directory: %s\nBranch: %s\nHead: %s%s\n" + default-directory + (if branch + (if (string-match "^refs/heads/" branch) + (substring branch (match-end 0)) + branch) + "none (detached HEAD)") + head + (if merge-heads + (concat "\nMerging: " + (mapconcat (lambda (str) (git-get-commit-description str)) merge-heads "\n ")) + "")) + (if (ewoc-nth status 0) "" " No changes.")))) + +(defun git-get-filenames (files) + (mapcar (lambda (info) (git-fileinfo->name info)) files)) + +(defun git-update-index (index-file files) + "Run git-update-index on a list of files." + (let ((process-environment (append (and index-file (list (concat "GIT_INDEX_FILE=" index-file))) + process-environment)) + added deleted modified) + (dolist (info files) + (case (git-fileinfo->state info) + ('added (push info added)) + ('deleted (push info deleted)) + ('modified (push info modified)))) + (and + (or (not added) (apply #'git-call-process-display-error "update-index" "--add" "--" (git-get-filenames added))) + (or (not deleted) (apply #'git-call-process-display-error "update-index" "--remove" "--" (git-get-filenames deleted))) + (or (not modified) (apply #'git-call-process-display-error "update-index" "--" (git-get-filenames modified)))))) + +(defun git-run-pre-commit-hook () + "Run the pre-commit hook if any." + (unless git-status (error "Not in git-status buffer.")) + (let ((files (git-marked-files-state 'added 'deleted 'modified))) + (or (not files) + (not (file-executable-p ".git/hooks/pre-commit")) + (let ((index-file (make-temp-file "gitidx"))) + (unwind-protect + (let ((head-tree (unless (git-empty-db-p) (git-rev-parse "HEAD^{tree}")))) + (git-read-tree head-tree index-file) + (git-update-index index-file files) + (git-run-hook "pre-commit" `(("GIT_INDEX_FILE" . ,index-file)))) + (delete-file index-file)))))) + +(defun git-do-commit () + "Perform the actual commit using the current buffer as log message." + (interactive) + (let ((buffer (current-buffer)) + (index-file (make-temp-file "gitidx"))) + (with-current-buffer log-edit-parent-buffer + (if (git-marked-files-state 'unmerged) + (message "You cannot commit unmerged files, resolve them first.") + (unwind-protect + (let ((files (git-marked-files-state 'added 'deleted 'modified)) + head tree head-tree) + (unless (git-empty-db-p) + (setq head (git-rev-parse "HEAD") + head-tree (git-rev-parse "HEAD^{tree}"))) + (message "Running git commit...") + (when + (and + (git-read-tree head-tree index-file) + (git-update-index nil files) ;update both the default index + (git-update-index index-file files) ;and the temporary one + (setq tree (git-write-tree index-file))) + (if (or (not (string-equal tree head-tree)) + (yes-or-no-p "The tree was not modified, do you really want to perform an empty commit? ")) + (let ((commit (git-commit-tree buffer tree head))) + (when commit + (condition-case nil (delete-file ".git/MERGE_HEAD") (error nil)) + (condition-case nil (delete-file ".git/MERGE_MSG") (error nil)) + (with-current-buffer buffer (erase-buffer)) + (git-update-status-files (git-get-filenames files)) + (git-call-process nil "rerere") + (git-call-process nil "gc" "--auto") + (message "Committed %s." commit) + (git-run-hook "post-commit" nil))) + (message "Commit aborted.")))) + (delete-file index-file)))))) + + +;;;; Interactive functions +;;;; ------------------------------------------------------------ + +(defun git-mark-file () + "Mark the file that the cursor is on and move to the next one." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (let* ((pos (ewoc-locate git-status)) + (info (ewoc-data pos))) + (setf (git-fileinfo->marked info) t) + (ewoc-invalidate git-status pos) + (ewoc-goto-next git-status 1))) + +(defun git-unmark-file () + "Unmark the file that the cursor is on and move to the next one." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (let* ((pos (ewoc-locate git-status)) + (info (ewoc-data pos))) + (setf (git-fileinfo->marked info) nil) + (ewoc-invalidate git-status pos) + (ewoc-goto-next git-status 1))) + +(defun git-unmark-file-up () + "Unmark the file that the cursor is on and move to the previous one." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (let* ((pos (ewoc-locate git-status)) + (info (ewoc-data pos))) + (setf (git-fileinfo->marked info) nil) + (ewoc-invalidate git-status pos) + (ewoc-goto-prev git-status 1))) + +(defun git-mark-all () + "Mark all files." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (ewoc-map (lambda (info) (unless (git-fileinfo->marked info) + (setf (git-fileinfo->marked info) t))) git-status) + ; move back to goal column after invalidate + (when goal-column (move-to-column goal-column))) + +(defun git-unmark-all () + "Unmark all files." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (ewoc-map (lambda (info) (when (git-fileinfo->marked info) + (setf (git-fileinfo->marked info) nil) + t)) git-status) + ; move back to goal column after invalidate + (when goal-column (move-to-column goal-column))) + +(defun git-toggle-all-marks () + "Toggle all file marks." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (ewoc-map (lambda (info) (setf (git-fileinfo->marked info) (not (git-fileinfo->marked info))) t) git-status) + ; move back to goal column after invalidate + (when goal-column (move-to-column goal-column))) + +(defun git-next-file (&optional n) + "Move the selection down N files." + (interactive "p") + (unless git-status (error "Not in git-status buffer.")) + (ewoc-goto-next git-status n)) + +(defun git-prev-file (&optional n) + "Move the selection up N files." + (interactive "p") + (unless git-status (error "Not in git-status buffer.")) + (ewoc-goto-prev git-status n)) + +(defun git-next-unmerged-file (&optional n) + "Move the selection down N unmerged files." + (interactive "p") + (unless git-status (error "Not in git-status buffer.")) + (let* ((last (ewoc-locate git-status)) + (node (ewoc-next git-status last))) + (while (and node (> n 0)) + (when (eq 'unmerged (git-fileinfo->state (ewoc-data node))) + (setq n (1- n)) + (setq last node)) + (setq node (ewoc-next git-status node))) + (ewoc-goto-node git-status last))) + +(defun git-prev-unmerged-file (&optional n) + "Move the selection up N unmerged files." + (interactive "p") + (unless git-status (error "Not in git-status buffer.")) + (let* ((last (ewoc-locate git-status)) + (node (ewoc-prev git-status last))) + (while (and node (> n 0)) + (when (eq 'unmerged (git-fileinfo->state (ewoc-data node))) + (setq n (1- n)) + (setq last node)) + (setq node (ewoc-prev git-status node))) + (ewoc-goto-node git-status last))) + +(defun git-insert-file (file) + "Insert file(s) into the git-status buffer." + (interactive "fInsert file: ") + (git-update-status-files (list (file-relative-name file)))) + +(defun git-add-file () + "Add marked file(s) to the index cache." + (interactive) + (let ((files (git-get-filenames (git-marked-files-state 'unknown 'ignored 'unmerged)))) + ;; FIXME: add support for directories + (unless files + (push (file-relative-name (read-file-name "File to add: " nil nil t)) files)) + (when (apply 'git-call-process-display-error "update-index" "--add" "--" files) + (git-update-status-files files) + (git-success-message "Added" files)))) + +(defun git-ignore-file () + "Add marked file(s) to the ignore list." + (interactive) + (let ((files (git-get-filenames (git-marked-files-state 'unknown)))) + (unless files + (push (file-relative-name (read-file-name "File to ignore: " nil nil t)) files)) + (dolist (f files) (git-append-to-ignore f)) + (git-update-status-files files) + (git-success-message "Ignored" files))) + +(defun git-remove-file () + "Remove the marked file(s)." + (interactive) + (let ((files (git-get-filenames (git-marked-files-state 'added 'modified 'unknown 'uptodate 'ignored)))) + (unless files + (push (file-relative-name (read-file-name "File to remove: " nil nil t)) files)) + (if (yes-or-no-p + (if (cdr files) + (format "Remove %d files? " (length files)) + (format "Remove %s? " (car files)))) + (progn + (dolist (name files) + (ignore-errors + (if (file-directory-p name) + (delete-directory name) + (delete-file name)))) + (when (apply 'git-call-process-display-error "update-index" "--remove" "--" files) + (git-update-status-files files) + (git-success-message "Removed" files))) + (message "Aborting")))) + +(defun git-revert-file () + "Revert changes to the marked file(s)." + (interactive) + (let ((files (git-marked-files-state 'added 'deleted 'modified 'unmerged)) + added modified) + (when (and files + (yes-or-no-p + (if (cdr files) + (format "Revert %d files? " (length files)) + (format "Revert %s? " (git-fileinfo->name (car files)))))) + (dolist (info files) + (case (git-fileinfo->state info) + ('added (push (git-fileinfo->name info) added)) + ('deleted (push (git-fileinfo->name info) modified)) + ('unmerged (push (git-fileinfo->name info) modified)) + ('modified (push (git-fileinfo->name info) modified)))) + ;; check if a buffer contains one of the files and isn't saved + (dolist (file modified) + (let ((buffer (get-file-buffer file))) + (when (and buffer (buffer-modified-p buffer)) + (error "Buffer %s is modified. Please kill or save modified buffers before reverting." (buffer-name buffer))))) + (let ((ok (and + (or (not added) + (apply 'git-call-process-display-error "update-index" "--force-remove" "--" added)) + (or (not modified) + (apply 'git-call-process-display-error "checkout" "HEAD" modified)))) + (names (git-get-filenames files))) + (git-update-status-files names) + (when ok + (dolist (file modified) + (let ((buffer (get-file-buffer file))) + (when buffer (with-current-buffer buffer (revert-buffer t t t))))) + (git-success-message "Reverted" names)))))) + +(defun git-remove-handled () + "Remove handled files from the status list." + (interactive) + (ewoc-filter git-status + (lambda (info) + (case (git-fileinfo->state info) + ('ignored git-show-ignored) + ('uptodate git-show-uptodate) + ('unknown git-show-unknown) + (t t)))) + (unless (ewoc-nth git-status 0) ; refresh header if list is empty + (git-refresh-ewoc-hf git-status))) + +(defun git-toggle-show-uptodate () + "Toogle the option for showing up-to-date files." + (interactive) + (if (setq git-show-uptodate (not git-show-uptodate)) + (git-refresh-status) + (git-remove-handled))) + +(defun git-toggle-show-ignored () + "Toogle the option for showing ignored files." + (interactive) + (if (setq git-show-ignored (not git-show-ignored)) + (progn + (message "Inserting ignored files...") + (git-run-ls-files-with-excludes git-status nil 'ignored "-o" "-i") + (git-refresh-files) + (git-refresh-ewoc-hf git-status) + (message "Inserting ignored files...done")) + (git-remove-handled))) + +(defun git-toggle-show-unknown () + "Toogle the option for showing unknown files." + (interactive) + (if (setq git-show-unknown (not git-show-unknown)) + (progn + (message "Inserting unknown files...") + (git-run-ls-files-with-excludes git-status nil 'unknown "-o") + (git-refresh-files) + (git-refresh-ewoc-hf git-status) + (message "Inserting unknown files...done")) + (git-remove-handled))) + +(defun git-expand-directory (info) + "Expand the directory represented by INFO to list its files." + (when (eq (lsh (git-fileinfo->new-perm info) -9) ?\110) + (let ((dir (git-fileinfo->name info))) + (git-set-filenames-state git-status (list dir) nil) + (git-run-ls-files-with-excludes git-status (list (concat dir "/")) 'unknown "-o") + (git-refresh-files) + (git-refresh-ewoc-hf git-status) + t))) + +(defun git-setup-diff-buffer (buffer) + "Setup a buffer for displaying a diff." + (let ((dir default-directory)) + (with-current-buffer buffer + (diff-mode) + (goto-char (point-min)) + (setq default-directory dir) + (setq buffer-read-only t))) + (display-buffer buffer) + ; shrink window only if it displays the status buffer + (when (eq (window-buffer) (current-buffer)) + (shrink-window-if-larger-than-buffer))) + +(defun git-diff-file () + "Diff the marked file(s) against HEAD." + (interactive) + (let ((files (git-marked-files))) + (git-setup-diff-buffer + (apply #'git-run-command-buffer "*git-diff*" "diff-index" "-p" "-M" "HEAD" "--" (git-get-filenames files))))) + +(defun git-diff-file-merge-head (arg) + "Diff the marked file(s) against the first merge head (or the nth one with a numeric prefix)." + (interactive "p") + (let ((files (git-marked-files)) + (merge-heads (git-get-merge-heads))) + (unless merge-heads (error "No merge in progress")) + (git-setup-diff-buffer + (apply #'git-run-command-buffer "*git-diff*" "diff-index" "-p" "-M" + (or (nth (1- arg) merge-heads) "HEAD") "--" (git-get-filenames files))))) + +(defun git-diff-unmerged-file (stage) + "Diff the marked unmerged file(s) against the specified stage." + (let ((files (git-marked-files))) + (git-setup-diff-buffer + (apply #'git-run-command-buffer "*git-diff*" "diff-files" "-p" stage "--" (git-get-filenames files))))) + +(defun git-diff-file-base () + "Diff the marked unmerged file(s) against the common base file." + (interactive) + (git-diff-unmerged-file "-1")) + +(defun git-diff-file-mine () + "Diff the marked unmerged file(s) against my pre-merge version." + (interactive) + (git-diff-unmerged-file "-2")) + +(defun git-diff-file-other () + "Diff the marked unmerged file(s) against the other's pre-merge version." + (interactive) + (git-diff-unmerged-file "-3")) + +(defun git-diff-file-combined () + "Do a combined diff of the marked unmerged file(s)." + (interactive) + (git-diff-unmerged-file "-c")) + +(defun git-diff-file-idiff () + "Perform an interactive diff on the current file." + (interactive) + (let ((files (git-marked-files-state 'added 'deleted 'modified))) + (unless (eq 1 (length files)) + (error "Cannot perform an interactive diff on multiple files.")) + (let* ((filename (car (git-get-filenames files))) + (buff1 (find-file-noselect filename)) + (buff2 (git-run-command-buffer (concat filename ".~HEAD~") "cat-file" "blob" (concat "HEAD:" filename)))) + (ediff-buffers buff1 buff2)))) + +(defun git-log-file () + "Display a log of changes to the marked file(s)." + (interactive) + (let* ((files (git-marked-files)) + (coding-system-for-read git-commits-coding-system) + (buffer (apply #'git-run-command-buffer "*git-log*" "rev-list" "--pretty" "HEAD" "--" (git-get-filenames files)))) + (with-current-buffer buffer + ; (git-log-mode) FIXME: implement log mode + (goto-char (point-min)) + (setq buffer-read-only t)) + (display-buffer buffer))) + +(defun git-log-edit-files () + "Return a list of marked files for use in the log-edit buffer." + (with-current-buffer log-edit-parent-buffer + (git-get-filenames (git-marked-files-state 'added 'deleted 'modified)))) + +(defun git-log-edit-diff () + "Run a diff of the current files being committed from a log-edit buffer." + (with-current-buffer log-edit-parent-buffer + (git-diff-file))) + +(defun git-append-sign-off (name email) + "Append a Signed-off-by entry to the current buffer, avoiding duplicates." + (let ((sign-off (format "Signed-off-by: %s <%s>" name email)) + (case-fold-search t)) + (goto-char (point-min)) + (unless (re-search-forward (concat "^" (regexp-quote sign-off)) nil t) + (goto-char (point-min)) + (unless (re-search-forward "^Signed-off-by: " nil t) + (setq sign-off (concat "\n" sign-off))) + (goto-char (point-max)) + (insert sign-off "\n")))) + +(defun git-setup-log-buffer (buffer &optional merge-heads author-name author-email subject date msg) + "Setup the log buffer for a commit." + (unless git-status (error "Not in git-status buffer.")) + (let ((dir default-directory) + (committer-name (git-get-committer-name)) + (committer-email (git-get-committer-email)) + (sign-off git-append-signed-off-by)) + (with-current-buffer buffer + (cd dir) + (erase-buffer) + (insert + (propertize + (format "Author: %s <%s>\n%s%s" + (or author-name committer-name) + (or author-email committer-email) + (if date (format "Date: %s\n" date) "") + (if merge-heads + (format "Merge: %s\n" + (mapconcat 'identity merge-heads " ")) + "")) + 'face 'git-header-face) + (propertize git-log-msg-separator 'face 'git-separator-face) + "\n") + (when subject (insert subject "\n\n")) + (cond (msg (insert msg "\n")) + ((file-readable-p ".git/rebase-apply/msg") + (insert-file-contents ".git/rebase-apply/msg")) + ((file-readable-p ".git/MERGE_MSG") + (insert-file-contents ".git/MERGE_MSG"))) + ; delete empty lines at end + (goto-char (point-min)) + (when (re-search-forward "\n+\\'" nil t) + (replace-match "\n" t t)) + (when sign-off (git-append-sign-off committer-name committer-email))) + buffer)) + +(defun git-commit-file () + "Commit the marked file(s), asking for a commit message." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (when (git-run-pre-commit-hook) + (let ((buffer (get-buffer-create "*git-commit*")) + (coding-system (git-get-commits-coding-system)) + author-name author-email subject date) + (when (eq 0 (buffer-size buffer)) + (when (file-readable-p ".git/rebase-apply/info") + (with-temp-buffer + (insert-file-contents ".git/rebase-apply/info") + (goto-char (point-min)) + (when (re-search-forward "^Author: \\(.*\\)\nEmail: \\(.*\\)$" nil t) + (setq author-name (match-string 1)) + (setq author-email (match-string 2))) + (goto-char (point-min)) + (when (re-search-forward "^Subject: \\(.*\\)$" nil t) + (setq subject (match-string 1))) + (goto-char (point-min)) + (when (re-search-forward "^Date: \\(.*\\)$" nil t) + (setq date (match-string 1))))) + (git-setup-log-buffer buffer (git-get-merge-heads) author-name author-email subject date)) + (if (boundp 'log-edit-diff-function) + (log-edit 'git-do-commit nil '((log-edit-listfun . git-log-edit-files) + (log-edit-diff-function . git-log-edit-diff)) buffer) + (log-edit 'git-do-commit nil 'git-log-edit-files buffer)) + (setq font-lock-keywords (font-lock-compile-keywords git-log-edit-font-lock-keywords)) + (setq paragraph-separate (concat (regexp-quote git-log-msg-separator) "$\\|Author: \\|Date: \\|Merge: \\|Signed-off-by: \\|\f\\|[ ]*$")) + (setq buffer-file-coding-system coding-system) + (re-search-forward (regexp-quote (concat git-log-msg-separator "\n")) nil t)))) + +(defun git-setup-commit-buffer (commit) + "Setup the commit buffer with the contents of COMMIT." + (let (parents author-name author-email subject date msg) + (with-temp-buffer + (let ((coding-system (git-get-logoutput-coding-system))) + (git-call-process t "log" "-1" "--pretty=medium" "--abbrev=40" commit) + (goto-char (point-min)) + (when (re-search-forward "^Merge: *\\(.*\\)$" nil t) + (setq parents (cdr (split-string (match-string 1) " +")))) + (when (re-search-forward "^Author: *\\(.*\\) <\\(.*\\)>$" nil t) + (setq author-name (match-string 1)) + (setq author-email (match-string 2))) + (when (re-search-forward "^Date: *\\(.*\\)$" nil t) + (setq date (match-string 1))) + (while (re-search-forward "^ \\(.*\\)$" nil t) + (push (match-string 1) msg)) + (setq msg (nreverse msg)) + (setq subject (pop msg)) + (while (and msg (zerop (length (car msg))) (pop msg))))) + (git-setup-log-buffer (get-buffer-create "*git-commit*") + parents author-name author-email subject date + (mapconcat #'identity msg "\n")))) + +(defun git-get-commit-files (commit) + "Retrieve a sorted list of files modified by COMMIT." + (let (files) + (with-temp-buffer + (git-call-process t "diff-tree" "-m" "-r" "-z" "--name-only" "--no-commit-id" "--root" commit) + (goto-char (point-min)) + (while (re-search-forward "\\([^\0]*\\)\0" nil t 1) + (push (match-string 1) files))) + (sort files #'string-lessp))) + +(defun git-read-commit-name (prompt &optional default) + "Ask for a commit name, with completion for local branch, remote branch and tag." + (completing-read prompt + (list* "HEAD" "ORIG_HEAD" "FETCH_HEAD" (mapcar #'car (git-for-each-ref))) + nil nil nil nil default)) + +(defun git-checkout (branch &optional merge) + "Checkout a branch, tag, or any commit. +Use a prefix arg if git should merge while checking out." + (interactive + (list (git-read-commit-name "Checkout: ") + current-prefix-arg)) + (unless git-status (error "Not in git-status buffer.")) + (let ((args (list branch "--"))) + (when merge (push "-m" args)) + (when (apply #'git-call-process-display-error "checkout" args) + (git-update-status-files)))) + +(defun git-branch (branch) + "Create a branch from the current HEAD and switch to it." + (interactive (list (git-read-commit-name "Branch: "))) + (unless git-status (error "Not in git-status buffer.")) + (if (git-rev-parse (concat "refs/heads/" branch)) + (if (yes-or-no-p (format "Branch %s already exists, replace it? " branch)) + (and (git-call-process-display-error "branch" "-f" branch) + (git-call-process-display-error "checkout" branch)) + (message "Canceled.")) + (git-call-process-display-error "checkout" "-b" branch)) + (git-refresh-ewoc-hf git-status)) + +(defun git-amend-commit () + "Undo the last commit on HEAD, and set things up to commit an +amended version of it." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (when (git-empty-db-p) (error "No commit to amend.")) + (let* ((commit (git-rev-parse "HEAD")) + (files (git-get-commit-files commit))) + (when (if (git-rev-parse "HEAD^") + (git-call-process-display-error "reset" "--soft" "HEAD^") + (and (git-update-ref "ORIG_HEAD" commit) + (git-update-ref "HEAD" nil commit))) + (git-update-status-files files t) + (git-setup-commit-buffer commit) + (git-commit-file)))) + +(defun git-cherry-pick-commit (arg) + "Cherry-pick a commit." + (interactive (list (git-read-commit-name "Cherry-pick commit: "))) + (unless git-status (error "Not in git-status buffer.")) + (let ((commit (git-rev-parse (concat arg "^0")))) + (unless commit (error "Not a valid commit '%s'." arg)) + (when (git-rev-parse (concat commit "^2")) + (error "Cannot cherry-pick a merge commit.")) + (let ((files (git-get-commit-files commit)) + (ok (git-call-process-display-error "cherry-pick" "-n" commit))) + (git-update-status-files files ok) + (with-current-buffer (git-setup-commit-buffer commit) + (goto-char (point-min)) + (if (re-search-forward "^\n*Signed-off-by:" nil t 1) + (goto-char (match-beginning 0)) + (goto-char (point-max))) + (insert "(cherry picked from commit " commit ")\n")) + (when ok (git-commit-file))))) + +(defun git-revert-commit (arg) + "Revert a commit." + (interactive (list (git-read-commit-name "Revert commit: "))) + (unless git-status (error "Not in git-status buffer.")) + (let ((commit (git-rev-parse (concat arg "^0")))) + (unless commit (error "Not a valid commit '%s'." arg)) + (when (git-rev-parse (concat commit "^2")) + (error "Cannot revert a merge commit.")) + (let ((files (git-get-commit-files commit)) + (subject (git-get-commit-description commit)) + (ok (git-call-process-display-error "revert" "-n" commit))) + (git-update-status-files files ok) + (when (string-match "^[0-9a-f]+ - \\(.*\\)$" subject) + (setq subject (match-string 1 subject))) + (git-setup-log-buffer (get-buffer-create "*git-commit*") + (git-get-merge-heads) nil nil (format "Revert \"%s\"" subject) nil + (format "This reverts commit %s.\n" commit)) + (when ok (git-commit-file))))) + +(defun git-find-file () + "Visit the current file in its own buffer." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (let ((info (ewoc-data (ewoc-locate git-status)))) + (unless (git-expand-directory info) + (find-file (git-fileinfo->name info)) + (when (eq 'unmerged (git-fileinfo->state info)) + (smerge-mode 1))))) + +(defun git-find-file-other-window () + "Visit the current file in its own buffer in another window." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (let ((info (ewoc-data (ewoc-locate git-status)))) + (find-file-other-window (git-fileinfo->name info)) + (when (eq 'unmerged (git-fileinfo->state info)) + (smerge-mode)))) + +(defun git-find-file-imerge () + "Visit the current file in interactive merge mode." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (let ((info (ewoc-data (ewoc-locate git-status)))) + (find-file (git-fileinfo->name info)) + (smerge-ediff))) + +(defun git-view-file () + "View the current file in its own buffer." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (let ((info (ewoc-data (ewoc-locate git-status)))) + (view-file (git-fileinfo->name info)))) + +(defun git-refresh-status () + "Refresh the git status buffer." + (interactive) + (unless git-status (error "Not in git-status buffer.")) + (message "Refreshing git status...") + (git-update-status-files) + (message "Refreshing git status...done")) + +(defun git-status-quit () + "Quit git-status mode." + (interactive) + (bury-buffer)) + +;;;; Major Mode +;;;; ------------------------------------------------------------ + +(defvar git-status-mode-hook nil + "Run after `git-status-mode' is setup.") + +(defvar git-status-mode-map nil + "Keymap for git major mode.") + +(defvar git-status nil + "List of all files managed by the git-status mode.") + +(unless git-status-mode-map + (let ((map (make-keymap)) + (commit-map (make-sparse-keymap)) + (diff-map (make-sparse-keymap)) + (toggle-map (make-sparse-keymap))) + (suppress-keymap map) + (define-key map "?" 'git-help) + (define-key map "h" 'git-help) + (define-key map " " 'git-next-file) + (define-key map "a" 'git-add-file) + (define-key map "c" 'git-commit-file) + (define-key map "\C-c" commit-map) + (define-key map "d" diff-map) + (define-key map "=" 'git-diff-file) + (define-key map "f" 'git-find-file) + (define-key map "\r" 'git-find-file) + (define-key map "g" 'git-refresh-status) + (define-key map "i" 'git-ignore-file) + (define-key map "I" 'git-insert-file) + (define-key map "l" 'git-log-file) + (define-key map "m" 'git-mark-file) + (define-key map "M" 'git-mark-all) + (define-key map "n" 'git-next-file) + (define-key map "N" 'git-next-unmerged-file) + (define-key map "o" 'git-find-file-other-window) + (define-key map "p" 'git-prev-file) + (define-key map "P" 'git-prev-unmerged-file) + (define-key map "q" 'git-status-quit) + (define-key map "r" 'git-remove-file) + (define-key map "t" toggle-map) + (define-key map "T" 'git-toggle-all-marks) + (define-key map "u" 'git-unmark-file) + (define-key map "U" 'git-revert-file) + (define-key map "v" 'git-view-file) + (define-key map "x" 'git-remove-handled) + (define-key map "\C-?" 'git-unmark-file-up) + (define-key map "\M-\C-?" 'git-unmark-all) + ; the commit submap + (define-key commit-map "\C-a" 'git-amend-commit) + (define-key commit-map "\C-b" 'git-branch) + (define-key commit-map "\C-o" 'git-checkout) + (define-key commit-map "\C-p" 'git-cherry-pick-commit) + (define-key commit-map "\C-v" 'git-revert-commit) + ; the diff submap + (define-key diff-map "b" 'git-diff-file-base) + (define-key diff-map "c" 'git-diff-file-combined) + (define-key diff-map "=" 'git-diff-file) + (define-key diff-map "e" 'git-diff-file-idiff) + (define-key diff-map "E" 'git-find-file-imerge) + (define-key diff-map "h" 'git-diff-file-merge-head) + (define-key diff-map "m" 'git-diff-file-mine) + (define-key diff-map "o" 'git-diff-file-other) + ; the toggle submap + (define-key toggle-map "u" 'git-toggle-show-uptodate) + (define-key toggle-map "i" 'git-toggle-show-ignored) + (define-key toggle-map "k" 'git-toggle-show-unknown) + (define-key toggle-map "m" 'git-toggle-all-marks) + (setq git-status-mode-map map)) + (easy-menu-define git-menu git-status-mode-map + "Git Menu" + `("Git" + ["Refresh" git-refresh-status t] + ["Commit" git-commit-file t] + ["Checkout..." git-checkout t] + ["New Branch..." git-branch t] + ["Cherry-pick Commit..." git-cherry-pick-commit t] + ["Revert Commit..." git-revert-commit t] + ("Merge" + ["Next Unmerged File" git-next-unmerged-file t] + ["Prev Unmerged File" git-prev-unmerged-file t] + ["Interactive Merge File" git-find-file-imerge t] + ["Diff Against Common Base File" git-diff-file-base t] + ["Diff Combined" git-diff-file-combined t] + ["Diff Against Merge Head" git-diff-file-merge-head t] + ["Diff Against Mine" git-diff-file-mine t] + ["Diff Against Other" git-diff-file-other t]) + "--------" + ["Add File" git-add-file t] + ["Revert File" git-revert-file t] + ["Ignore File" git-ignore-file t] + ["Remove File" git-remove-file t] + ["Insert File" git-insert-file t] + "--------" + ["Find File" git-find-file t] + ["View File" git-view-file t] + ["Diff File" git-diff-file t] + ["Interactive Diff File" git-diff-file-idiff t] + ["Log" git-log-file t] + "--------" + ["Mark" git-mark-file t] + ["Mark All" git-mark-all t] + ["Unmark" git-unmark-file t] + ["Unmark All" git-unmark-all t] + ["Toggle All Marks" git-toggle-all-marks t] + ["Hide Handled Files" git-remove-handled t] + "--------" + ["Show Uptodate Files" git-toggle-show-uptodate :style toggle :selected git-show-uptodate] + ["Show Ignored Files" git-toggle-show-ignored :style toggle :selected git-show-ignored] + ["Show Unknown Files" git-toggle-show-unknown :style toggle :selected git-show-unknown] + "--------" + ["Quit" git-status-quit t]))) + + +;; git mode should only run in the *git status* buffer +(put 'git-status-mode 'mode-class 'special) + +(defun git-status-mode () + "Major mode for interacting with Git. +Commands: +\\{git-status-mode-map}" + (kill-all-local-variables) + (buffer-disable-undo) + (setq mode-name "git status" + major-mode 'git-status-mode + goal-column 17 + buffer-read-only t) + (use-local-map git-status-mode-map) + (let ((buffer-read-only nil)) + (erase-buffer) + (let ((status (ewoc-create 'git-fileinfo-prettyprint "" ""))) + (set (make-local-variable 'git-status) status)) + (set (make-local-variable 'list-buffers-directory) default-directory) + (make-local-variable 'git-show-uptodate) + (make-local-variable 'git-show-ignored) + (make-local-variable 'git-show-unknown) + (run-hooks 'git-status-mode-hook))) + +(defun git-find-status-buffer (dir) + "Find the git status buffer handling a specified directory." + (let ((list (buffer-list)) + (fulldir (expand-file-name dir)) + found) + (while (and list (not found)) + (let ((buffer (car list))) + (with-current-buffer buffer + (when (and list-buffers-directory + (string-equal fulldir (expand-file-name list-buffers-directory)) + (eq major-mode 'git-status-mode)) + (setq found buffer)))) + (setq list (cdr list))) + found)) + +(defun git-status (dir) + "Entry point into git-status mode." + (interactive "DSelect directory: ") + (setq dir (git-get-top-dir dir)) + (if (file-directory-p (concat (file-name-as-directory dir) ".git")) + (let ((buffer (or (and git-reuse-status-buffer (git-find-status-buffer dir)) + (create-file-buffer (expand-file-name "*git-status*" dir))))) + (switch-to-buffer buffer) + (cd dir) + (git-status-mode) + (git-refresh-status) + (goto-char (point-min)) + (add-hook 'after-save-hook 'git-update-saved-file)) + (message "%s is not a git working tree." dir))) + +(defun git-update-saved-file () + "Update the corresponding git-status buffer when a file is saved. +Meant to be used in `after-save-hook'." + (let* ((file (expand-file-name buffer-file-name)) + (dir (condition-case nil (git-get-top-dir (file-name-directory file)) (error nil))) + (buffer (and dir (git-find-status-buffer dir)))) + (when buffer + (with-current-buffer buffer + (let ((filename (file-relative-name file dir))) + ; skip files located inside the .git directory + (unless (string-match "^\\.git/" filename) + (git-call-process nil "add" "--refresh" "--" filename) + (git-update-status-files (list filename)))))))) + +(defun git-help () + "Display help for Git mode." + (interactive) + (describe-function 'git-status-mode)) + +(provide 'git) +;;; git.el ends here diff --git a/editor/emacs/emacs/files/pisi-spec.rnc b/editor/emacs/emacs/files/pisi-spec.rnc new file mode 100644 index 0000000000..90ffe9e105 --- /dev/null +++ b/editor/emacs/emacs/files/pisi-spec.rnc @@ -0,0 +1,1071 @@ +namespace local = "" +namespace inh = inherit + +start = PISI + +PISI = element PISI { Source, Package+, History } + +Source = + element Source + { + Name, + Homepage, + Packager, + License+, + Icon?, + IsA*, + PartOf?, + Summary+, + Description*, + Archive, + BuildDependencies?, + Patches? + } + +Package = + element Package + { + Name, + License?, + IsA*, + PartOf?, + Summary*, + Description*, + RuntimeDependencies?, + Conflicts?, + Replaces?, + Files, + AdditionalFiles?, + Provides? + } + +History = element History { Update+ } + +Name = + element Name + { + xsd:string { pattern = "[0-9a-zA-Z\-_+]*" maxLength = "255" } + } + +Homepage = element Homepage { text } + +Icon = element Icon { text } + +Packager = element Packager { Packager.Name, Email } + +Packager.Name = element Name { xsd:string { maxLength = "255" } } + +Email = element Email { text } + +License = + element License + { + "3DFX" + | "3proxy" + | "3ware" + | "4F" + | "7plus" + | "9wm" + | "ACME" + | "ACML" + | "AECA" + | "AFL-2.0" + | "AFL-2.1" + | "AFL-3.0" + | "AFTERSTEP" + | "AGREP" + | "AICCU" + | "ALMWorks-1.2" + | "AMD" + | "AMPAS" + | "AMS" + | "ANTLR" + | "APL-1.0" + | "APSL-2" + | "ATI" + | "ATOK" + | "ATT" + | "AURA" + | "Adaptec" + | "Adobe" + | "Adobe-SourceCode" + | "AdobeFlash-9.0.31.0" + | "Aladdin" + | "Allegro" + | "Apache-1.1" + | "Apache-2.0" + | "Apple" + | "Arkkra" + | "Army-EULA" + | "Arphic" + | "Artistic" + | "Artistic-2" + | "Atmel" + | "AvP" + | "BAEKMUK" + | "BCS" + | "BEER-WARE" + | "BL" + | "BSD" + | "BSD-2" + | "BWidget" + | "BZIP2" + | "Babylon" + | "BitTorrent" + | "BitstreamVera" + | "Blitz-Artistic" + | "Boost-1.0" + | "C3" + | "CAOSL" + | "CAPS" + | "CAVER" + | "CCPL-Attribution-2.0" + | "CCPL-Attribution-3.0" + | "CCPL-Attribution-NonCommercial-NoDerivs-2.0" + | "CCPL-Attribution-NonCommercial-NoDerivs-2.5" + | "CCPL-Attribution-ShareAlike-2.0" + | "CCPL-Attribution-ShareAlike-2.5" + | "CCPL-Attribution-ShareAlike-3.0" + | "CCPL-Attribution-ShareAlike-NonCommercial-2.5" + | "CCPL-ShareAlike-1.0" + | "CDDL" + | "CDDL-Schily" + | "CDF" + | "CGL" + | "CMASS-M3" + | "CMake" + | "CNRI" + | "CNRI-QUIXOTE-2.4" + | "CPL-0.5" + | "CPL-1.0" + | "CRACKLIB" + | "CROSSOVER" + | "CS-1.0" + | "Caldera" + | "CeCILL-2" + | "Cenon" + | "Ciphire" + | "Clarified-Artistic" + | "Conexant" + | "Conexant-firmware" + | "CyberNeko-1.0" + | "D1X" + | "DB" + | "DCC" + | "DEC-M3" + | "DES" + | "DMD" + | "DNS2GO" + | "DOOM3" + | "DSL" + | "DSNIFF" + | "DUMB-0.9.2" + | "EAPL" + | "ECWPL" + | "EDB" + | "EPL" + | "EPL-1.0" + | "EPSON" + | "ETQW" + | "ElementTree" + | "Elm" + | "Emacs" + | "Exolab" + | "F-PROT" + | "FDL-1.1" + | "FDL-1.2" + | "FESTIVAL" + | "FIPL-1.0" + | "FLEX" + | "FLTK" + | "FML-1" + | "FTL" + | "FVWM" + | "FastCGI" + | "FreeArt" + | "Frodo" + | "GAlib" + | "GDLS" + | "GLX" + | "GMGPL" + | "GPLv1" + | "GPLv2" + | "GPLv2+" + | "GPLv2-with-MySQL-FLOSS-exception" + | "GPLv2-with-exceptions" + | "GPLv2-with-linking-exception" + | "GPLv3" + | "GPLv3+" + | "HBRL" + | "HKSCS" + | "HPL" + | "HYDRA" + | "Hauppauge-Firmware" + | "HyperSpec" + | "IBM" + | "IBM-ILNWP" + | "IBM-J1.4" + | "IBM-J1.5" + | "IBM-J1.6" + | "ICE" + | "IPL-1" + | "IRPDL" + | "ISC" + | "ITS4" + | "Info-ZIP" + | "Inform" + | "Intel" + | "Intel-SDP" + | "Interbase-1.0" + | "Introversion" + | "JDOM" + | "JNIC" + | "JPython" + | "JamesClark" + | "JasPer" + | "KQEMU" + | "KenMacLeod" + | "Kermit" + | "LDP" + | "LDP-1a" + | "LFS" + | "LGPLv2" + | "LGPLv2+" + | "LGPLv2.1" + | "LGPLv2.1-FPC" + | "LGPLv2.1-UUST" + | "LGPLv2.1-linking-exception" + | "LGPLv3" + | "LGPLv3+" + | "LIBGLOSS" + | "LICENSE-BITSTREAM" + | "LLGPL-2.1" + | "LOKI-EULA" + | "LPPL-1.2" + | "LPPL-1.3" + | "LPPL-1.3b" + | "LPPL-1.3c" + | "LRCTF" + | "MARBLEBLAST" + | "MBROLA" + | "MILO" + | "MIT" + | "MOTIF" + | "MPEG4" + | "MPL-1.0" + | "MPL-1.1" + | "MSF-1.2" + | "MSjdbcEULA" + | "MSttfEULA" + | "Macromedia" + | "MakeIndex" + | "Memonix" + | "MonetDBPL-1.1" + | "Moria" + | "Mozart" + | "NCSA-HDF" + | "NEWLIB" + | "NPL-1.1" + | "NVIDIA" + | "NWL" + | "NWN-EULA" + | "Nero" + | "Nessus-EULA" + | "NewArtisans" + | "No-Problem-Bugroff" + | "Norvig" + | "OFL" + | "OFL-1.1" + | "OGL-1.0a" + | "OGTSL" + | "OPENLDAP" + | "OPERA-9.0" + | "OPL" + | "ORIONSERVER" + | "OSI-Approved" + | "OSIRIS" + | "OSL-1.1" + | "OSL-2.0" + | "OTN" + | "Omni" + | "OpenSoftware" + | "OpenSymphony-1.1" + | "OracleDB" + | "PAM" + | "PBZIP2" + | "PDB" + | "PDFLite" + | "PEL" + | "PHP" + | "PHP-2.02" + | "PHP-3" + | "PHP-3.01" + | "PICO" + | "PLAN9" + | "PLDSPv2" + | "POMPOM" + | "POSTGRESQL" + | "PSF-2.2" + | "PSF-2.3" + | "PSF-2.4" + | "PSTT" + | "PUEL" + | "PYTHON" + | "Palm-SDK" + | "Panda3D" + | "Pando-EULA" + | "Parallels" + | "PathfinderPL-1.1" + | "PicoContainer" + | "PoseidonCommon.pdf" + | "Princeton" + | "Q2EULA" + | "Q3AEULA" + | "QPL" + | "QPL-1.0" + | "QUAKE4" + | "RAR" + | "RDist" + | "REALbasic" + | "RSA-MD2" + | "RSA-MD4" + | "RSA-MD5" + | "RSA-PKCS11" + | "RTCW" + | "RTCW-ETEULA" + | "Racer" + | "Resounding" + | "RiceBSD" + | "Roadrunner" + | "Ruby" + | "SGI-B" + | "SGI-B-1.1" + | "SGMLUG" + | "SIFT" + | "SIL-freeware" + | "SNNS-4.2" + | "SOPLA-2.3" + | "SPL" + | "SVFL" + | "Scintilla" + | "Sendmail" + | "Sendmail-Open-Source" + | "SixXS" + | "Sleepycat" + | "Smart-Link" + | "SpeedTouch-USB-Firmware" + | "Spice-1.1" + | "Spread-1.0" + | "Stanford" + | "Stuffit" + | "Subversion" + | "Sudo" + | "THINKTANKS" + | "TeX" + | "Tinker" + | "UCAR-Unidata" + | "UCL" + | "VGBA" + | "VIGRA" + | "VOSTROM" + | "VPL-1.0" + | "ValveSDK" + | "ValveServer" + | "Volano" + | "W3C" + | "W3C-document" + | "WANPIPE" + | "WRI-EULA" + | "WTFPL-2" + | "WarpPipe" + | "WebMO" + | "Werken-1.1.1.1" + | "WordNet-1.6" + | "X11" + | "XAnim" + | "XCIN" + | "Xdebug" + | "XeTeX" + | "Ximian-logos" + | "YAZ" + | "ZBL" + | "ZLIB" + | "ZORK" + | "ZPL" + | "ZSH" + | "ZendFramework-1.1" + | "aczoom" + | "adobe-ps" + | "adom" + | "aewm" + | "amiwm" + | "anubis" + | "appres" + | "aquafont" + | "arj" + | "as-is" + | "astrolog" + | "astromenace" + | "atheros-hal" + | "bakoma" + | "bass" + | "bdftopcf" + | "bea.ri.jsr173" + | "beforelight" + | "bestcrypt" + | "bigreqsproto" + | "bioapi" + | "bitmap" + | "blackshades" + | "bonnie" + | "bungie-marathon" + | "cadsoft" + | "canada-med" + | "ccc-beta" + | "ccp4" + | "cdegroot" + | "cedega" + | "charm" + | "chasen" + | "chntpw" + | "circlemud" + | "cisco" + | "cisco-vpn-client" + | "clibpdf" + | "clustalw" + | "cmigemo" + | "cns" + | "codehaus-classworlds" + | "codehaus-groovy" + | "colt" + | "compaq-sdla" + | "compositeproto" + | "cos" + | "crafty" + | "crazney" + | "cryptopp" + | "damageproto" + | "dbgphp" + | "descent2-data" + | "dgen-sdl" + | "distributed.net" + | "dlj-1.1" + | "dmxproto" + | "dom4j" + | "dvibook" + | "eGenixPublic" + | "eGenixPublic-1.1" + | "editres" + | "egressor" + | "encodings" + | "eternal_lands" + | "evieext" + | "fixesproto" + | "fmod" + | "folding-at-home" + | "font-adobe-100dpi" + | "font-adobe-75dpi" + | "font-adobe-utopia-100dpi" + | "font-adobe-utopia-75dpi" + | "font-adobe-utopia-type1" + | "font-alias" + | "font-arabic-misc" + | "font-bh-100dpi" + | "font-bh-75dpi" + | "font-bh-lucidatypewriter-100dpi" + | "font-bh-lucidatypewriter-75dpi" + | "font-bh-ttf" + | "font-bh-type1" + | "font-bitstream-100dpi" + | "font-bitstream-75dpi" + | "font-bitstream-speedo" + | "font-bitstream-type1" + | "font-cronyx-cyrillic" + | "font-cursor-misc" + | "font-daewoo-misc" + | "font-dec-misc" + | "font-ibm-type1" + | "font-isas-misc" + | "font-jis-misc" + | "font-micro-misc" + | "font-misc-cyrillic" + | "font-misc-ethiopic" + | "font-misc-meltho" + | "font-misc-misc" + | "font-mutt-misc" + | "font-schumacher-misc" + | "font-screen-cyrillic" + | "font-sony-misc" + | "font-sun-misc" + | "font-util" + | "font-winitzki-cyrillic" + | "font-xfree86-type1" + | "fontcacheproto" + | "fontconfig" + | "fontsproto" + | "fonttosfnt" + | "fping" + | "free-noncomm" + | "freedist" + | "freemarker" + | "freetts" + | "fslsfonts" + | "fstobdf" + | "galaxyhack" + | "gamess" + | "gccmakedep" + | "gips_iLBClicense.pdf" + | "glest-data" + | "glimpse" + | "glproto" + | "glut" + | "gnuplot" + | "google-picasa" + | "googleearth" + | "grass-ipafonts" + | "guild" + | "hp-value" + | "hylafax" + | "hyperic" + | "iASL" + | "iceauth" + | "ico" + | "icu" + | "imagemagick" + | "imake" + | "informix-jdbc" + | "inmon-sflow" + | "inputproto" + | "ipadic" + | "ipw2100-fw" + | "ipw2200-fw" + | "ipw3945" + | "isc-dhcp" + | "ixp4xx" + | "jardinains" + | "jaxen" + | "jcraft" + | "jdepend" + | "jlex" + | "jrockit" + | "kbproto" + | "kinterbasdb" + | "knights-demo" + | "kvirc" + | "lbxproxy" + | "less" + | "levee" + | "lha" + | "libFS" + | "libICE" + | "libSM" + | "libX11" + | "libXScrnSaver" + | "libXTrap" + | "libXau" + | "libXaw" + | "libXcomposite" + | "libXcursor" + | "libXdamage" + | "libXdmcp" + | "libXevie" + | "libXext" + | "libXfixes" + | "libXfont" + | "libXfontcache" + | "libXft" + | "libXi" + | "libXinerama" + | "libXmu" + | "libXp" + | "libXpm" + | "libXprintAppUtil" + | "libXprintUtil" + | "libXrandr" + | "libXrender" + | "libXres" + | "libXt" + | "libXtst" + | "libXv" + | "libXvMC" + | "libXxf86dga" + | "libXxf86misc" + | "libXxf86vm" + | "libdmx" + | "libdomainkeys-1.1" + | "libdrm" + | "libf2c" + | "libffi" + | "libfontenc" + | "liblbxutil" + | "liboldX" + | "libxkbfile" + | "libxkbui" + | "lisp2wish" + | "listres" + | "lndir" + | "lsof" + | "luit" + | "maestro" + | "makedepend" + | "mammoth" + | "mapm" + | "marginalhacks" + | "maui" + | "maya-5.0" + | "mayadoc-5.0" + | "mekanix" + | "meme" + | "mindterm" + | "mkcfm" + | "mkfontdir" + | "mkfontscale" + | "mmix" + | "molmol" + | "molscript" + | "mongrel" + | "mopac7" + | "mplus-fonts" + | "mserv" + | "mupad" + | "mx4j" + | "myspell-en_CA-JRossBeresford" + | "myspell-en_CA-KevinAtkinson" + | "myspell-et_EE-IEL" + | "myspell-hyph_sk_SK-TiborBako" + | "myspell-ispell-GeoffKuenning" + | "myspell-lt_LT-AlbertasAgejevas" + | "myspell-ru_RU-ALexanderLebedev" + | "myspell-th_cs_CZ-PavelRychlySmrz" + | "namd" + | "nemerle" + | "nethack" + | "netlogo" + | "netperf" + | "newton" + | "nhc98" + | "nomachine" + | "oclock" + | "openafs-krb5" + | "openafs-krb5-a" + | "openknights" + | "openmarket" + | "openpbs" + | "openspml" + | "openssl" + | "oracle-jdbc" + | "otter" + | "paraview" + | "penguzzle" + | "perforce" + | "petrify" + | "pgasync" + | "phrack" + | "pixman" + | "pkcrack" + | "pmd" + | "point2play" + | "postal2" + | "poster" + | "povlegal-3.1g" + | "povlegal-3.5" + | "povlegal-3.6" + | "printproto" + | "proxymngr" + | "public-domain" + | "pymol" + | "pysqlite" + | "qeradiant" + | "qlogic-fibre-channel-firmware" + | "qpage" + | "qpopper" + | "quake1-demodata" + | "quake2-demodata" + | "queen" + | "qwt" + | "randrproto" + | "recordproto" + | "renderproto" + | "resourceproto" + | "rgb" + | "richardson" + | "ringtonetools" + | "rstart" + | "ruby-debug" + | "satan" + | "saxpath" + | "scilab" + | "scripts" + | "scrnsaverproto" + | "selfhtml" + | "sessreg" + | "setxkbmap" + | "shoutcast" + | "showfont" + | "simpserver-test" + | "singular" + | "sip" + | "skype-eula" + | "smproxy" + | "sparky" + | "ssh" + | "sslwrap" + | "staden" + | "stardock-images" + | "stix" + | "sun-asis-javamake" + | "sun-bcla-j2ee" + | "sun-bcla-j2ee-deployment" + | "sun-bcla-j2me" + | "sun-bcla-jai" + | "sun-bcla-java-vm" + | "sun-bcla-java-vm-1.4.2" + | "sun-bcla-jimi" + | "sun-bcla-jmf" + | "sun-bcla-jmi" + | "sun-bcla-jms" + | "sun-bcla-jsapi" + | "sun-bcla-jsr101" + | "sun-bcla-jta" + | "sun-bcla-jvmstat" + | "sun-csl" + | "sun-j2sl" + | "sun-j2sl-6" + | "sun-jdl" + | "sun-jrl" + | "sun-jsr67" + | "sun-jsr93" + | "sun-openlook" + | "sun-rpc" + | "swiss-prot" + | "szip" + | "t-coffee" + | "tacc" + | "tcp_wrappers_license" + | "tkMOO" + | "tlswrap" + | "trac" + | "trapproto" + | "trolltech_PUL-1.0" + | "truecrypt-collective-1.0" + | "ttf2pt1" + | "twm" + | "unRAR" + | "ut2003" + | "ut2003-demo" + | "util-macros" + | "ventrilo" + | "videoproto" + | "vienna-rna" + | "viewcvs" + | "viewres" + | "vim" + | "visual" + | "vlgothic" + | "vmd" + | "vmware" + | "vmware-console" + | "w3m" + | "werken.xpath" + | "whitehead" + | "wxWinFDL-3" + | "wxWinLL-3" + | "x11perf" + | "xauth" + | "xbacklight" + | "xbattle" + | "xbiff" + | "xbitmaps" + | "xboing" + | "xcalc" + | "xclipboard" + | "xclock" + | "xcmiscproto" + | "xcmsdb" + | "xconsole" + | "xcursor-themes" + | "xcursorgen" + | "xdbedizzy" + | "xditview" + | "xdm" + | "xdpyinfo" + | "xdriinfo" + | "xearth" + | "xedit" + | "xev" + | "xextproto" + | "xeyes" + | "xf86-input-acecad" + | "xf86-input-aiptek" + | "xf86-input-calcomp" + | "xf86-input-citron" + | "xf86-input-digitaledge" + | "xf86-input-dmc" + | "xf86-input-dynapro" + | "xf86-input-elo2300" + | "xf86-input-elographics" + | "xf86-input-evdev" + | "xf86-input-fpit" + | "xf86-input-hyperpen" + | "xf86-input-jamstudio" + | "xf86-input-joystick" + | "xf86-input-keyboard" + | "xf86-input-magellan" + | "xf86-input-magictouch" + | "xf86-input-microtouch" + | "xf86-input-mouse" + | "xf86-input-mutouch" + | "xf86-input-palmax" + | "xf86-input-penmount" + | "xf86-input-spaceorb" + | "xf86-input-summa" + | "xf86-input-tek4957" + | "xf86-input-ur98" + | "xf86-input-vmmouse" + | "xf86-input-void" + | "xf86-video-amd" + | "xf86-video-apm" + | "xf86-video-ark" + | "xf86-video-ati" + | "xf86-video-chips" + | "xf86-video-cirrus" + | "xf86-video-cyrix" + | "xf86-video-dummy" + | "xf86-video-fbdev" + | "xf86-video-glint" + | "xf86-video-i128" + | "xf86-video-i740" + | "xf86-video-i810" + | "xf86-video-impact" + | "xf86-video-imstt" + | "xf86-video-mga" + | "xf86-video-neomagic" + | "xf86-video-newport" + | "xf86-video-nsc" + | "xf86-video-nv" + | "xf86-video-rendition" + | "xf86-video-s3" + | "xf86-video-s3virge" + | "xf86-video-savage" + | "xf86-video-siliconmotion" + | "xf86-video-sis" + | "xf86-video-sisusb" + | "xf86-video-sunbw2" + | "xf86-video-suncg14" + | "xf86-video-suncg3" + | "xf86-video-suncg6" + | "xf86-video-sunffb" + | "xf86-video-sunleo" + | "xf86-video-suntcx" + | "xf86-video-tdfx" + | "xf86-video-tga" + | "xf86-video-trident" + | "xf86-video-tseng" + | "xf86-video-v4l" + | "xf86-video-vermilion" + | "xf86-video-vesa" + | "xf86-video-vga" + | "xf86-video-via" + | "xf86-video-vmware" + | "xf86-video-voodoo" + | "xf86-video-xgi" + | "xf86bigfontproto" + | "xf86dga" + | "xf86dgaproto" + | "xf86driproto" + | "xf86miscproto" + | "xf86rushproto" + | "xf86vidmodeproto" + | "xfd" + | "xfindproxy" + | "xfontsel" + | "xfs" + | "xfsinfo" + | "xfwp" + | "xgamma" + | "xgc" + | "xhost" + | "xineramaproto" + | "xinit" + | "xkbcomp" + | "xkbdata" + | "xkbevd" + | "xkbprint" + | "xkbutils" + | "xkill" + | "xload" + | "xlogo" + | "xlsatoms" + | "xlsclients" + | "xlsfonts" + | "xmag" + | "xmame" + | "xman" + | "xmessage" + | "xmh" + | "xmlformat" + | "xmodmap" + | "xmore" + | "xorg-cf-files" + | "xorg-docs" + | "xorg-server" + | "xorg-sgml-doctools" + | "xphelloworld" + | "xplsprinters" + | "xpr" + | "xprehashprinterlist" + | "xprop" + | "xproto" + | "xproxymanagementprotocol" + | "xrandr" + | "xrdb" + | "xref.lisp" + | "xrefresh" + | "xrx" + | "xset" + | "xsetmode" + | "xsetpointer" + | "xsetroot" + | "xshipwars" + | "xsm" + | "xstdcmap" + | "xtrans" + | "xtrap" + | "xv" + | "xvidtune" + | "xvinfo" + | "xwd" + | "xwininfo" + | "xwud" + | "zend-optimizer" + | "zoo" + } + +IsA = + element IsA + { + "app" + | "app:console" + | "app:gui" + | "app:web" + | "library" + | "service" + | "data" + | "data:doc" + | "data:font" + | "kernel" + | "driver" + | "locale" + | "locale:tr" + | "locale:en" + | "locale:es" + | "locale:nl" + | "locale:fr" + | "locale:de" + | "locale:it" + } + +PartOf = element PartOf { text } + +Summary = element Summary { attlist.Summary, text } + +attlist.Summary &= attribute xml:lang { text }? + +Description = element Description { attlist.Description, text } + +attlist.Description &= attribute xml:lang { text }? + +Archive = element Archive { attlist.Archive, text } + +attlist.Archive &= + attribute sha1sum { text }, + attribute type + { + "targz" | "tarbz2" | "tarlzma" | "tar" | "zip" | "gzip" | "binary" + } + +BuildDependencies = element BuildDependencies { Dependency+ } + +Dependency = element Dependency { attlist.VersionReleaseToFrom, text } + +attlist.VersionReleaseToFrom = + attribute versionFrom { text }?, + attribute versionTo { text }?, + attribute version { text }?, + attribute releaseFrom { text }?, + attribute releaseTo { text }?, + attribute release { text }? + +Patches = element Patches { Patch+ } + +Patch = element Patch { attlist.Patch, text } + +attlist.Patch &= + attribute compressionType { text }?, + attribute level { text }?, + attribute target { text }? + +Provides = element Provides { COMAR+ } + +COMAR = element COMAR { attlist.COMAR, text } + +attlist.COMAR = attribute script { text }? + +Conflicts = element Conflicts { Conflicts.Package+ } + +Conflicts.Package = element Package { attlist.VersionReleaseToFrom, text } + +Replaces = element Replaces { Replaces.Package+ } + +Replaces.Package = element Package { attlist.VersionReleaseToFrom, text } + +AdditionalFiles = element AdditionalFiles { AdditionalFile+ } + +AdditionalFile = element AdditionalFile { attlist.AdditionalFile, text } + +attlist.AdditionalFile = + attribute target { text }, + attribute permission { text }?, + attribute owner { text }? + +RuntimeDependencies = element RuntimeDependencies { Dependency+ } + +Files = element Files { Path+ } + +Path = element Path { attlist.Path, text } + +attlist.Path &= + attribute fileType + { + "executable" + | "library" + | "data" + | "config" + | "doc" + | "man" + | "info" + | "localedata" + | "header" + }, + attribute permanent { "false" | "true" }? + +Update = + element Update + { + attlist.Update, + Date, + Version, + Comment, + Packager.Name, + Email + } + +attlist.Update &= + attribute release { text }, + attribute type { "security" | "bug" }? + +Date = element Date { xsd:date } + +Version = element Version { text } + +Comment = element Comment { text } diff --git a/editor/emacs/emacs/files/site-start.el b/editor/emacs/emacs/files/site-start.el new file mode 100644 index 0000000000..f715b0c16a --- /dev/null +++ b/editor/emacs/emacs/files/site-start.el @@ -0,0 +1,97 @@ + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Default configuration file for GNU/Emacs on Pisi Linux ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +(setq column-number-mode t) ; show column numbers below + +(display-time-mode t) ; display time below + +(show-paren-mode t) ; show parenthesis + +(transient-mark-mode t) ; show mark visually... + +;; (setq make-backup-files nil) ; no nasty back-up files + +(setq-default show-trailing-whitespace t) ; show trailing whitespace + +(setq frame-title-format "%b (%m)") ; descriptive frame title "filename (mode)" + +(setq scroll-step 1) ; scroll one line at a time + +(setq load-path (cons "~/.elisp" load-path)) ; add ~/.elisp as a custom load path + +(set-face-foreground 'font-lock-comment-face "red") ; show comments in red + +(set-scroll-bar-mode 'right) ; show scrollbar on the right + +;; use ibuffer by default +(global-set-key (kbd "C-x C-b") 'ibuffer) +(autoload 'ibuffer "ibuffer" "List buffers." t) + + +;; for zpspell +(setq ispell-program-name "zpspell") +(setq ispell-local-dictionary-alist + `((nil + "[A-ZŞĞIa-zşğı]" + "[^A-ZŞĞIa-zşğı]" + "[']" nil ("") "~utf-8" utf-8))) + + +;; Autoload init files under /etc/emacs/site-lisp +(defun pardus-auto-load-all () + "Autoload all init files under /etc/emacs/site-lisp" + (mapcar '(lambda (f) + (if (pardus-file-or-symlink-exists-p f) + (load f) + nil)) + (sort + (el-files-in-directory "/etc/emacs/site-lisp/") + 'string-lessp))) + +(defun pardus-file-or-symlink-exists-p (f) + "Check if file or symlink exists" + (let ((f-symlink-target (file-symlink-p f))) + (if f-symlink-target + (let ((f-symlink-target-path + (concat (file-name-directory f) f-symlink-target))) + (if (file-exists-p f-symlink-target-path) + t + nil)) + (file-exists-p f)))) + +(defun el-files-in-directory (directory) + "List the .el files in DIRECTORY and in its sub-directories." + (let (el-files-list + (current-directory-list + (directory-files-and-attributes directory t))) + ;; while we are in the current directory + (while current-directory-list + (cond + ;; check to see whether filename ends in `.el' + ;; and if so, append its name to a list. + ((equal ".el" (substring (car (car current-directory-list)) -3)) + (setq el-files-list + (cons (car (car current-directory-list)) el-files-list))) + ;; check whether filename is that of a directory + ((eq t (car (cdr (car current-directory-list)))) + ;; decide whether to skip or recurse + (if + (equal (or "." "..") + (substring (car (car current-directory-list)) -1)) + ;; then do nothing if filename is that of + ;; current directory or parent + () + ;; else descend into the directory and repeat the process + (setq el-files-list + (append + (el-files-in-directory + (car (car current-directory-list))) + el-files-list))))) + ;; move to the next filename in the list; this also + ;; shortens the list so the while loop eventually comes to an end + (setq current-directory-list (cdr current-directory-list))) + ;; return the filenames + el-files-list)) diff --git a/editor/emacs/emacs/pspec.xml b/editor/emacs/emacs/pspec.xml new file mode 100644 index 0000000000..84047be841 --- /dev/null +++ b/editor/emacs/emacs/pspec.xml @@ -0,0 +1,118 @@ + + + + + emacs + http://www.gnu.org/software/emacs + + PisiLinux Community + admins@pisilinux.org + + GPLv3+ + emacs + app:gui + app:console + An extensible console-mode editor + Emacs is the extensible, customizable, self-documenting real-time console-mode editor. It has many features to increase productivity when programming. + ftp://mirrors.kernel.org/gnu/emacs/emacs-25.2.tar.xz + + gtk2-devel + alsa-lib-devel + fontconfig-devel + giflib-devel + gpm + libjpeg-turbo-devel + libICE-devel + libSM-devel + libXft-devel + libXpm-devel + libXrender-devel + libpng-devel + librsvg-devel + tiff-devel + gnutls-devel + imagemagick-devel + + + + + emacs + + gpm + tiff + gtk2 + zlib + glib2 + libX11 + libpng + ncurses + freetype + libSM + libXft + libICE + giflib + libXpm + gnutls + librsvg + alsa-lib + gdk-pixbuf + fontconfig + libXrender + imagemagick + libjpeg-turbo + libXfixes + libxcb + dbus + gtk3 + cairo + pango + + + /etc + /usr/share/doc + /usr/share/man + /usr/bin + /usr/share/info + /usr/share/emacs + /usr/share/icons + /var/games/emacs + /usr/share/pixmaps + /usr/share/appdata + /usr/share/applications + /usr/libexec/emacs + + + site-start.el + pisi-spec.rnc + 80-nxml-mode.el + emacs.desktop + + + System.PackageHandler + + + + + + 2016-06-09 + 25.2 + Release Bump + Mustafa Cinasal + muscnsl@gmail.com + + + 2016-06-09 + 24.5 + Release Bump + Pisi Linux Community + admin@pisilinux.org + + + 2016-04-02 + 24.5 + First release + Ilker Manap + ilkermanap@gmail.com + + + diff --git a/editor/emacs/emacs/translations.xml b/editor/emacs/emacs/translations.xml new file mode 100644 index 0000000000..2be1c8e598 --- /dev/null +++ b/editor/emacs/emacs/translations.xml @@ -0,0 +1,8 @@ + + + + emacs + Genişletilebilir bir metin düzenleyici + Emacs, gelişmiş, özelleştirilebilir ve esnek bir metin editörüdür. Özellikle program yazanlar tarafından çokça tercih edilen, fare kullanımına gerek bırakmadan çok hızlı çalışma imkânı sağlayan bir editördür. + +