From 3da6e5174cbb3a2d551a9862dd79655908e2e0fc Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Sun, 7 Dec 2014 01:15:37 +0000 Subject: Create sx-babel Has functions and a variable for font-locking pre blocks. --- sx-babel.el | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 sx-babel.el diff --git a/sx-babel.el b/sx-babel.el new file mode 100644 index 0000000..7da24a5 --- /dev/null +++ b/sx-babel.el @@ -0,0 +1,114 @@ +;;; sx-babel.el --- Font-locking pre blocks according to language. -*- lexical-binding: t; -*- + +;; Copyright (C) 2014 Artur Malabarba + +;; Author: Artur Malabarba + +;; 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 . + +;;; 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)) + "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 " "))) + (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 (cdr 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 + -- cgit v1.2.3 From 4898b1669b54a8afca3303e70f01a9825cbe01d1 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Sun, 7 Dec 2014 01:18:04 +0000 Subject: Patch sx and sx-question-print to use sx-babel. --- sx-question-print.el | 24 +++++++----------------- sx.el | 28 ---------------------------- 2 files changed, 7 insertions(+), 45 deletions(-) diff --git a/sx-question-print.el b/sx-question-print.el index 2a0a035..fe64392 100644 --- a/sx-question-print.el +++ b/sx-question-print.el @@ -431,29 +431,19 @@ 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 + (buffer-substring + (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 8e3e5d3..d5d9b75 100644 --- a/sx.el +++ b/sx.el @@ -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 -- cgit v1.2.3 From 42157310ba599a05dce1664080213e31ab00a2d4 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Mon, 8 Dec 2014 13:10:27 +0000 Subject: Don't require sx Requiring sx is not needed because the macro is autoloaded. --- sx-question-print.el | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sx-question-print.el b/sx-question-print.el index fe64392..6b65d70 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." -- cgit v1.2.3 From 635bbc2a3e410f5b97a3f20e5b790712cc873cc2 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Tue, 9 Dec 2014 14:13:31 +0000 Subject: Fix some implementation bugs --- sx-babel.el | 10 +++++++--- sx-question-print.el | 9 ++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/sx-babel.el b/sx-babel.el index 7da24a5..5544642 100644 --- a/sx-babel.el +++ b/sx-babel.el @@ -30,7 +30,11 @@ (defvar sx-babel-major-mode-alist `((,(rx (or "*" "#+")) org-mode) - (,(rx (or "[" "(" ";" "#(")) emacs-lisp-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. @@ -59,7 +63,7 @@ on a match.") (sx-babel--determine-and-activate-major-mode) (font-lock-fontify-region (point-min) (point-max)) (goto-char (point-min)) - (let ((space (make-string indent " "))) + (let ((space (make-string indent ?\s))) (while (not (eobp)) (insert space) (forward-line 1))) @@ -78,7 +82,7 @@ on a match.") (let ((kar (car cell))) (when (if (stringp kar) (looking-at kar) (funcall kar)) (setq alist nil) - (funcall (cdr cell))))))) + (funcall (cadr cell))))))) (defun sx-babel--unindent-buffer () "Remove absolute indentation in current buffer. diff --git a/sx-question-print.el b/sx-question-print.el index 6b65d70..653ebab 100644 --- a/sx-question-print.el +++ b/sx-question-print.el @@ -436,11 +436,10 @@ font-locking." (setq beg (point)))) (setq end (point)) (sx-babel--make-pre-button - (buffer-substring - (save-excursion - (goto-char beg) - (line-beginning-position)) - end))))) + (save-excursion + (goto-char beg) + (line-beginning-position)) + end)))) (provide 'sx-question-print) ;;; sx-question-print.el ends here -- cgit v1.2.3 From c8c59b246ef179fbd1829124e07efc2ea144f6db Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Tue, 9 Dec 2014 14:16:34 +0000 Subject: Update sx.org --- sx.org | 2 ++ 1 file changed, 2 insertions(+) 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. -- cgit v1.2.3 From 194a28541d8d2193872a4d83cef50567488a6338 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Tue, 9 Dec 2014 15:05:04 +0000 Subject: Require sx-babel on sx-load --- sx-load.el | 1 + 1 file changed, 1 insertion(+) diff --git a/sx-load.el b/sx-load.el index e29d439..b348ea1 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 -- cgit v1.2.3 From 79c03c20d14ddfe546c9f612bd9c8b1b1cb00b2c Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Fri, 12 Dec 2014 15:12:54 +0000 Subject: Autoload sx-authenticate This also removes the sx-authenticate alias and renames sx-auth-authenticate to sx-authenticate. I did this because I felt it wasn't helpful to have both. Whenever I hit `M-x sx-au ` the only completions offered were two identical, but differently named, commands. That's useless at best, confusing at worst. --- sx-auth.el | 5 ++--- sx-method.el | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) 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-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)) -- cgit v1.2.3 From 97d953b092198b7d43e5930fd80a28936ddfda04 Mon Sep 17 00:00:00 2001 From: Steve Purcell Date: Fri, 12 Dec 2014 18:45:19 +0000 Subject: Use package-file directive in Cask No need to repeat the metadata which in sx.el: cask knows how to read it. --- Cask | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Cask b/Cask index f0c70fb..a055f12 100644 --- a/Cask +++ b/Cask @@ -1,14 +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") - (development (depends-on "ert")) -- cgit v1.2.3 From 351e13583de4dd1060c2877611faa27c83e3b297 Mon Sep 17 00:00:00 2001 From: Steve Purcell Date: Fri, 12 Dec 2014 18:46:26 +0000 Subject: Update package description line --- sx.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sx.el b/sx.el index 53c636a..b5c5c66 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 -- cgit v1.2.3 From 302b5a0cf2222973b901c7856da3920705ebe24e Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Sat, 13 Dec 2014 00:18:12 +0000 Subject: HOTFIX: Mark question as read when displaying it. This is a pretty big bug because it was leading SX to think the question wasn't read, even though it was open. This, in turn, prevented the user from being able to do anything (vote, comment) on the question, since we prevent interaction with unread questions. --- sx-question-mode.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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) -- cgit v1.2.3