aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cask9
-rw-r--r--sx-auth.el5
-rw-r--r--sx-babel.el118
-rw-r--r--sx-load.el1
-rw-r--r--sx-method.el2
-rw-r--r--sx-question-mode.el4
-rw-r--r--sx-question-print.el27
-rw-r--r--sx.el30
-rw-r--r--sx.org2
9 files changed, 136 insertions, 62 deletions
diff --git a/Cask b/Cask
index f1bcb07..a055f12 100644
--- a/Cask
+++ b/Cask
@@ -1,15 +1,8 @@
-(package "stack-mode" "0" "Stack Exchange for Emacs")
-
(source gnu)
(source melpa-stable)
+(package-file "sx.el")
(files "sx*.el")
-(depends-on "json" "1.4")
-(depends-on "url")
-(depends-on "cl-lib")
-(depends-on "markdown-mode")
-(depends-on "let-alist")
-
(development
(depends-on "ert"))
diff --git a/sx-auth.el b/sx-auth.el
index b6c0411..fca5392 100644
--- a/sx-auth.el
+++ b/sx-auth.el
@@ -80,7 +80,8 @@ will be (METHOD . t)")
Keywords are of form (OBJECT TYPES) where TYPES is (FILTER FILTER
FILTER).")
-(defun sx-auth-authenticate ()
+;;;###autoload
+(defun sx-authenticate ()
"Authenticate this application.
Authentication is required to read your personal data (such as
notifications) and to write with the API (asking and answering
@@ -126,8 +127,6 @@ parsed and displayed prominently on the page)."
(error "You must enter this code to use this client fully"))
(sx-cache-set 'auth `((access_token . ,sx-auth-access-token)))))
-(defalias 'sx-authenticate #'sx-auth-authenticate)
-
(defun sx-auth--method-p (method &optional submethod)
"Check if METHOD is one that may require authentication.
If it has `auth-required' SUBMETHODs, or no submethod, return t."
diff --git a/sx-babel.el b/sx-babel.el
new file mode 100644
index 0000000..5544642
--- /dev/null
+++ b/sx-babel.el
@@ -0,0 +1,118 @@
+;;; sx-babel.el --- Font-locking pre blocks according to language. -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2014 Artur Malabarba
+
+;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
+
+;; 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 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, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file contains functions and a variable for font-locking the
+;; content of markdown pre blocks according to their language. The
+;; main configuration point, for both the user and the developer is
+;; the varuable `sx-babel-major-mode-alist', which see.
+
+
+;;; Code:
+(require 'sx-button)
+
+(defvar sx-babel-major-mode-alist
+ `((,(rx (or "*" "#+")) org-mode)
+ (,(rx (or "[" "(" ";" "#(")) emacs-lisp-mode)
+ ;; @TODO: Make shell-mode work here. Currently errors because it
+ ;; needs a process. `sh-mode' isn't as nice.
+ (,(rx (or "$ " "# ")) sh-mode)
+ )
+ "List of cons cells determining which major-mode to use when.
+Each car is a rule and each cdr is a major-mode. The first rule
+which is satisfied activates the major-mode.
+
+Point is moved to the first non-blank character before testing
+the rule, which can either be a string or a function. If it is a
+string, is tested as a regexp starting from point. If it is a
+function, is called with no arguments and should return non-nil
+on a match.")
+(put 'sx-babel-major-mode-alist 'risky-local-variable-p t)
+
+
+;;; Font-locking the text
+(defun sx-babel--make-pre-button (beg end)
+ "Turn the region between BEG and END into a button."
+ (let ((text (buffer-substring-no-properties beg end))
+ indent)
+ (with-temp-buffer
+ (insert text)
+ (setq indent (sx-babel--unindent-buffer))
+ (goto-char (point-min))
+ (make-text-button
+ (point-min) (point-max)
+ 'sx-button-copy (buffer-string)
+ :type 'sx-question-mode-code-block)
+ (sx-babel--determine-and-activate-major-mode)
+ (font-lock-fontify-region (point-min) (point-max))
+ (goto-char (point-min))
+ (let ((space (make-string indent ?\s)))
+ (while (not (eobp))
+ (insert space)
+ (forward-line 1)))
+ (setq text (buffer-string)))
+ (goto-char beg)
+ (delete-region beg end)
+ (insert text)))
+
+(defun sx-babel--determine-and-activate-major-mode ()
+ "Activate the major-mode most suitable for the current buffer."
+ (let ((alist sx-babel-major-mode-alist)
+ cell)
+ (while (setq cell (pop alist))
+ (goto-char (point-min))
+ (skip-chars-forward "\r\n[:blank:]")
+ (let ((kar (car cell)))
+ (when (if (stringp kar) (looking-at kar) (funcall kar))
+ (setq alist nil)
+ (funcall (cadr cell)))))))
+
+(defun sx-babel--unindent-buffer ()
+ "Remove absolute indentation in current buffer.
+Finds the least indented line, and removes that amount of
+indentation from all lines. Primarily designed to extract the
+content of markdown code blocks.
+
+Returns the amount of indentation removed."
+ (save-excursion
+ (goto-char (point-min))
+ (let (result)
+ ;; Get indentation of each non-blank line
+ (while (null (eobp))
+ (skip-chars-forward "[:blank:]")
+ (unless (looking-at "$")
+ (push (current-column) result))
+ (forward-line 1))
+ (when result
+ (setq result (apply #'min result))
+ ;; Build a regexp with the smallest indentation
+ (let ((rx (format "^ \\{0,%s\\}" result)))
+ (goto-char (point-min))
+ ;; Use this regexp to remove that much indentation
+ ;; throughout the buffer.
+ (while (and (null (eobp))
+ (search-forward-regexp rx nil 'noerror))
+ (replace-match "")
+ (forward-line 1))))
+ (or result 0))))
+
+(provide 'sx-babel)
+;;; sx-babel.el ends here
+
diff --git a/sx-load.el b/sx-load.el
index 659f54b..d71b8ed 100644
--- a/sx-load.el
+++ b/sx-load.el
@@ -25,6 +25,7 @@
sx-time
sx-auth
sx-button
+ sx-babel
sx-cache
sx-compose
sx-encoding
diff --git a/sx-method.el b/sx-method.el
index 5646772..4575b0f 100644
--- a/sx-method.el
+++ b/sx-method.el
@@ -91,7 +91,7 @@ Return the entire response as a complex alist."
;; 1. Need auth and warn user (interactive use)
((and method-auth (equal 'warn auth))
(user-error
- "This request requires authentication. Please run `M-x sx-auth-authenticate' and try again."))
+ "This request requires authentication. Please run `M-x sx-authenticate' and try again."))
;; 2. Need auth to populate UI, cannot provide subset
((and method-auth auth)
(setq call 'sx-request-fallback))
diff --git a/sx-question-mode.el b/sx-question-mode.el
index 19d7d16..5735f47 100644
--- a/sx-question-mode.el
+++ b/sx-question-mode.el
@@ -62,7 +62,9 @@ Returns the question buffer."
(sx-question-mode--erase-and-print-question data)))
(defun sx-question-mode--erase-and-print-question (data)
- "Erase contents of buffer and print question given by DATA."
+ "Erase contents of buffer and print question given by DATA.
+Also marks the question as read with `sx-question--mark-read'."
+ (sx-question--mark-read data)
(let ((inhibit-read-only t))
(erase-buffer)
(sx-question-mode)
diff --git a/sx-question-print.el b/sx-question-print.el
index c32c3eb..dc853ba 100644
--- a/sx-question-print.el
+++ b/sx-question-print.el
@@ -23,11 +23,9 @@
;;; Code:
(require 'markdown-mode)
(require 'sx-button)
-(eval-when-compile
- (require 'rx))
-
(require 'sx)
(require 'sx-question)
+(require 'sx-babel)
(defgroup sx-question-mode nil
"Customization group for sx-question-mode."
@@ -431,29 +429,18 @@ If ID is nil, use FALLBACK-ID instead."
"If there's a pre block ahead, handle it, skip it and return t.
Handling means to turn it into a button and remove erroneous
font-locking."
- (let (beg end text)
+ (let (beg end)
(when (markdown-match-pre-blocks
(save-excursion
(skip-chars-forward "\r\n[:blank:]")
(setq beg (point))))
(setq end (point))
- (setq text
- (sx--unindent-text
- (buffer-substring
- (save-excursion
- (goto-char beg)
- (line-beginning-position))
- end)))
- (put-text-property beg end 'display nil)
- (make-text-button
- beg end
- 'face 'markdown-pre-face
- 'sx-button-copy text
- :type 'sx-question-mode-code-block))))
+ (sx-babel--make-pre-button
+ (save-excursion
+ (goto-char beg)
+ (line-beginning-position))
+ end))))
(provide 'sx-question-print)
;;; sx-question-print.el ends here
-;; Local Variables:
-;; lexical-binding: t
-;; End:
diff --git a/sx.el b/sx.el
index bb7eddc..7dde8a7 100644
--- a/sx.el
+++ b/sx.el
@@ -1,4 +1,4 @@
-;;; sx.el --- core functions of the sx package.
+;;; sx.el --- StackExchange client
;; Copyright (C) 2014 Sean Allred
@@ -201,34 +201,6 @@ Anything before the (sub)domain is removed."
(rx string-start (or (and (0+ word) (optional ":") "//")))
"" url)))
-(defun sx--unindent-text (text)
- "Remove indentation from TEXT.
-Primarily designed to extract the content of markdown code
-blocks."
- (with-temp-buffer
- (insert text)
- (goto-char (point-min))
- (let (result)
- ;; Get indentation of each non-blank line
- (while (null (eobp))
- (skip-chars-forward "[:blank:]")
- (unless (looking-at "$")
- (push (current-column) result))
- (forward-line 1))
- (when result
- ;; Build a regexp with the smallest indentation
- (let ((rx (format "^ \\{0,%s\\}"
- (apply #'min result))))
- (goto-char (point-min))
- ;; Use this regexp to remove that much indentation
- ;; throughout the buffer.
- (while (and (null (eobp))
- (search-forward-regexp rx nil 'noerror))
- (replace-match "")
- (forward-line 1)))))
- ;; Return the buffer
- (buffer-string)))
-
;;; Printing request data
(defvar sx--overlays nil
diff --git a/sx.org b/sx.org
index e9c1211..7ccb51b 100644
--- a/sx.org
+++ b/sx.org
@@ -186,6 +186,8 @@ structure. This list is very loosely ordered form low to high-level.
- ~sx-question-print.el~ - Populating the question buffer with
content. Used by ~sx-question-mode.el~ to actually print the content
of a question.
+- ~sx-babel.el~ - Font-locking code blocks printed by
+ ~sx-question-print.el~ according to the language.
- ~sx-compose.el~ - Major-mode for composing questions and answers.
- ~sx-interaction.el~ - Voting, commenting, and otherwise interacting with questions.