Showing with 220 additions and 55 deletions.
  1. +2 −2 .editorconfig
  2. +1 −0 .gitignore
  3. +27 −0 .travis.yml
  4. +7 −0 CONTRIBUTORS
  5. +28 −0 Makefile
  6. +35 −10 README.md
  7. +106 −43 editorconfig.el
  8. +14 −0 ert-tests/tests.el
4 changes: 2 additions & 2 deletions .editorconfig
Expand Up @@ -2,6 +2,6 @@
root = true

[*.el]
indent_style = tab
indent_style = space
indent_size = 2
tab_width = 8
insert_final_newline = true
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
*.elc
27 changes: 27 additions & 0 deletions .travis.yml
@@ -0,0 +1,27 @@
# https://github.com/rolandwalker/emacs-travis

language: emacs-lisp

env:
matrix:
- EMACS=emacs24
- EMACS=emacs-snapshot

install:
- if [ "$EMACS" = "emacs24" ]; then
sudo add-apt-repository -y ppa:cassou/emacs &&
sudo apt-get update -qq &&
sudo apt-get install -qq emacs24 emacs24-el;
fi
- if [ "$EMACS" = "emacs-snapshot" ]; then
sudo add-apt-repository -y ppa:cassou/emacs &&
sudo apt-get update -qq &&
sudo apt-get install -qq emacs-snapshot &&
sudo apt-get install -qq emacs-snapshot-el emacs-snapshot-gtk;
fi

script:
$EMACS --version && make test EMACS=${EMACS}

# notifications:
# email: false
7 changes: 7 additions & 0 deletions CONTRIBUTORS
@@ -0,0 +1,7 @@
Contributors to EditorConfig Emacs plugin:

Trey Hunner
Jonas Bernoulli
Johan Sundström
Desmond O. Chang
Steve Jordan
28 changes: 28 additions & 0 deletions Makefile
@@ -0,0 +1,28 @@
# -*- Makefile -*-

EMACS = emacs

TEST_DIR = ert-tests
TRAVIS_FILE = .travis.yml

# Compile with noninteractive and relatively clean environment.
BATCHFLAGS = -batch -q --no-site-file

SRCS = editorconfig.el
OBJS = $(SRCS:.el=.elc)

%.elc: %.el
${EMACS} $(BATCHFLAGS) -f batch-byte-compile $^

.PHONY: all clean test test-travis

all: $(OBJS)

clean:
-rm -f $(OBJS)

test:
${EMACS} $(BATCHFLAGS) -l editorconfig.el

test-travis:
@if test -z "$$TRAVIS" && test -e $(TRAVIS_FILE); then travis-lint $(TRAVIS_FILE); fi
45 changes: 35 additions & 10 deletions README.md
Expand Up @@ -7,22 +7,47 @@ This is an [EditorConfig][] plugin for Emacs.
Download the [EditorConfig core][] and follow the instructions in the README
and INSTALL files to install it.

Once EditorConfig core is installed, copy `editorconfig.el` to `~/.emacs.d/`
Once EditorConfig core is installed, copy [`editorconfig.el`][] to `~/.emacs.d/`
and add the following to your `~/.emacs` file:

(add-to-list 'load-path "~/.emacs.d/")
(load "editorconfig")

## Supported properties

The EditorConfig Emacs plugin supports the following EditorConfig [properties][]:

* indent_style
* indent_size
* tab_width
* end_of_line
* root (only used by EditorConfig core)
Current Emacs plugin coverage for EditorConfig's [properties][]:

* `indent_style`
* `indent_size`
* `tab_width`
* `end_of_line`
* <del>`charset`</del>
* `trim_trailing_whitespace`
* `insert_final_newline = true` is supported
* <del>`insert_final_newline = false`</del> is not enforced
(as in trailing newlines actually being removed automagically),
we just buffer-locally override any preferences that would auto-add them
to files `.editorconfig` marks as trailing-newline-free
* `root` (only used by EditorConfig core)

Not yet covered properties marked with <del>over-strike</del>
– pull requests implementin missing features warmly welcomed!
Typically, you will want to tie these to native functionality,
or the configuration of existing packages handling the feature.

As several packages have their own handling of, say, indention,
we might not yet cover some mode you use, but we try to add the
ones that show up on our radar. Similarly, we don't yet hook
in to all different packages for whitespace trimming to inform
them about editorconfig settings, but aim for better coverage
of things like [ws-trim](ftp://ftp.lysator.liu.se/pub/emacs/ws-trim.el).

## Submitting Bugs and Feature Requests

Bugs, feature requests, and other issues should be submitted to the main
EditorConfig issue tracker: https://github.com/editorconfig/editorconfig/issues

[EditorConfig]: http://editorconfig.org
[EditorConfig core]: https://github.com/editorconfig/editorconfig
[properties]: http://editorconfig.org/#supported-properties
[EditorConfig core]: https://github.com/editorconfig/editorconfig-core
[properties]: http://editorconfig.org/#supported-properties
[`editorconfig.el`]: https://github.com/editorconfig/editorconfig-emacs/raw/master/editorconfig.el
149 changes: 106 additions & 43 deletions editorconfig.el
@@ -1,10 +1,14 @@
;;; editorconfig.el --- EditorConfig <http://editorconfig.org> Emacs extension
;;; editorconfig.el --- EditorConfig Emacs extension

;; Copyright (C) 2011-2012 EditorConfig Team
;; Copyright (C) 2011-2013 EditorConfig Team

;; Author: Trey Hunner
;; Version: 0.1
;; URL: http://editorconfig.org
;; Author: EditorConfig Team <editorconfig@googlegroups.com>
;; Version: 0.2
;; URL: http://github.com/editorconfig/editorconfig-emacs#readme

;; See
;; http://github.com/editorconfig/editorconfig-emacs/graphs/contributors
;; or the CONTRIBUTORS file for the list of contributors.

;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions are met:
Expand All @@ -27,66 +31,125 @@
;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
;; POSSIBILITY OF SUCH DAMAGE.

(defvar editorconfig-exec-path "editorconfig")
(defun set-indentation (style &optional size tab_width)
;;; Commentary:

;; EditorConfig helps developers define and maintain consistent
;; coding styles between different editors and IDEs.

;; The EditorConfig project consists of a file format for defining
;; coding styles and a collection of text editor plugins that enable
;; editors to read the file format and adhere to defined styles.
;; EditorConfig files are easily readable and they work nicely with
;; version control systems.

;;; Code:

(defvar edconf-exec-path "editorconfig")

(defun edconf-set-indentation (style &optional size tab_width)
"Set indentation type from given style and size"
(if (equal style "space")
(setq indent-tabs-mode nil
size (string-to-number size)
c-basic-offset size
python-indent size
py-indent-offset size
perl-indent-level size
cperl-indent-level size
tab-stop-list (let ((stops (cons size ())))
(while (< (car stops) 120)
(setq stops (cons
(+ size (car stops))
stops)))
(nreverse stops)))
(when (equal style "space")
(setq indent-tabs-mode nil
size (string-to-number size)
LaTeX-indent-level size
LaTeX-item-indent size
TeX-brace-indent-level size
c-basic-offset size
cperl-indent-level size
js-indent-level size
lisp-indent-offset size
perl-indent-level size
py-indent-offset size
python-indent size
ruby-indent-level size
;(make-local-variable 'sgml-basic-offset) size
tab-stop-list (let ((stops (cons size ())))
(while (< (car stops) 120)
(setq stops (cons
(+ size (car stops))
stops)))
(nreverse stops))))
(when (equal style "tab")
(setq indent-tabs-mode t))
(if tab_width
(setq tab-width (string-to-number tab_width))))

(defun set-line-ending (end-of-line)
(defun edconf-set-line-ending (end-of-line)
"Set line ending style to CR, LF, or CRLF"
(set-buffer-file-coding-system
(cond
((equal end-of-line "lf") 'undecided-unix)
((equal end-of-line "cr") 'undecided-mac)
((equal end-of-line "crlf") 'undecided-dos))))
((equal end-of-line "crlf") 'undecided-dos)
(t 'undecided))
nil t))

(defun get-properties ()
(defun edconf-set-trailing-nl (final-newline)
(cond
((equal final-newline "true")
;; keep prefs around how/when the nl is added, if set - otherwise add on save
(setq require-final-newline (or require-final-newline t)
mode-require-final-newline (or mode-require-final-newline t)))
((equal final-newline "false")
;; FIXME: Add functionality for actually REMOVING any trailing newlines here!
;; (rather than just making sure we don't automagically ADD a new one)
(setq require-final-newline nil
mode-require-final-newline nil))))

(defun edconf-set-trailing-ws (trim-trailing-ws)
"set up trimming of trailing whitespace at end of lines"
(make-local-variable 'write-file-functions) ;; just current buffer
(when (equal trim-trailing-ws "true")
;; when true we push delete-trailing-whitespace (emacs > 21)
;; to write-file-functions
(add-to-list
'write-file-functions
'delete-trailing-whitespace))
(when (equal trim-trailing-ws "false")
;; when false we remove every delete-trailing-whitespace
;; from write-file-functions
(setq
write-file-functions
(delete
'delete-trailing-whitespace
write-file-functions))))

(defun edconf-get-properties ()
"Call EditorConfig core and return output"
(let ((oldbuf (current-buffer)))
(call-process editorconfig-exec-path nil "ecbuffer" nil (buffer-file-name oldbuf))
(call-process edconf-exec-path nil "ecbuffer" nil (buffer-file-name oldbuf))
(set-buffer (get-buffer "ecbuffer"))
(let (props-string)
(setq props-string (buffer-string))
(set-buffer oldbuf)
(kill-buffer (get-buffer "ecbuffer"))
props-string)))

(defun parse-properties (props-string)
(defun edconf-parse-properties (props-string)
"Create properties hash table from string of properties"
(let (props-list properties)
(setq props-list (split-string props-string "\n")
properties (make-hash-table :test 'equal))
properties (make-hash-table :test 'equal))
(dolist (prop props-list properties)
(let ((key-val (split-string prop " *= *")))
(if (> (length key-val) 1)
(let (key val)
(setq key (car key-val)
val (mapconcat 'identity (cdr key-val) ""))
(puthash key val properties)))))))

(add-hook 'find-file-hook
(function (lambda ()
(let (props indent_style indent_size tab_width)
(setq props (parse-properties (get-properties))
indent_style (gethash "indent_style" props)
indent_size (gethash "indent_size" props)
tab_width (gethash "tab_width" props)
end_of_line (gethash "end_of_line" props))
(set-indentation indent_style indent_size tab_width)
(set-line-ending end_of_line)))))
(when (> (length key-val) 1)
(let ((key (intern (car key-val)))
(val (mapconcat 'identity (cdr key-val) "")))
(puthash key val properties)))))))

(defun edconf-find-file-hook ()
(when (executable-find edconf-exec-path)
(let ((props (edconf-parse-properties (edconf-get-properties))))
(edconf-set-indentation (gethash 'indent_style props)
(gethash 'indent_size props)
(gethash 'tab_width props))
(edconf-set-line-ending (gethash 'end_of_line props))
(edconf-set-trailing-nl (gethash 'insert_final_newline props))
(edconf-set-trailing-ws (gethash 'trim_trailing_whitespace props)))))

;;;###autoload
(add-hook 'find-file-hook 'edconf-find-file-hook)

(provide 'editorconfig)

;;; editorconfig.el ends here
14 changes: 14 additions & 0 deletions ert-tests/tests.el
@@ -0,0 +1,14 @@
(require 'editorconfig)

;;; interactive

(ert-deftest interactive-test-01 nil
"This test should not run on Travis"
:tags '(:interactive)
(should t))

;;; noninteractive, will run on Travis

(ert-deftest has-feature-01 nil
"minimally working - provides 'editorconfig"
(should (featurep 'editorconfig)))