From 91284e55300c4f7c6473ce576def88e89111bf0e Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 9 Jun 2013 20:45:59 -0500 Subject: [PATCH 1/9] Add failing test bad mac format --- samples/Emacs Lisp/ess-julia.el | 473 ++++++++++++++++++++++++++++++++ test/test_blob.rb | 1 + 2 files changed, 474 insertions(+) create mode 100644 samples/Emacs Lisp/ess-julia.el diff --git a/samples/Emacs Lisp/ess-julia.el b/samples/Emacs Lisp/ess-julia.el new file mode 100644 index 00000000..ff324293 --- /dev/null +++ b/samples/Emacs Lisp/ess-julia.el @@ -0,0 +1,473 @@ +;; ess-julia.el --- ESS julia mode and inferior interaction +;; +;; Copyright (C) 2012 Vitalie Spinu. +;; +;; Filename: ess-julia.el +;; Author: Vitalie Spinu (based on julia-mode.el from julia-lang project) +;; Maintainer: Vitalie Spinu +;; Created: 02-04-2012 (ESS 12.03) +;; Keywords: ESS, julia +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; This file is *NOT* part of GNU Emacs. +;; This file is part of ESS +;; +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 3, 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; see the file COPYING. If not, write to the Free Software +;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +;; USA. +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Commentary: +;; customise inferior-julia-program-name to point to your julia-release-basic +;; and start the inferior with M-x julia. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +(require 'compile); for compilation-* below + +;;; Code: + +(defvar julia-mode-hook nil) + +(add-to-list 'auto-mode-alist '("\\.jl\\'" . julia-mode)) + +(defvar julia-syntax-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?_ "_" table) ; underscores in words + (modify-syntax-entry ?@ "_" table) + (modify-syntax-entry ?. "_" table) + (modify-syntax-entry ?# "<" table) ; # single-line comment start + (modify-syntax-entry ?\n ">" table) ; \n single-line comment end + (modify-syntax-entry ?\{ "(} " table) + (modify-syntax-entry ?\} "){ " table) + (modify-syntax-entry ?\[ "(] " table) + (modify-syntax-entry ?\] ")[ " table) + (modify-syntax-entry ?\( "() " table) + (modify-syntax-entry ?\) ")( " table) + ;(modify-syntax-entry ?\\ "." table) ; \ is an operator outside quotes + (modify-syntax-entry ?' "." table) ; character quote or transpose + (modify-syntax-entry ?\" "\"" table) + (modify-syntax-entry ?` "\"" table) + ;; (modify-syntax-entry ?\" "." table) + (modify-syntax-entry ?? "." table) + (modify-syntax-entry ?$ "." table) + (modify-syntax-entry ?& "." table) + (modify-syntax-entry ?* "." table) + (modify-syntax-entry ?+ "." table) + (modify-syntax-entry ?- "." table) + (modify-syntax-entry ?< "." table) + (modify-syntax-entry ?> "." table) + (modify-syntax-entry ?= "." table) + (modify-syntax-entry ?% "." table) + table) + "Syntax table for julia-mode") + +;; syntax table that holds within strings +(defvar julia-mode-string-syntax-table + (let ((table (make-syntax-table))) + table) + "Syntax table for julia-mode") + +;; disable " inside char quote +(defvar julia-mode-char-syntax-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?\" "." table) + table) + "Syntax table for julia-mode") + +;; not used +;; (defconst julia-string-regex +;; "\"[^\"]*?\\(\\(\\\\\\\\\\)*\\\\\"[^\"]*?\\)*\"") + +(defconst julia-char-regex + "\\(\\s(\\|\\s-\\|-\\|[,%=<>\\+*/?&|$!\\^~\\\\;:]\\|^\\)\\('\\(\\([^']*?[^\\\\]\\)\\|\\(\\\\\\\\\\)\\)'\\)") + +(defconst julia-unquote-regex + "\\(\\s(\\|\\s-\\|-\\|[,%=<>\\+*/?&|!\\^~\\\\;:]\\|^\\)\\($[a-zA-Z0-9_]+\\)") + +(defconst julia-forloop-in-regex + "for +[^ ]+ +.*\\(in\\)\\(\\s-\\|$\\)+") + +(defconst ess-subset-regexp + "\\[[0-9:, ]*\\]" ) + +(defconst julia-font-lock-defaults + (list '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\)\\|Int\\(8\\|16\\|32\\|64\\)\\|Integer\\|Float\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexNum\\|Bool\\|Char\\|Number\\|Scalar\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|Range\\|Range1\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Buffer\\|Size\\|Index\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|None\\|String\\|Ptr\\|Void\\|Exception\\|PtrInt\\|Long\\|Ulong\\)\\>" . + font-lock-type-face) + (cons + (concat "\\<\\(" + (mapconcat + 'identity + '("if" "else" "elseif" "while" "for" "begin" "end" "quote" + "try" "catch" "return" "local" "abstract" "function" "macro" "ccall" + "typealias" "break" "continue" "type" "global" "@\\w+" + "module" "import" "export" "const" "let" "bitstype" "using") + "\\|") "\\)\\>") + 'font-lock-keyword-face) + '("\\<\\(true\\|false\\|C_NULL\\|Inf\\|NaN\\|Inf32\\|NaN32\\)\\>" . font-lock-constant-face) + (list julia-unquote-regex 2 'font-lock-constant-face) + (list julia-char-regex 2 'font-lock-string-face) + (list julia-forloop-in-regex 1 'font-lock-keyword-face) + ;; (cons ess-subset-regexp 'font-lock-constant-face) + (cons "\\(\\sw+\\) ?(" '(1 font-lock-function-name-face keep)) + ;(list julia-string-regex 0 'font-lock-string-face) +)) + +(defconst julia-block-start-keywords + (list "if" "while" "for" "begin" "try" "function" "type" "let" "macro" + "quote")) + +(defconst julia-block-other-keywords + (list "else" "elseif")) + +(defconst julia-block-end-keywords + (list "end" "else" "elseif" "catch")) + +(defun ess-inside-brackets-p (&optional pos) + (save-excursion + (let* ((pos (or pos (point))) + (beg (re-search-backward "\\[" (max (point-min) (- pos 1000)) t)) + (end (re-search-forward "\\]" (min (point-max) (+ pos 1000)) t))) + (and beg end (> pos beg) (> end pos))))) + +(defun julia-at-keyword (kw-list) + ; not a keyword if used as a field name, X.word, or quoted, :word + (and (or (= (point) 1) + (and (not (equal (char-before (point)) ?.)) + (not (equal (char-before (point)) ?:)))) + (not (ess-inside-string-or-comment-p (point))) + (not (ess-inside-brackets-p (point))) + (member (current-word) kw-list))) + +; get the position of the last open block +(defun julia-last-open-block-pos (min) + (let ((count 0)) + (while (not (or (> count 0) (<= (point) min))) + (backward-word 1) + (setq count + (cond ((julia-at-keyword julia-block-start-keywords) + (+ count 1)) + ((and (equal (current-word) "end") + (not (ess-inside-comment-p)) (not (ess-inside-brackets-p))) + (- count 1)) + (t count)))) + (if (> count 0) + (point) + nil))) + +; get indent for last open block +(defun julia-last-open-block (min) + (let ((pos (julia-last-open-block-pos min))) + (and pos + (progn + (goto-char pos) + (+ julia-basic-offset (current-indentation)))))) + +; return indent implied by a special form opening on the previous line, if any +(defun julia-form-indent () + (forward-line -1) + (end-of-line) + (backward-sexp) + (if (julia-at-keyword julia-block-other-keywords) + (+ julia-basic-offset (current-indentation)) + (if (char-equal (char-after (point)) ?\() + (progn + (backward-word 1) + (let ((cur (current-indentation))) + (if (julia-at-keyword julia-block-start-keywords) + (+ julia-basic-offset cur) + nil))) + nil))) + +(defun julia-paren-indent () + (let* ((p (parse-partial-sexp (save-excursion + ;; only indent by paren if the last open + ;; paren is closer than the last open + ;; block + (or (julia-last-open-block-pos (point-min)) + (point-min))) + (progn (beginning-of-line) + (point)))) + (pos (cadr p))) + (if (or (= 0 (car p)) (null pos)) + nil + (progn (goto-char pos) (+ 1 (current-column)))))) + ; (forward-line -1) + ; (end-of-line) + ; (let ((pos (condition-case nil + ; (scan-lists (point) -1 1) + ; (error nil)))) + ; (if pos + ; (progn (goto-char pos) (+ 1 (current-column))) + ; nil))) + +(defun julia-indent-line () + "Indent current line of julia code" + (interactive) + ; (save-excursion + (end-of-line) + (indent-line-to + (or (and (ess-inside-string-p (point-at-bol)) 0) + (save-excursion (ignore-errors (julia-form-indent))) + (save-excursion (ignore-errors (julia-paren-indent))) + ;; previous line ends in = + (save-excursion + (beginning-of-line) + (skip-chars-backward " \t\n") + (when (eql (char-before) ?=) + (+ julia-basic-offset (current-indentation)))) + (save-excursion + (let ((endtok (progn + (beginning-of-line) + (forward-to-indentation 0) + (julia-at-keyword julia-block-end-keywords)))) + (ignore-errors (+ (julia-last-open-block (point-min)) + (if endtok (- julia-basic-offset) 0))))) + ;; take same indentation as previous line + (save-excursion (forward-line -1) + (current-indentation)) + 0)) + (when (julia-at-keyword julia-block-end-keywords) + (forward-word 1))) + +(defvar julia-editing-alist + '((paragraph-start . (concat "\\s-*$\\|" page-delimiter)) + (paragraph-separate . (concat "\\s-*$\\|" page-delimiter)) + (paragraph-ignore-fill-prefix . t) + (require-final-newline . t) + (comment-start . "# ") + (comment-add . 1) + (comment-start-skip . "#+\\s-*") + (comment-column . 40) + ;;(comment-indent-function . 'S-comment-indent) + ;;(ess-comment-indent . 'S-comment-indent) + ;; (ess-indent-line . 'S-indent-line) + ;;(ess-calculate-indent . 'ess-calculate-indent) + (ess-indent-line-function . 'julia-indent-line) + (indent-line-function . 'julia-indent-line) + (parse-sexp-ignore-comments . t) + (ess-style . ess-default-style) ;; ignored + (ess-local-process-name . nil) + ;;(ess-keep-dump-files . 'ask) + (ess-mode-syntax-table . julia-syntax-table) + ;; For Changelog add, require ' ' before <- : "attr<-" is a function name : + ;; (add-log-current-defun-header-regexp . "^\\(.+\\)\\s-+=[ \t\n]*function") + (add-log-current-defun-header-regexp . "^.*function[ \t]*\\([^ \t(]*\\)[ \t]*(") + (font-lock-defaults . '(julia-font-lock-defaults + nil nil ((?\_ . "w")))) + ) + "General options for julia source files.") + +(autoload 'inferior-ess "ess-inf" "Run an ESS process.") +(autoload 'ess-mode "ess-mode" "Edit an ESS process.") + +(defun julia-send-string-function (process string visibly) + (let ((file (concat temporary-file-directory "julia_eval_region.jl"))) + (with-temp-file file + (insert string)) + (process-send-string process (format ess-load-command file)))) + +(defun julia-get-help-topics (&optional proc) + (ess-get-words-from-vector "ESS.all_help_topics()\n")) + ;; (ess-command com))) + +(defvar julia-help-command "help(\"%s\")\n") + +(defvar ess-julia-error-regexp-alist '(julia-in julia-at) + "List of symbols which are looked up in `compilation-error-regexp-alist-alist'.") + +(add-to-list 'compilation-error-regexp-alist-alist + '(julia-in "^\\s-*in [^ \t\n]* \\(at \\(.*\\):\\([0-9]+\\)\\)" 2 3 nil 2 1)) +(add-to-list 'compilation-error-regexp-alist-alist + '(julia-at "^\\S-+\\s-+\\(at \\(.*\\):\\([0-9]+\\)\\)" 2 3 nil 2 1)) + +(defvar julia-customize-alist + '((comint-use-prompt-regexp . t) + (ess-eldoc-function . 'ess-julia-eldoc-function) + (inferior-ess-primary-prompt . "a> ") ;; from julia> + (inferior-ess-secondary-prompt . nil) + (inferior-ess-prompt . "\\w*> ") + (ess-local-customize-alist . 'julia-customize-alist) + (inferior-ess-program . inferior-julia-program-name) + (inferior-ess-font-lock-defaults . julia-font-lock-defaults) + (ess-get-help-topics-function . 'julia-get-help-topics) + (ess-help-web-search-command . "http://docs.julialang.org/en/latest/search/?q=%s") + (ess-load-command . "include(\"%s\")\n") + (ess-funargs-command . "ESS.fun_args(\"%s\")\n") + (ess-dump-error-re . "in \\w* at \\(.*\\):[0-9]+") + (ess-error-regexp . "\\(^\\s-*at\\s-*\\(?3:.*\\):\\(?2:[0-9]+\\)\\)") + (ess-error-regexp-alist . ess-julia-error-regexp-alist) + (ess-send-string-function . nil);'julia-send-string-function) + (ess-imenu-generic-expression . julia-imenu-generic-expression) + ;; (inferior-ess-objects-command . inferior-R-objects-command) + ;; (inferior-ess-search-list-command . "search()\n") + (inferior-ess-help-command . julia-help-command) + ;; (inferior-ess-help-command . "help(\"%s\")\n") + (ess-language . "julia") + (ess-dialect . "julia") + (ess-suffix . "jl") + (ess-dump-filename-template . (ess-replace-regexp-in-string + "S$" ess-suffix ; in the one from custom: + ess-dump-filename-template-proto)) + (ess-mode-syntax-table . julia-syntax-table) + (ess-mode-editing-alist . julia-editing-alist) + (ess-change-sp-regexp . nil );ess-R-change-sp-regexp) + (ess-help-sec-regex . ess-help-R-sec-regex) + (ess-help-sec-keys-alist . ess-help-R-sec-keys-alist) + (ess-loop-timeout . ess-S-loop-timeout);fixme: dialect spec. + (ess-cmd-delay . ess-R-cmd-delay) + (ess-function-pattern . ess-R-function-pattern) + (ess-object-name-db-file . "ess-r-namedb.el" ) + (ess-smart-operators . ess-R-smart-operators) + (inferior-ess-help-filetype . nil) + (inferior-ess-exit-command . "exit()\n") + ;;harmful for shell-mode's C-a: -- but "necessary" for ESS-help? + (inferior-ess-start-file . nil) ;; "~/.ess-R" + (inferior-ess-start-args . "") + (inferior-ess-language-start . nil) + (ess-STERM . "iESS") + (ess-editor . R-editor) + (ess-pager . R-pager) + ) + "Variables to customize for Julia -- set up later than emacs initialization.") + + +(defvar ess-julia-versions '("julia") + "List of partial strings for versions of Julia to access within ESS. +Each string specifies the start of a filename. If a filename +beginning with one of these strings is found on `exec-path', a M-x +command for that version of Julia is made available. ") + +(defcustom inferior-julia-args "" + "String of arguments (see 'julia --help') used when starting julia." +;; These arguments are currently not passed to other versions of julia that have +;; been created using the variable `ess-r-versions'." + :group 'ess-julia + :type 'string) + +;;;###autoload +(defun julia-mode (&optional proc-name) + "Major mode for editing julia source. See `ess-mode' for more help." + (interactive "P") + ;; (setq ess-customize-alist julia-customize-alist) + (ess-mode julia-customize-alist proc-name) + ;; for emacs < 24 + ;; (add-hook 'comint-dynamic-complete-functions 'ess-complete-object-name nil 'local) + ;; for emacs >= 24 + ;; (remove-hook 'completion-at-point-functions 'ess-filename-completion 'local) ;; should be first + ;; (add-hook 'completion-at-point-functions 'ess-object-completion nil 'local) + ;; (add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local) + (if (fboundp 'ess-add-toolbar) (ess-add-toolbar)) + (set (make-local-variable 'end-of-defun-function) 'ess-end-of-function) + ;; (local-set-key "\t" 'julia-indent-line) ;; temp workaround + ;; (set (make-local-variable 'indent-line-function) 'julia-indent-line) + (set (make-local-variable 'julia-basic-offset) 4) + (setq imenu-generic-expression julia-imenu-generic-expression) + (imenu-add-to-menubar "Imenu-jl") + (run-hooks 'julia-mode-hook)) + + +(defvar ess-julia-post-run-hook nil + "Functions run in process buffer after the initialization of + julia process.") + +;;;###autoload +(defun julia (&optional start-args) + "Call 'julia', +Optional prefix (C-u) allows to set command line arguments, such as +--load=. This should be OS agnostic. +If you have certain command line arguments that should always be passed +to julia, put them in the variable `inferior-julia-args'." + (interactive "P") + ;; get settings, notably inferior-julia-program-name : + (if (null inferior-julia-program-name) + (error "'inferior-julia-program-name' does not point to 'julia-release-basic' executable") + (setq ess-customize-alist julia-customize-alist) + (ess-write-to-dribble-buffer ;; for debugging only + (format + "\n(julia): ess-dialect=%s, buf=%s, start-arg=%s\n current-prefix-arg=%s\n" + ess-dialect (current-buffer) start-args current-prefix-arg)) + (let* ((jl-start-args + (concat inferior-julia-args " " ; add space just in case + (if start-args + (read-string + (concat "Starting Args" + (if inferior-julia-args + (concat " [other than '" inferior-julia-args "']")) + " ? ")) + nil)))) + (inferior-ess jl-start-args) ;; -> .. (ess-multi ...) -> .. (inferior-ess-mode) .. + (ess--tb-start) + (set (make-local-variable 'julia-basic-offset) 4) + ;; remove ` from julia's logo + (goto-char (point-min)) + (while (re-search-forward "`" nil t) + (replace-match "'")) + (goto-char (point-max)) + (ess--inject-code-from-file (format "%sess-julia.jl" ess-etc-directory)) + (with-ess-process-buffer nil + (run-mode-hooks 'ess-julia-post-run-hook)) + ))) + +;;; ELDOC + +(defun ess-julia-eldoc-function () + "Return the doc string, or nil. +If an ESS process is not associated with the buffer, do not try +to look up any doc strings." + (interactive) + (when (and (ess-process-live-p) + (not (ess-process-get 'busy))) + (let ((funname (or (and ess-eldoc-show-on-symbol ;; aggressive completion + (symbol-at-point)) + (car (ess--funname.start))))) + (when funname + (let* ((args (copy-sequence (nth 2 (ess-function-arguments funname)))) + (W (- (window-width (minibuffer-window)) (+ 4 (length funname)))) + (doc (concat (propertize funname 'face font-lock-function-name-face) ": "))) + (when args + (setq args (sort args (lambda (s1 s2) + (< (length s1) (length s2))))) + (setq doc (concat doc (pop args))) + (while (and args (< (length doc) W)) + (setq doc (concat doc " " + (pop args)))) + (when (and args (< (length doc) W)) + (setq doc (concat doc " {--}")))) + doc))))) + + +;;; IMENU +(defvar julia-imenu-generic-expression + ;; don't use syntax classes, screws egrep + '(("Function (_)" "[ \t]*function[ \t]+\\(_[^ \t\n]*\\)" 1) + ("Function" "[ \t]*function[ \t]+\\([^_][^\t\n]*\\)" 1) + ("Const" "[ \t]*const \\([^ \t\n]*\\)" 1) + ("Type" "^[ \t]*[a-zA-Z0-9_]*type[a-zA-Z0-9_]* \\([^ \t\n]*\\)" 1) + ("Require" " *\\(\\brequire\\)(\\([^ \t\n)]*\\)" 2) + ("Include" " *\\(\\binclude\\)(\\([^ \t\n)]*\\)" 2) + ;; ("Classes" "^.*setClass(\\(.*\\)," 1) + ;; ("Coercions" "^.*setAs(\\([^,]+,[^,]*\\)," 1) ; show from and to + ;; ("Generics" "^.*setGeneric(\\([^,]*\\)," 1) + ;; ("Methods" "^.*set\\(Group\\|Replace\\)?Method(\"\\(.+\\)\"," 2) + ;; ;;[ ]*\\(signature=\\)?(\\(.*,?\\)*\\)," 1) + ;; ;; + ;; ;;("Other" "^\\(.+\\)\\s-*<-[ \t\n]*[^\\(function\\|read\\|.*data\.frame\\)]" 1) + ;; ("Package" "^.*\\(library\\|require\\)(\\(.*\\)," 2) + ;; ("Data" "^\\(.+\\)\\s-*<-[ \t\n]*\\(read\\|.*data\.frame\\).*(" 1))) + )) + +(provide 'ess-julia) diff --git a/test/test_blob.rb b/test/test_blob.rb index a5efbb6f..6d6b4051 100644 --- a/test/test_blob.rb +++ b/test/test_blob.rb @@ -67,6 +67,7 @@ class TestBlob < Test::Unit::TestCase def test_mac_format assert blob("Text/mac.txt").mac_format? + assert !blob("Emacs Lisp/ess-julia.el").mac_format? end def test_lines_mac_format From c7100be1399917dd9f9137a130a60d7ac934509f Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 9 Jun 2013 20:48:45 -0500 Subject: [PATCH 2/9] Make mac_format? private --- lib/linguist/blob_helper.rb | 2 +- test/test_blob.rb | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/linguist/blob_helper.rb b/lib/linguist/blob_helper.rb index 8e0e3262..3e63b5ef 100644 --- a/lib/linguist/blob_helper.rb +++ b/lib/linguist/blob_helper.rb @@ -250,7 +250,7 @@ module Linguist @line_split_character ||= (mac_format?? "\r" : "\n") end - # Public: Is the data in ** Mac Format **. This format uses \r (0x0d) characters + # Private: Is the data in ** Mac Format **. This format uses \r (0x0d) characters # for line ends and does not include a \n (0x0a). # # Returns true when mac format is detected. diff --git a/test/test_blob.rb b/test/test_blob.rb index 6d6b4051..9690c6df 100644 --- a/test/test_blob.rb +++ b/test/test_blob.rb @@ -65,13 +65,9 @@ class TestBlob < Test::Unit::TestCase assert_equal ["module Foo", "end", ""], blob("Ruby/foo.rb").lines end - def test_mac_format - assert blob("Text/mac.txt").mac_format? - assert !blob("Emacs Lisp/ess-julia.el").mac_format? - end - def test_lines_mac_format assert_equal ["line 1", "line 2", ""], blob("Text/mac.txt").lines + assert_equal 473, blob("Emacs Lisp/ess-julia.el").lines.length end def test_size From fa797df0c7689ae023cbeb5ab06bf7100e6201bd Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 9 Jun 2013 20:51:26 -0500 Subject: [PATCH 3/9] Note that BlobHelper is a turd --- lib/linguist/blob_helper.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/linguist/blob_helper.rb b/lib/linguist/blob_helper.rb index 3e63b5ef..933c4563 100644 --- a/lib/linguist/blob_helper.rb +++ b/lib/linguist/blob_helper.rb @@ -8,6 +8,11 @@ require 'pygments' require 'yaml' module Linguist + # DEPRECATED Avoid mixing into Blob classes. Prefer functional interfaces + # like `Language.detect` over `Blob#language`. + # + # Avoid adding additional bloat to this module. + # # BlobHelper is a mixin for Blobish classes that respond to "name", # "data" and "size" such as Grit::Blob. module BlobHelper From 2e39d1d582b6569443efd388bd5698bcd623a128 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 9 Jun 2013 20:53:33 -0500 Subject: [PATCH 4/9] Rebuild samples --- lib/linguist/samples.json | 327 +++++++++++++++++++++++++++++++++++++- 1 file changed, 320 insertions(+), 7 deletions(-) diff --git a/lib/linguist/samples.json b/lib/linguist/samples.json index d41e9a89..ce06b4d3 100644 --- a/lib/linguist/samples.json +++ b/lib/linguist/samples.json @@ -380,8 +380,8 @@ ".gemrc" ] }, - "tokens_total": 358215, - "languages_total": 424, + "tokens_total": 359968, + "languages_total": 425, "tokens": { "ABAP": { "*/**": 1, @@ -12162,9 +12162,322 @@ "show": 2 }, "Emacs Lisp": { - "(": 1, + "(": 156, "print": 1, - ")": 1 + ")": 144, + ";": 333, + "ess": 48, + "-": 294, + "julia.el": 2, + "ESS": 5, + "julia": 39, + "mode": 12, + "and": 3, + "inferior": 13, + "interaction": 1, + "Copyright": 1, + "C": 2, + "Vitalie": 3, + "Spinu.": 1, + "Filename": 1, + "Author": 1, + "Spinu": 2, + "based": 1, + "on": 2, + "mode.el": 1, + "from": 3, + "lang": 1, + "project": 1, + "Maintainer": 1, + "Created": 1, + "Keywords": 1, + "This": 4, + "file": 10, + "is": 5, + "*NOT*": 1, + "part": 2, + "of": 8, + "GNU": 4, + "Emacs.": 1, + "program": 6, + "free": 1, + "software": 1, + "you": 1, + "can": 1, + "redistribute": 1, + "it": 3, + "and/or": 1, + "modify": 5, + "under": 1, + "the": 10, + "terms": 1, + "General": 3, + "Public": 3, + "License": 3, + "as": 1, + "published": 1, + "by": 1, + "Free": 2, + "Software": 2, + "Foundation": 2, + "either": 1, + "version": 2, + "any": 1, + "later": 1, + "version.": 1, + "distributed": 1, + "in": 3, + "hope": 1, + "that": 2, + "will": 1, + "be": 2, + "useful": 1, + "but": 2, + "WITHOUT": 1, + "ANY": 1, + "WARRANTY": 1, + "without": 1, + "even": 1, + "implied": 1, + "warranty": 1, + "MERCHANTABILITY": 1, + "or": 3, + "FITNESS": 1, + "FOR": 1, + "A": 1, + "PARTICULAR": 1, + "PURPOSE.": 1, + "See": 1, + "for": 8, + "more": 1, + "details.": 1, + "You": 1, + "should": 2, + "have": 1, + "received": 1, + "a": 4, + "copy": 2, + "along": 1, + "with": 4, + "this": 1, + "see": 2, + "COPYING.": 1, + "If": 1, + "not": 1, + "write": 2, + "to": 4, + "Inc.": 1, + "Franklin": 1, + "Street": 1, + "Fifth": 1, + "Floor": 1, + "Boston": 1, + "MA": 1, + "USA.": 1, + "Commentary": 1, + "customise": 1, + "name": 8, + "point": 6, + "your": 1, + "release": 1, + "basic": 1, + "start": 13, + "M": 2, + "x": 2, + "julia.": 2, + "require": 2, + "auto": 1, + "alist": 9, + "table": 9, + "character": 1, + "quote": 2, + "transpose": 1, + "syntax": 7, + "entry": 4, + ".": 40, + "Syntax": 3, + "inside": 1, + "char": 6, + "defvar": 5, + "let": 3, + "make": 4, + "defconst": 5, + "regex": 5, + "unquote": 1, + "forloop": 1, + "subset": 2, + "regexp": 6, + "font": 6, + "lock": 6, + "defaults": 2, + "list": 3, + "identity": 1, + "keyword": 2, + "face": 4, + "constant": 1, + "cons": 1, + "function": 7, + "keep": 2, + "string": 8, + "paragraph": 3, + "concat": 7, + "page": 2, + "delimiter": 2, + "separate": 1, + "ignore": 2, + "fill": 1, + "prefix": 2, + "t": 6, + "final": 1, + "newline": 1, + "comment": 6, + "add": 4, + "skip": 1, + "column": 1, + "indent": 8, + "S": 2, + "line": 5, + "calculate": 1, + "parse": 1, + "sexp": 1, + "comments": 1, + "style": 2, + "default": 1, + "ignored": 1, + "local": 6, + "process": 5, + "nil": 12, + "dump": 2, + "files": 1, + "_": 1, + "autoload": 1, + "defun": 5, + "send": 3, + "visibly": 1, + "temporary": 1, + "directory": 2, + "temp": 2, + "insert": 1, + "format": 3, + "load": 1, + "command": 5, + "get": 3, + "help": 3, + "topics": 1, + "&": 3, + "optional": 3, + "proc": 3, + "words": 1, + "vector": 1, + "com": 1, + "error": 6, + "s": 5, + "*in": 1, + "[": 3, + "n": 1, + "]": 3, + "*": 1, + "at": 5, + ".*": 2, + "+": 5, + "w*": 1, + "http": 1, + "//docs.julialang.org/en/latest/search/": 1, + "q": 1, + "%": 1, + "include": 1, + "funargs": 1, + "re": 2, + "args": 10, + "language": 1, + "STERM": 1, + "editor": 2, + "R": 2, + "pager": 2, + "versions": 1, + "Julia": 1, + "made": 1, + "available.": 1, + "String": 1, + "arguments": 2, + "used": 1, + "when": 2, + "starting": 1, + "group": 1, + "###autoload": 2, + "interactive": 2, + "setq": 2, + "customize": 5, + "emacs": 1, + "<": 1, + "hook": 4, + "complete": 1, + "object": 2, + "completion": 4, + "functions": 2, + "first": 1, + "if": 4, + "fboundp": 1, + "end": 1, + "workaround": 1, + "set": 3, + "variable": 3, + "post": 1, + "run": 2, + "settings": 1, + "notably": 1, + "null": 1, + "dribble": 1, + "buffer": 3, + "debugging": 1, + "only": 1, + "dialect": 1, + "current": 2, + "arg": 1, + "let*": 2, + "jl": 2, + "space": 1, + "just": 1, + "case": 1, + "read": 1, + "..": 3, + "multi": 1, + "...": 1, + "tb": 1, + "logo": 1, + "goto": 2, + "min": 1, + "while": 1, + "search": 1, + "forward": 1, + "replace": 1, + "match": 1, + "max": 1, + "inject": 1, + "code": 1, + "etc": 1, + "hooks": 1, + "busy": 1, + "funname": 5, + "eldoc": 1, + "show": 1, + "symbol": 2, + "aggressive": 1, + "car": 1, + "funname.start": 1, + "sequence": 1, + "nth": 1, + "W": 1, + "window": 2, + "width": 1, + "minibuffer": 1, + "length": 1, + "doc": 1, + "propertize": 1, + "use": 1, + "classes": 1, + "screws": 1, + "egrep": 1 }, "Erlang": { "SHEBANG#!escript": 2, @@ -38454,7 +38767,7 @@ "Ecl": 281, "edn": 227, "Elm": 628, - "Emacs Lisp": 3, + "Emacs Lisp": 1756, "Erlang": 1861, "fish": 636, "Forth": 1516, @@ -38554,7 +38867,7 @@ "Ecl": 1, "edn": 1, "Elm": 3, - "Emacs Lisp": 1, + "Emacs Lisp": 2, "Erlang": 4, "fish": 3, "Forth": 7, @@ -38635,5 +38948,5 @@ "Xtend": 2, "YAML": 1 }, - "md5": "60253432196336ca0df1d8d79a7f16ad" + "md5": "d233899b021f2ee7af2d7ff73c37a2b3" } \ No newline at end of file From 4b8f362eb7a92957bfebe99311d79cb5cc1c79ec Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 9 Jun 2013 20:53:48 -0500 Subject: [PATCH 5/9] Merge test cases --- test/test_blob.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/test_blob.rb b/test/test_blob.rb index 9690c6df..ae979e5c 100644 --- a/test/test_blob.rb +++ b/test/test_blob.rb @@ -63,9 +63,6 @@ class TestBlob < Test::Unit::TestCase def test_lines assert_equal ["module Foo", "end", ""], blob("Ruby/foo.rb").lines - end - - def test_lines_mac_format assert_equal ["line 1", "line 2", ""], blob("Text/mac.txt").lines assert_equal 473, blob("Emacs Lisp/ess-julia.el").lines.length end From b5681ca5595378ea2952e056180c282feba0b57e Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 9 Jun 2013 21:00:20 -0500 Subject: [PATCH 6/9] Correct count --- test/test_blob.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_blob.rb b/test/test_blob.rb index ae979e5c..56d9e6f2 100644 --- a/test/test_blob.rb +++ b/test/test_blob.rb @@ -64,7 +64,7 @@ class TestBlob < Test::Unit::TestCase def test_lines assert_equal ["module Foo", "end", ""], blob("Ruby/foo.rb").lines assert_equal ["line 1", "line 2", ""], blob("Text/mac.txt").lines - assert_equal 473, blob("Emacs Lisp/ess-julia.el").lines.length + assert_equal 475, blob("Emacs Lisp/ess-julia.el").lines.length end def test_size From 9c1d6e154cc564d82009b3ddcd54cfbf523383b3 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 9 Jun 2013 21:01:03 -0500 Subject: [PATCH 7/9] Always split lines on \n or \r --- lib/linguist/blob_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/linguist/blob_helper.rb b/lib/linguist/blob_helper.rb index 933c4563..2a5d26e2 100644 --- a/lib/linguist/blob_helper.rb +++ b/lib/linguist/blob_helper.rb @@ -241,7 +241,7 @@ module Linguist def lines @lines ||= if viewable? && data - data.split(line_split_character, -1) + data.split(/\r\n|\r|\n/, -1) else [] end From d907ab994047230a8e5749e7021520da9320d589 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 9 Jun 2013 21:02:11 -0500 Subject: [PATCH 8/9] Kill mac_format check, buggy --- lib/linguist/blob_helper.rb | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/lib/linguist/blob_helper.rb b/lib/linguist/blob_helper.rb index 2a5d26e2..583b2416 100644 --- a/lib/linguist/blob_helper.rb +++ b/lib/linguist/blob_helper.rb @@ -247,25 +247,6 @@ module Linguist end end - # Character used to split lines. This is almost always "\n" except when Mac - # Format is detected in which case it's "\r". - # - # Returns a split pattern string. - def line_split_character - @line_split_character ||= (mac_format?? "\r" : "\n") - end - - # Private: Is the data in ** Mac Format **. This format uses \r (0x0d) characters - # for line ends and does not include a \n (0x0a). - # - # Returns true when mac format is detected. - def mac_format? - return if !viewable? - if pos = data[0, 4096].index("\r") - data[pos + 1] != ?\n - end - end - # Public: Get number of lines of code # # Requires Blob#data From 3e3fb0cdfe6839d89a8bf43b070bb9f11dde1766 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Sun, 9 Jun 2013 21:02:55 -0500 Subject: [PATCH 9/9] Say why --- lib/linguist/blob_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/linguist/blob_helper.rb b/lib/linguist/blob_helper.rb index 583b2416..47031a49 100644 --- a/lib/linguist/blob_helper.rb +++ b/lib/linguist/blob_helper.rb @@ -9,7 +9,8 @@ require 'yaml' module Linguist # DEPRECATED Avoid mixing into Blob classes. Prefer functional interfaces - # like `Language.detect` over `Blob#language`. + # like `Language.detect` over `Blob#language`. Functions are much easier to + # cache and compose. # # Avoid adding additional bloat to this module. #