aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtur Malabarba <bruce.connor.am@gmail.com>2014-12-09 15:10:26 +0000
committerArtur Malabarba <bruce.connor.am@gmail.com>2014-12-09 15:10:26 +0000
commitdb82dc546b528eef2487820381884c7c67e3683a (patch)
tree00fc5da4031932315956e79952aa4cce2e68e6db
parent2651764450b76bd6573cfea2b98f54beeae4f0f1 (diff)
parenta983476a59701f1cc01580b16fc5235360054adf (diff)
Merge branch 'master' into fix-@highligthing
Conflicts: test/tests.el
-rw-r--r--README.org3
-rw-r--r--sx-compose.el50
-rw-r--r--sx-filter.el2
-rw-r--r--sx-interaction.el2
-rw-r--r--sx-load.el50
-rw-r--r--sx-method.el2
-rw-r--r--sx-question-mode.el2
-rw-r--r--sx-question-print.el2
-rw-r--r--sx-question.el2
-rw-r--r--sx-request.el4
-rw-r--r--sx.el31
-rw-r--r--sx.org79
-rw-r--r--test/tests.el36
13 files changed, 223 insertions, 42 deletions
diff --git a/README.org b/README.org
index 460ba34..db47904 100644
--- a/README.org
+++ b/README.org
@@ -36,8 +36,7 @@ As always, =C-h m= is the definitive resource for the functions of this mode.
To install the development version, follow the usual steps:
- Clone this repository
- Add this directory to your ~load-path~
-- Issue ~(require 'sx)~
-- Issue ~(require 'sx-tab)~
+- Issue ~(require 'sx-load)~
This should give you access to the ~sx-tab-~ functions (the main entry points at
this time).
diff --git a/sx-compose.el b/sx-compose.el
index d7d3ff3..d8f3b23 100644
--- a/sx-compose.el
+++ b/sx-compose.el
@@ -43,7 +43,7 @@
;;; Faces and Variables
-(defvar sx-compose-before-send-hook nil
+(defvar sx-compose-before-send-hook nil
"Hook run before POSTing to the API.
Functions are called without arguments and should return non-nil.
@@ -54,7 +54,7 @@ notifying the user.
Current buffer is the compose-mode buffer whose content is about
to be POSTed.")
-(defvar sx-compose-after-send-functions nil
+(defvar sx-compose-after-send-functions nil
"Hook run after POSTing to the API.
Functions on this hook should take two arguments, the
`sx-compose-mode' buffer (which not be live) and the data
@@ -70,12 +70,15 @@ Is invoked between `sx-compose-before-send-hook' and
(defvar sx-compose--question-headers
(concat
#("Title: " 0 7 (intangible t read-only t rear-nonsticky t))
+ "%s"
#("\n" 0 1 (read-only t))
#("Tags : " 0 7 (read-only t intangible t rear-nonsticky t))
+ "%s"
#("\n" 0 1 (read-only t rear-nonsticky t))
- #("________________________________________\n\n"
- 0 42 (read-only t rear-nonsticky t intangible t
- sx-compose-separator t)))
+ #("________________________________________\n"
+ 0 41 (read-only t rear-nonsticky t intangible t
+ sx-compose-separator t))
+ "\n")
"Headers inserted when composing a new question.
Used by `sx-compose-create'.")
@@ -129,9 +132,9 @@ contents to the API, then calls `sx-compose-after-send-functions'."
;;; Functions to help preparing buffers
(defun sx-compose-create (site parent &optional before-functions after-functions)
"Create an `sx-compose-mode' buffer.
-SITE is the site where it will be posted.
+SITE is the site where it will be posted.
-If composing questions, PARENT is nil.
+If composing questions, PARENT is nil.
If composing answers, it is the `question_id'.
If editing answers or questions, it should be the alist data
related to that object.
@@ -172,19 +175,32 @@ respectively added locally to `sx-compose-before-send-hook' and
(add-hook 'sx-compose-after-send-functions it nil t))
;; If the buffer is empty, the draft didn't exist. So prepare the
;; question.
- (when (and is-question (string= (buffer-string) ""))
- (let ((inhibit-point-motion-hooks))
- (insert sx-compose--question-headers)
- (goto-char (point-min))
- (goto-char (line-end-position))))
- (when (consp parent)
- (when (or (string= (buffer-string) "")
- (y-or-n-p "Draft buffer exists. Reset it? "))
+ (when (or (string= (buffer-string) "")
+ (y-or-n-p "Draft buffer exists. Reset it? "))
+ (let ((inhibit-point-motion-hooks t)
+ (inhibit-read-only t))
(erase-buffer)
- (insert (cdr (assoc 'body_markdown parent)))))
+ (when (consp parent)
+ (insert (cdr (assoc 'body_markdown parent))))
+ (when is-question
+ (sx-compose--print-question-headers
+ (when (consp parent) parent))
+ (unless (consp parent)
+ (goto-char (point-min))
+ (goto-char (line-end-position))))))
;; Return the buffer
(current-buffer))))
+(defun sx-compose--print-question-headers (question)
+ "Print question headers for the compose buffer.
+If QUESTION is non-nil, fill the headers with the data from
+QUESTION."
+ (sx-assoc-let question
+ (goto-char (point-min))
+ (insert
+ (format sx-compose--question-headers
+ (or .title "") (mapconcat #'identity .tags " ")))))
+
(defun sx-compose--generate-keywords (is-question)
"Reading current buffer, generate a keywords alist.
Keywords meant to be used in `sx-method-call'.
@@ -194,7 +210,7 @@ other keywords are read from the header "
`(,@(when is-question
(let ((inhibit-point-motion-hooks t)
(inhibit-read-only t)
- (header-end
+ (header-end
(next-single-property-change
(point-min) 'sx-compose-separator))
keywords)
diff --git a/sx-filter.el b/sx-filter.el
index 38084b9..8c00c12 100644
--- a/sx-filter.el
+++ b/sx-filter.el
@@ -1,4 +1,4 @@
-;;; sx-filter.el --- filters -*- lexical-binding: t; -*-
+;;; sx-filter.el --- Handles retrieval of filters. -*- lexical-binding: t; -*-
;; Copyright (C) 2014 Sean Allred
diff --git a/sx-interaction.el b/sx-interaction.el
index 89050c3..9b63e0a 100644
--- a/sx-interaction.el
+++ b/sx-interaction.el
@@ -230,7 +230,7 @@ TEXT is a string. Interactively, it is read from the minibufer."
:url-method "POST"
:filter sx-browse-filter
:site .site
- :keywords `((body ,text)))))
+ :keywords `((body . ,text)))))
;; The api returns the new DATA.
(when (> (length result) 0)
(sx--add-comment-to-object
diff --git a/sx-load.el b/sx-load.el
new file mode 100644
index 0000000..659f54b
--- /dev/null
+++ b/sx-load.el
@@ -0,0 +1,50 @@
+;;; sx-load.el --- Load all files of the sx package.
+
+;; 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:
+
+;;; Code:
+(mapc #'require
+ '(sx
+ sx-time
+ sx-auth
+ sx-button
+ sx-cache
+ sx-compose
+ sx-encoding
+ sx-favorites
+ sx-filter
+ sx-interaction
+ sx-method
+ sx-networks
+ sx-question
+ sx-question-list
+ sx-question-mode
+ sx-question-print
+ sx-request
+ sx-site
+ sx-tab
+ ))
+
+(provide 'sx-load)
+;;; sx-load.el ends here
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End:
diff --git a/sx-method.el b/sx-method.el
index 83455b8..5646772 100644
--- a/sx-method.el
+++ b/sx-method.el
@@ -1,4 +1,4 @@
-;;; sx-method.el --- method calls
+;;; sx-method.el --- Main interface for API method calls. -*- lexical-binding: t; -*-
;; Copyright (C) 2014 Sean Allred
diff --git a/sx-question-mode.el b/sx-question-mode.el
index bccb658..ccd9433 100644
--- a/sx-question-mode.el
+++ b/sx-question-mode.el
@@ -1,4 +1,4 @@
-;;; sx-question-mode.el --- Creating the buffer that displays questions
+;;; sx-question-mode.el --- Major-mode for displaying a question. -*- lexical-binding: t; -*-
;; Copyright (C) 2014 Artur Malabarba
diff --git a/sx-question-print.el b/sx-question-print.el
index 11a3e11..c32c3eb 100644
--- a/sx-question-print.el
+++ b/sx-question-print.el
@@ -1,4 +1,4 @@
-;;; sx-question-print.el --- Populating the question-mode buffer with content.
+;;; sx-question-print.el --- Populating the question-mode buffer with content. -*- lexical-binding: t; -*-
;; Copyright (C) 2014 Artur Malabarba
diff --git a/sx-question.el b/sx-question.el
index c4b2445..fea8978 100644
--- a/sx-question.el
+++ b/sx-question.el
@@ -1,4 +1,4 @@
-;;; sx-question.el --- question logic
+;;; sx-question.el --- Base question logic. -*- lexical-binding: t; -*-
;; Copyright (C) 2014 Sean Allred
diff --git a/sx-request.el b/sx-request.el
index 6be363d..a17a982 100644
--- a/sx-request.el
+++ b/sx-request.el
@@ -1,4 +1,4 @@
-;;; sx-request.el --- requests and url manipulation -*- lexical-binding: t; -*-
+;;; sx-request.el --- Requests and url manipulation. -*- lexical-binding: t; -*-
;; Copyright (C) 2014 Sean Allred
@@ -188,7 +188,7 @@ false, use the symbol `false'. Each element is processed with
(concat
(sx--thing-as-string (car pair))
"="
- (sx--thing-as-string (cdr pair) kv-sep)))
+ (sx--thing-as-string (cdr pair) kv-sep t)))
(delq nil (mapcar
(lambda (pair)
(when (cdr pair) pair))
diff --git a/sx.el b/sx.el
index 1c0ae9f..0bacad2 100644
--- a/sx.el
+++ b/sx.el
@@ -115,19 +115,32 @@ See `format'."
(let ((echo (get-text-property (point) 'help-echo)))
(when echo (message "%s" echo))))
-(defun sx--thing-as-string (thing &optional sequence-sep)
+(defun sx--thing-as-string (thing &optional sequence-sep url-hexify)
"Return a string representation of THING.
If THING is already a string, just return it.
Optional argument SEQUENCE-SEP is the separator applied between
-elements of a sequence."
- (cond
- ((stringp thing) thing)
- ((symbolp thing) (symbol-name thing))
- ((numberp thing) (number-to-string thing))
- ((sequencep thing)
- (mapconcat #'sx--thing-as-string
- thing (if sequence-sep sequence-sep ";")))))
+elements of a sequence. If SEQUENCE-SEP is a list, use the first
+element for the top level joining, the second for the next level,
+etc. \";\" is used as a default.
+
+If optional argument URL-HEXIFY is non-nil, this function behaves
+as `url-hexify-string'; this option is only effective on strings
+and sequences of strings."
+ (let ((process (if url-hexify #'url-hexify-string #'identity))
+ (first-f (if (listp sequence-sep) #'car #'identity))
+ (rest-f (if (listp sequence-sep) #'cdr #'identity)))
+ (cond
+ ((stringp thing) (funcall process thing))
+ ((symbolp thing) (funcall process (symbol-name thing)))
+ ((numberp thing) (number-to-string thing))
+ ((sequencep thing)
+ (mapconcat (lambda (thing)
+ (sx--thing-as-string
+ thing (funcall rest-f sequence-sep) url-hexify))
+ thing (if sequence-sep
+ (funcall first-f sequence-sep)
+ ";"))))))
(defun sx--filter-data (data desired-tree)
"Filter DATA and return the DESIRED-TREE.
diff --git a/sx.org b/sx.org
index f866aa5..e9c1211 100644
--- a/sx.org
+++ b/sx.org
@@ -55,6 +55,14 @@ Emacs conventions. Of course, the core convention of Emacs is
arbitrary customizability -- [[#hooks][hack away]]!
* Basic Usage
+
+** Activation
+
+If you install ~SX~ with ~package-install~, you should have every
+needed command properly autoloaded. If you install it manually,
+require the ~sx-load~ file to make sure everything is correctly
+loaded.
+
** Authenticating
Use ~sx-auth-authenticate~. Calling this function will open up a
webpage on StackExchange that will prompt you to authorize this
@@ -67,7 +75,8 @@ a cache file.
** Browsing Questions
To browse a list of questions retrieved from the site, use
~sx-tab-frontpage~. This queries for a site, pulls the first page of
-questions for that site, and displays them in a list.
+questions for that site, and displays them in a list. Alternatively,
+use any of the other ~sx-tab-~ commands.
- Refresh the page with =g= or by scrolling past the top.
- Use =n=, =p=, =N=, =P= to navigate without viewing the question.
@@ -86,8 +95,27 @@ Scrolling past the bottom of the list fetches more questions.
# used only by contributors.
- ~sx-init-hook~ :: Run when ~sx-initialize~ is called.
+- ~sx-compose-before-send-hook~ :: Run before POSTing to the API from
+ a buffer in ~sx-compose-mode~. If any of the functions in this
+ hook, return nil, the transaction is cancelled.
+- ~sx-compose-after-send-functions~ :: Run after POSTing to the API
+ from a buffer in ~sx-compose-mode~, if the transaction was
+ successful.
* Contributing
+Contributions, be them to the code or to this document, are very much
+welcome. Both of these can be found at [[github.com/vermiculus/sx.el][the GitHub repository]]. The
+easiest way to contribute is to clone it, make your changes, and
+submit a pull request. If you prefer, you can also email a patch of
+your changes to one of the authors or maintainers listed in the header
+comments. But please, when you do, heed the following conventions.
+
+1. Contributions to the code which change or add user-facing
+ functionality should be accompanied by updates to this document.
+2. Both in code and in this document, sentences should end in double
+ space.
+
+** Contributing to this Document
This document is maintained in Org format. Updates to the source code
should be accompanied by updates to this document when user-facing
functionality is changed.
@@ -95,7 +123,7 @@ functionality is changed.
Note that some distinctions are made which may not be apparent when
viewing the document with Info.
-** Markup Conventions
+*** Markup Conventions
Markup is used consistently as follows:
- packages :: =package.el=
@@ -108,7 +136,7 @@ To make the Info export readable, lists and source code blocks are
separated from body text with a blank line (as to start a new
paragraph).
-** Document Attributes
+*** Document Attributes
Attributes should be given in uppercase:
#+BEGIN_SRC org
@@ -117,11 +145,54 @@ Attributes should be given in uppercase:
,#+END_SRC
#+END_SRC
-** Source Code Blocks
+*** Source Code Blocks
The language for Emacs Lisp source code blocks should be given as
=elisp= and its content should be indented by two spaces. See
~org-edit-src-content-indentation~.
+** Contributing to the Code
+Contributing to the code should be fairly straightforward. Each file
+has a descriptive header explaining its purpose. Still, to help you
+find your way around, we describe below the current project
+structure. This list is very loosely ordered form low to high-level.
+
+- ~sx.el~ - Utility functions used throughout the package. Essentially
+ every file indirectly requires this one. If you're adding a function
+ that's used by different parts of the package, add it to this file.
+- ~sx-time.el~ - Similar to ~sx.el~, but only contains a few
+ time-related functions.
+- ~sx-filter.el~ - Handles retrieval of filters.
+- ~sx-cache.el~ - Saves and restores persistent data between sessions.
+- ~sx-button.el~ - Defines all button types used throughout the
+ package. Currently used only by ~sx-question-print.el~.
+
+- ~sx-request.el~ - Requests and url manipulation. Backend used by
+ ~sx-method.el~. It shouldn't be necessary to use the functions in
+ this file outside ~sx-method.el~.
+- ~sx-method.el~ - Main interface for API method calls.
+
+- ~sx-favorites.el~ - Starred questions.
+- ~sx-networks.el~ - User network information.
+- ~sx-site.el~ - Browsing sites.
+- ~sx-auth.el~ - Handles user authentication.
+
+- ~sx-question.el~ - Base question logic. Holds several functions for
+ retrieving questions and for processing retrieved questions. Doesn't
+ do any sort of user interface, that is left for
+ ~sx-question-list.el~ and ~sx-question-mode.el~.
+- ~sx-question-list.el~ - Major-mode for navigating questions list.
+- ~sx-question-mode.el~ - User interface for displaying a
+ question. Creates the buffer and defines the major-mode.
+- ~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-compose.el~ - Major-mode for composing questions and answers.
+- ~sx-interaction.el~ - Voting, commenting, and otherwise interacting with questions.
+- ~sx-tab.el~ - Functions for viewing different tabs.
+
+- ~sx-load.el~ - Load all files of the sx package. Designed as an easy way in for users who install the package manually (since they don't have autoloads).
+
* COMMENT Local Variables
# LocalWords: StackExchange SX inbox sx API url json inline Org
# LocalWords: Markup keybinding keybindings customizability webpage
diff --git a/test/tests.el b/test/tests.el
index 56a5501..b997c6e 100644
--- a/test/tests.el
+++ b/test/tests.el
@@ -137,10 +137,42 @@
(ert-deftest sx--user-@name ()
"Tests macro expansion for `sx-assoc-let'"
(should
- (string=
+ (string=
(sx--user-@name '((display_name . "ĥÞßđłřğĝýÿñńśşšŝżźžçćčĉùúûüŭůòóôõöøőðìíîïıèéêëęàåáâäãåąĵ★")))
"@hTHssdlrggyynnsssszzzccccuuuuuuooooooooiiiiieeeeeaaaaaaaaj"))
(should
- (string=
+ (string=
(sx--user-@name '((display_name . "ĤÞßĐŁŘĞĜÝŸÑŃŚŞŠŜŻŹŽÇĆČĈÙÚÛÜŬŮÒÓÔÕÖØŐÐÌÍÎÏıÈÉÊËĘÀÅÁÂÄÃÅĄĴ")))
"@HTHssDLRGGYYNNSSSSZZZCCCCUUUUUUOOOOOOOOIIIIiEEEEEAAAAAAAAJ")))
+
+(ert-deftest thing-as-string ()
+ "Tests `sx--thing-as-string'"
+ (should
+ (string= (sx--thing-as-string
+ '(hello world (this is a test))
+ '(";" "+"))
+ "hello;world;this+is+a+test"))
+ (should
+ (string= (sx--thing-as-string
+ '(this is a test) '(";" "+"))
+ "this;is;a;test"))
+ (should
+ (string= (sx--thing-as-string
+ '(this is a test) "+")
+ "this+is+a+test"))
+ (should
+ (string= (sx--thing-as-string
+ '(this is a test))
+ "this;is;a;test"))
+ (should
+ (string= (sx--thing-as-string
+ 'test)
+ "test"))
+ (should
+ (string= (sx--thing-as-string
+ 'test&)
+ "test&"))
+ (should
+ (string= (sx--thing-as-string
+ 'test& nil t)
+ "test%26")))