summaryrefslogtreecommitdiff
path: root/tissue/skribilo.scm
blob: 8a0a9295f97d2b896a148635168c42a5e4b7d118 (plain)
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
;;; tissue --- Text based issue tracker
;;; Copyright © 2023 Arun Isaac <arunisaac@systemreboot.net>
;;;
;;; This file is part of tissue.
;;;
;;; tissue 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.
;;;
;;; tissue 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 tissue.  If not, see <https://www.gnu.org/licenses/>.

(define-module (tissue skribilo)
  #:use-module (rnrs conditions)
  #:use-module (rnrs exceptions)
  #:use-module (srfi srfi-26)
  #:use-module (ice-9 match)
  #:use-module (oop goops)
  #:use-module (skribilo ast)
  #:use-module (skribilo evaluator)
  #:use-module (skribilo reader)
  #:use-module (tissue document)
  #:use-module (tissue file-document)
  #:use-module (tissue utils)
  #:export (<skribilo-fragment>
            skribilo-fragment-filename
            skribilo-fragment-identifier
            document-fragment))

(define-class <skribilo-fragment> (<file-document>)
  (identifier #:getter skribilo-fragment-identifier #:init-keyword #:identifier)
  (reader-name #:getter skribilo-fragment-reader-name #:init-keyword #:reader-name))

(define (document-node file identifier reader-name)
  "Return @code{<markup>} object describing node identified by
@var{identifier} in @var{file} read using reader named by
@var{reader-name}."
  (find1-down (lambda (node)
                (and (is-a? node <markup>)
                     (markup-ident node)
                     (string=? (markup-ident node) identifier)))
              (call-with-input-file file
                (cut evaluate-ast-from-port <> #:reader (make-reader reader-name)))))

(define (fragment-text file identifier reader-name)
  "Return the full text of skribilo fragment in @var{file} identified by
@var{identifier} using reader named by @var{reader-name}."
  (call-with-output-string
    (cut ast->text
         (document-node file identifier reader-name)
         <>)))

(define* (document-fragment file identifier #:key (reader-name 'skribe))
  "Return a @code{<skribilo-fragment>} object describing node identified
by @var{identifier} in @var{file} read using reader named by
@var{reader-name}."
  (make <skribilo-fragment>
    #:title (ast->string
             (markup-option (document-node file identifier reader-name)
                            #:title))
    #:path file
    #:commits (commits-affecting-file file)
    #:identifier identifier
    #:reader-name reader-name
    #:snippet-source-text (fragment-text file identifier reader-name)))

(define-method (document-id-term (fragment <skribilo-fragment>))
  "Return the ID term for skribilo @var{fragment}."
  (string-append "Qskribilofragment."
                 (file-document-path fragment)
                 "#"
                 (skribilo-fragment-identifier fragment)))

(define (ast->text node port)
  "Serialize AST @var{node} into text suitable for indexing. Write
output to @var{port}."
  (cond
   ((is-a? node <node>)
    (for-each (match-lambda
                ((_ . value)
                 (display (ast->string value) port)))
              (node-options node))
    (newline port)
    (ast->text (node-body node) port))
   ((string? node)
    (display node port))
   ((number? node)
    (display (number->string node) port))
   ((list? node)
    (for-each (lambda (element)
                (ast->text element port) port)
              node))))

(define-method (document-text (fragment <skribilo-fragment>))
  "Return the full text of skribilo @var{fragment}."
  (fragment-text (file-document-path fragment)
                 (skribilo-fragment-identifier fragment)
                 (skribilo-fragment-reader-name fragment)))