aboutsummaryrefslogtreecommitdiffstats
path: root/src/signatures.h
blob: e2bfd9c154b6cdf276aaf082a6678c81683cc85c (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
/*
 * qtmaildir - a Qt6 mail client for notmuch-indexed Maildirs
 * Copyright (C) 2026 Danilo M. <danix@danix.xyz>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#pragma once

#include <QString>
#include <QStringList>

/// Signatures, as markdown files spliced into the composer's buffer.
///
/// Free functions over values, with no widget anywhere, matching
/// MarkdownFormat, MessageBuilder and DraftStore. The splice is the part worth
/// testing and it is testable with no painter.
///
/// MARKDOWN, and that is what makes this small: MessageBuilder already builds
/// text/plain from the buffer verbatim and text/html from MarkdownRenderer
/// over the same string, so a signature in the buffer yields both forms with
/// no change there and no second code path. One choice by the user serves both
/// parts, which is what the feature was asked for.
namespace Signatures {

/// Where a newly inserted signature goes, from [compose] signature_position.
enum class Position {
    End,        ///< The end of the buffer. The default and the user's habit.
    AboveQuote  ///< Before the first quoted line, or the end when there is none.
};

/// The stems of every `*.md` in \p dir, sorted, without the extension.
///
/// A missing or unreadable directory yields an empty list. That is not a
/// misconfiguration: it means the user keeps no signatures, and the switch
/// then offers only "None".
QStringList names(const QString &dir);

/// The content of `<dir>/<name>.md`, or empty when it cannot be read.
///
/// \p name is a stem from names(), never a path. It is rejected if it contains
/// a path separator, so a value arriving from the config file cannot reach
/// outside \p dir.
QString text(const QString &dir, const QString &name);

/// Returns \p buffer with \p signature spliced in.
///
/// Any signature already present is replaced; \p signature empty removes it
/// and inserts nothing, which is what "None" selects.
///
/// \p known is the text of every signature in the directory, and it is what
/// makes this non-destructive. A `-- ` delimiter is NOT sufficient authority
/// to delete what follows it: the block is replaced only when its text matches
/// one of \p known, and otherwise the new signature is INSERTED with nothing
/// removed. `-- ` reaches a buffer without the user ever choosing a signature,
/// most plausibly pasted in with quoted text from another client, and the
/// unguarded rule would silently delete everything after it.
///
/// The failure is therefore directional, which is the whole point: a wrong
/// guess adds a visible second signature, one undo away, rather than losing
/// the user's own writing.
QString replace(const QString &buffer, const QString &signature,
                const QStringList &known, Position position);

}  // namespace Signatures