aboutsummaryrefslogtreecommitdiff
path: root/sx-search.el
blob: aefd12ea21093bdf9269f77d1cf3ed40be20dedc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
;;; sx-search.el --- searching for questions         -*- 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:

;; Implements search functionality.  The basic function is
;; `sx-search-get-questions', which returns an array of questions
;; according to a search term.
;;
;; This also defines a user-level command, `sx-search', which is an
;; interactive wrapper around `sx-search-get-questions' and
;; `sx-question-list-mode'.


;;; Code:

(require 'sx)
(require 'sx-question-list)
(require 'sx-tag)

(defvar sx-search--query-history nil
  "Query history for interactive prompts.")


;;; Basic function
(defun sx-search-get-questions (site page query &optional tags excluded-tags keywords)
  "Like `sx-question-get-questions', but restrict results by a search.

Perform search on SITE.  PAGE is an integer indicating which page
of results to return.  QUERY, TAGS, and EXCLUDED-TAGS restrict the
possible returned questions as per `sx-search'.

Either QUERY or TAGS must be non-nil, or the search will
fail.  EXCLUDED-TAGS is only is used if TAGS is also provided.

KEYWORDS is passed to `sx-method-call'."
  (sx-method-call 'search
    :keywords `((page . ,page)
                (sort . activity)
                (intitle . ,query)
                (tagged . ,tags)
                (nottagged . ,excluded-tags)
                ,@keywords)
    :site site
    :auth t
    :filter sx-browse-filter))


;;; User command
(defun sx-search (site query &optional tags excluded-tags)
  "Display search on SITE for question titles containing QUERY.
When TAGS is given, it is a lists of tags, one of which must
match.  When EXCLUDED-TAGS is given, it is a list of tags, none
of which is allowed to match.

Interactively, the user is asked for SITE and QUERY.  With a
prefix argument, the user is asked for everything."
  (interactive
   (let ((site (sx--maybe-site-prompt current-prefix-arg))
         (query (read-string
                 (format "Query (%s): "
                   (if current-prefix-arg "optional" "mandatory"))
                 ""
                 'sx-search--query-history))
         tags excluded-tags)
     (when (string= query "")
       (setq query nil))
     (when current-prefix-arg
       (setq tags (sx-tag-multiple-read
                   site (concat "Tags" (when query " (optional)"))))
       (when (and (not query) (string= "" tags))
         (sx-user-error "Must supply either QUERY or TAGS"))
       (setq excluded-tags
             (sx-tag-multiple-read site "Excluded tags (optional)")))
     (list site query tags excluded-tags)))
  
  ;; Here starts the actual function
  (sx-initialize)
  (with-current-buffer (get-buffer-create "*sx-search-result*")
    (sx-question-list-mode)
    (setq sx-question-list--next-page-function
          (lambda (page)
            (sx-search-get-questions
             sx-question-list--site page
             query tags excluded-tags)))
    (setq sx-question-list--site site)
    (sx-question-list-refresh 'redisplay)
    (switch-to-buffer (current-buffer))))

(provide 'sx-search)
;;; sx-search.el ends here

;; Local Variables:
;; indent-tabs-mode: nil
;; End: