~sircmpwn/aerc

embedded docs, configs and version v1 PROPOSED

Tom Grennan
Tom Grennan: 2
 doc: fix literal blocks
 embed version, license, help and config files

 25 files changed, 3813 insertions(+), 176 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~sircmpwn/aerc/patches/23057/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH 1/2] doc: fix literal blocks Export this patch

Tom Grennan
An indented literal block indicator (```) results this formatting error:

	$ git show HEAD:doc/aerc-templates.7.scd | scdoc >/dev/null
	Error at 49:3: Cannot deindent in literal block

Signed-off-by: Tom Grennan <tmgrennan@gmail.com>
---
 doc/aerc-templates.7.scd | 47 +++++++++++++++++-----------------------
 1 file changed, 20 insertions(+), 27 deletions(-)

diff --git a/doc/aerc-templates.7.scd b/doc/aerc-templates.7.scd
index 1d94cf1..e8fb1c9 100644
--- a/doc/aerc-templates.7.scd
+++ b/doc/aerc-templates.7.scd
@@ -45,14 +45,14 @@ available always.
	Example:

	Get the name of the first sender.
	```
```
	{{(index .From 0).Name}}
	```
```

	Get the email address of the first sender.
	```
```
	{{(index .From 0).Address}}
	```
```

*Date and Time*
	The date and time information is always available and can be easily
@@ -67,8 +67,9 @@ available always.

*Subject*
	The subject of the email is available for quoted reply and forward.

```
	{{.Subject}}
```

*MIME Type*
	MIME Type is available for quoted reply and forward.
@@ -79,10 +80,9 @@ available always.
*Original Message*
	When using quoted reply or forward, the original message is available in a
	field called ".OriginalText".

	```
```
	{{.OriginalText}}
	```
```

# TEMPLATE FUNCTIONS

@@ -91,58 +91,51 @@ aerc provides the following additional functions:

*wrap*
	Wrap the original text to the specified number of characters per line.

	```
```
	{{wrap 72 .OriginalText}}
	```
```

*quote*
	Prepends each line with "> ".

	```
```
	{{quote .OriginalText}}
	```
```

*exec*
	Execute external command, provide the second argument to its stdin.

	```
```
	{{exec `/usr/local/share/aerc/filters/html` .OriginalText}}
	```
```

*toLocal*
	Convert the date to the local timezone as specified by the locale.

	```
```
	{{toLocal .Date}}
	```
```

*dateFormat*
	Format date and time according to the format passed as the second argument.
	The format must be specified according to go's time package format.

	```
```
	{{dateFormat .Date "Mon Jan 2 15:04:05 -0700 MST 2006"}}
	```
```

*version*
	Returns the version of aerc, which can be useful for things like X-Mailer.

	```
	X-Mailer: aerc {{version}}
	```

*Function chaining*
	All of the template functions can be chained together if needed.

	Example: Automatic HTML parsing for text/html mime type messages
	```
```
	{{if eq .OriginalMIMEType "text/html"}}
	{{exec `/usr/local/share/aerc/filters/html` .OriginalText | wrap 72 | quote}}
	{{else}}
	{{wrap 72 .OriginalText | quote}}
	{{end}}
	```
```

# SEE ALSO

-- 
2.20.1

[PATCH 2/2] embed version, license, help and config files Export this patch

Tom Grennan
This uses the go1.16 feature to embed files. It also adds preemptive
options to show and install these files.

So, instead of:

	git clone https://git.sr.ht/~sircmpwn/aerc .
	make install

One may `go install` the program:

	go install git.sr.ht/~sircmpwn/aerc

VERSION

The preemptive -v option (aka version) now shows the embedded
VERSION content rather than the exported Version string value.
The default aerc make target now writes the VERSION file instead of
overwriting the exported string through ldflags.

A maintainer may mark a new release with,

	$ make release VERSION=<symver>

HELP

The :help runtime command and the new preemptive -h option (aka help)
now shows the embedded instead of installed man pages.

The embedded pages may also be installed to the primary `manpath` for
external view with,

	aerc help -i
	man aerc-config

Any installed man pages may be removed with,

	aerc help -u

CONFIG

The new preemptive config option may be used to list, show, and
non-destructively install/update embedded user configuration:

	aerc config		# list
	aerc config FILE	# show
	aerc config -i		# install
	aerc config -u		# uninstall (e.g. rm -r ~/.config/aerc)

When aerc is run without any arguments and $XDG_CONFIG_HOME/aerc doesn't
exist, it installs the embedded config before proceeding with account
configuration.

EXEC OPTIONS

The install and uninstall of help or config may include these options:

	-n	dryrun, note but don't run each invasive operation
	-v	verbose, note all invasive operations
	-q	quiet, suppress warnings

Signed-off-by: Tom Grennan <tmgrennan@gmail.com>
---
 .gitignore                                   |    4 -
 Makefile                                     |  150 +--
 VERSION                                      |    1 +
 aerc.go                                      |   66 +-
 assert/assert.go                             |  119 ++
 commands/help.go                             |   39 +-
 commands/term.go                             |    8 +-
 config/{aerc.conf.in => aerc.conf.tmpl}      |   14 +-
 doc/aerc-config.5                            | 1123 ++++++++++++++++++
 doc/aerc-imap.5                              |  132 ++
 doc/aerc-maildir.5                           |   50 +
 doc/aerc-notmuch.5                           |   97 ++
 doc/aerc-search.1                            |  115 ++
 doc/aerc-sendmail.5                          |   39 +
 doc/aerc-smtp.5                              |   96 ++
 doc/aerc-stylesets.7                         |  381 ++++++
 doc/aerc-templates.7                         |  269 +++++
 doc/aerc-tutorial.7                          |  218 ++++
 doc/aerc.1                                   |  620 ++++++++++
 doc/aerc.1.scd                               |   35 +-
 embedded.go                                  |  217 ++++
 go.mod                                       |    2 +-
 optional/optional.go                         |  147 +++
 config/default_styleset => stylesets/default |    0
 24 files changed, 3793 insertions(+), 149 deletions(-)
 create mode 100644 VERSION
 create mode 100644 assert/assert.go
 rename config/{aerc.conf.in => aerc.conf.tmpl} (94%)
 create mode 100644 doc/aerc-config.5
 create mode 100644 doc/aerc-imap.5
 create mode 100644 doc/aerc-maildir.5
 create mode 100644 doc/aerc-notmuch.5
 create mode 100644 doc/aerc-search.1
 create mode 100644 doc/aerc-sendmail.5
 create mode 100644 doc/aerc-smtp.5
 create mode 100644 doc/aerc-stylesets.7
 create mode 100644 doc/aerc-templates.7
 create mode 100644 doc/aerc-tutorial.7
 create mode 100644 doc/aerc.1
 create mode 100644 embedded.go
 create mode 100644 optional/optional.go
 rename config/default_styleset => stylesets/default (100%)

diff --git a/.gitignore b/.gitignore
index 5ea4190..049c37f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,3 @@
/aerc
log
raw.log
aerc.conf
*.1
*.5
*.7
diff --git a/Makefile b/Makefile
index 661acef..b1ae2c9 100644
--- a/Makefile
+++ b/Makefile
@@ -2,121 +2,77 @@
.SUFFIXES:
.SUFFIXES: .1 .5 .7 .1.scd .5.scd .7.scd

override undefine VERSION # don't allow local overrides, we want our version
_git_version=$(shell git describe --long --tags --dirty 2>/dev/null | sed 's/-/.r/;s/-/./')
ifeq ($(strip $(_git_version)),)
VERSION=0.5.2
else
VERSION=$(_git_version)
endif

VPATH=doc
PREFIX?=/usr/local
BINDIR?=$(PREFIX)/bin
SHAREDIR?=$(PREFIX)/share/aerc
MANDIR?=$(PREFIX)/share/man
GO?=go
GOFLAGS?=
SCDOC?=scdoc

GOSRC:=$(shell find . -name '*.go')
GOSRC+=go.mod go.sum
# A non-empty V enables verbose install/uninstall
V?=

aerc: $(GOSRC)
	$(GO) build $(GOFLAGS) \
		-ldflags "-X main.Prefix=$(PREFIX) \
		-X main.ShareDir=$(SHAREDIR) \
		-X main.Version=$(VERSION)" \
		-o $@
described := $(shell git describe --long --tags --dirty 2>/dev/null\
	| sed 's/-/.r/;s/-/./' || true)

aerc.conf: config/aerc.conf.in
	sed -e 's:@SHAREDIR@:$(SHAREDIR):g' > $@ < config/aerc.conf.in
head := $(shell git cat-file blob HEAD:VERSION 2>/dev/null || true)

debug: $(GOSRC)
	GOFLAGS="-tags=notmuch" \
	dlv debug --headless --listen localhost:4747 &>/dev/null
define version
echo '$1' > VERSION
git update-index -$(2)-skip-worktree VERSION
endef

DOCS := \
	aerc.1 \
	aerc-search.1 \
	aerc-config.5 \
	aerc-imap.5 \
	aerc-maildir.5 \
	aerc-sendmail.5 \
	aerc-notmuch.5 \
	aerc-smtp.5 \
	aerc-tutorial.7 \
	aerc-templates.7 \
	aerc-stylesets.7
dirty-version = $(if $(described),$(call version,$(described)))
clean-version = $(if $(head),$(call version,$(head),-no))

.1.scd.1:
	scdoc < $< > $@
GOSRC:=go.mod go.sum

.5.scd.5:
	scdoc < $< > $@
SCDS := $(wildcard doc/*.scd)
DOCS  = $(SCDS:.scd=)

.7.scd.7:
	scdoc < $< > $@
CONFS := $(wildcard config/*.conf config/*.tmpl)
CONFS += $(wildcard filters/* stylesets/* tempaltes/*)

doc: $(DOCS)
all: aerc

all: aerc aerc.conf doc
aerc: GOSRC+=$(shell find . -name '*.go')
aerc: $(GOSRC) $(CONFS) $(DOCS) LICENSE
	$(dirty-version)
	$(GO) build $(GOFLAGS)

install: | $(DOCS)
	$(dirty-version)
	$(GO) install $(GOFLAGS)
	aerc help -i$(if $V,v)

debug: $(GOSRC)
	GOFLAGS="-tags=notmuch" \
	dlv debug --headless --listen localhost:4747 &>/dev/null

%.1: %.1.scd; $(SCDOC) < $< > $@
%.5: %.5.scd; $(SCDOC) < $< > $@
%.7: %.7.scd; $(SCDOC) < $< > $@

# Exists in GNUMake but not in NetBSD make and others.
RM?=rm -f

clean:
	$(RM) $(DOCS) aerc.conf aerc

install: all
	mkdir -m755 -p $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man1 $(DESTDIR)$(MANDIR)/man5 $(DESTDIR)$(MANDIR)/man7 \
		$(DESTDIR)$(SHAREDIR) $(DESTDIR)$(SHAREDIR)/filters $(DESTDIR)$(SHAREDIR)/templates $(DESTDIR)$(SHAREDIR)/stylesets
	install -m755 aerc $(DESTDIR)$(BINDIR)/aerc
	install -m644 aerc.1 $(DESTDIR)$(MANDIR)/man1/aerc.1
	install -m644 aerc-search.1 $(DESTDIR)$(MANDIR)/man1/aerc-search.1
	install -m644 aerc-config.5 $(DESTDIR)$(MANDIR)/man5/aerc-config.5
	install -m644 aerc-imap.5 $(DESTDIR)$(MANDIR)/man5/aerc-imap.5
	install -m644 aerc-maildir.5 $(DESTDIR)$(MANDIR)/man5/aerc-maildir.5
	install -m644 aerc-sendmail.5 $(DESTDIR)$(MANDIR)/man5/aerc-sendmail.5
	install -m644 aerc-notmuch.5 $(DESTDIR)$(MANDIR)/man5/aerc-notmuch.5
	install -m644 aerc-smtp.5 $(DESTDIR)$(MANDIR)/man5/aerc-smtp.5
	install -m644 aerc-tutorial.7 $(DESTDIR)$(MANDIR)/man7/aerc-tutorial.7
	install -m644 aerc-templates.7 $(DESTDIR)$(MANDIR)/man7/aerc-templates.7
	install -m644 aerc-stylesets.7 $(DESTDIR)$(MANDIR)/man7/aerc-stylesets.7
	install -m644 config/accounts.conf $(DESTDIR)$(SHAREDIR)/accounts.conf
	install -m644 aerc.conf $(DESTDIR)$(SHAREDIR)/aerc.conf
	install -m644 config/binds.conf $(DESTDIR)$(SHAREDIR)/binds.conf
	install -m755 filters/hldiff $(DESTDIR)$(SHAREDIR)/filters/hldiff
	install -m755 filters/html $(DESTDIR)$(SHAREDIR)/filters/html
	install -m755 filters/plaintext $(DESTDIR)$(SHAREDIR)/filters/plaintext
	install -m644 templates/quoted_reply $(DESTDIR)$(SHAREDIR)/templates/quoted_reply
	install -m644 templates/forward_as_body $(DESTDIR)$(SHAREDIR)/templates/forward_as_body
	install -m644 config/default_styleset $(DESTDIR)$(SHAREDIR)/stylesets/default

RMDIR_IF_EMPTY:=sh -c '\
if test -d $$0 && ! ls -1qA $$0 | grep -q . ; then \
	rmdir $$0; \
fi'

uninstall:
	$(RM) $(DESTDIR)$(BINDIR)/aerc
	$(RM) $(DESTDIR)$(MANDIR)/man1/aerc.1
	$(RM) $(DESTDIR)$(MANDIR)/man1/aerc-search.1
	$(RM) $(DESTDIR)$(MANDIR)/man5/aerc-config.5
	$(RM) $(DESTDIR)$(MANDIR)/man5/aerc-imap.5
	$(RM) $(DESTDIR)$(MANDIR)/man5/aerc-maildir.5
	$(RM) $(DESTDIR)$(MANDIR)/man5/aerc-sendmail.5
	$(RM) $(DESTDIR)$(MANDIR)/man5/aerc-notmuch.5
	$(RM) $(DESTDIR)$(MANDIR)/man5/aerc-smtp.5
	$(RM) $(DESTDIR)$(MANDIR)/man7/aerc-tutorial.7
	$(RM) $(DESTDIR)$(MANDIR)/man7/aerc-templates.7
	$(RM) $(DESTDIR)$(MANDIR)/man7/aerc-stylesets.7
	$(RM) -r $(DESTDIR)$(SHAREDIR)
	${RMDIR_IF_EMPTY} $(DESTDIR)$(BINDIR)
	$(RMDIR_IF_EMPTY) $(DESTDIR)$(MANDIR)/man1
	$(RMDIR_IF_EMPTY) $(DESTDIR)$(MANDIR)/man5
	$(RMDIR_IF_EMPTY) $(DESTDIR)$(MANDIR)/man7
	$(RMDIR_IF_EMPTY) $(DESTDIR)$(MANDIR)
	$(clean-version)
	$(RM) aerc

release:
	$(if $(VERSION),$(call version,$(VERSION),-no),$(error \
		missing VERSION=<symver>))
	git update-index VERSION
	git commit -s -m "release $(VERSION)"
	git tag -s -m '' $(VERSION)

define uninstall
$(AERC) help -u$(if $V,v)
$(RM) $(AERC)
endef

uninstall: AERC=$(shell which aerc || true)
uninstall: ; $(if $(AERC),$(uninstall))

.DEFAULT_GOAL := all

.PHONY: all doc clean install uninstall debug
.PHONY: all clean install uninstall debug release
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..cb0c939
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
0.5.2
diff --git a/aerc.go b/aerc.go
index 33acb43..59f63ee 100644
--- a/aerc.go
+++ b/aerc.go
@@ -6,13 +6,15 @@ import (
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime/debug"
	"sort"
	"strings"
	"time"

	"git.sr.ht/~sircmpwn/getopt"
	"github.com/mattn/go-isatty"

	"git.sr.ht/~sircmpwn/aerc/assert"
	"git.sr.ht/~sircmpwn/aerc/commands"
	"git.sr.ht/~sircmpwn/aerc/commands/account"
	"git.sr.ht/~sircmpwn/aerc/commands/compose"
@@ -26,6 +28,8 @@ import (
	"git.sr.ht/~sircmpwn/aerc/widgets"
)

const usage = "usage: aerc [COMMAND [OPTION...] |  mailto:...]"

func getCommands(selected libui.Drawable) []*commands.Commands {
	switch selected.(type) {
	case *widgets.AccountView:
@@ -85,35 +89,35 @@ func getCompletions(aerc *widgets.Aerc, cmd string) []string {
	return completions
}

var (
	ShareDir string
	Version  string
)

func usage() {
	log.Fatal("Usage: aerc [-v] [mailto:...]")
}

func main() {
	opts, optind, err := getopt.Getopts(os.Args, "v")
	if err != nil {
		log.Print(err)
		usage()
		return
	}
	for _, opt := range opts {
		switch opt.Option {
		case 'v':
			fmt.Println("aerc " + Version)
	args := os.Args[1:]
	ac := filepath.Join(assert.UserConfig(), "aerc")
	ex := filepath.Join(ac, "examples")
	initDone := make(chan struct{})
	if len(args) > 0 {
		switch strings.TrimLeft(args[0], "-") {
		case "u", "usage":
			fmt.Println(usage)
			return
		case "h", "help", "man":
			help(args)
			return
		case "config":
			konfig(args)
			return
		case "license":
			io.Copy(os.Stdout, assert.Open(embedded, "LICENSE"))
			return
		case "v", "version":
			io.Copy(os.Stdout, assert.Open(embedded, "VERSION"))
			return
		default:
			if args[0][0] == '-' || len(args) > 1 {
				panic("invalid argument")
			}
		}
	}
	initDone := make(chan struct{})
	args := os.Args[optind:]
	if len(args) > 1 {
		usage()
		return
	} else if len(args) == 1 {
	if len(args) == 1 {
		arg := args[0]
		err := lib.ConnectAndExec(arg)
		if err == nil {
@@ -128,6 +132,10 @@ func main() {
				fmt.Fprintf(os.Stderr, "Failed to communicate to aerc: %v", err)
			}
		}(arg)
	} else {
		assert.IfNotExist(ac, func(_ string) {
			installEmbeddedConfig()
		})
	}

	var (
@@ -143,7 +151,7 @@ func main() {
	logger = log.New(logOut, "", log.LstdFlags)
	logger.Println("Starting up aerc")

	conf, err := config.LoadConfigFromFile(nil, ShareDir)
	conf, err := config.LoadConfigFromFile(&ac, ex)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to load config: %v\n", err)
		os.Exit(1)
@@ -186,7 +194,9 @@ func main() {
	}

	// set the aerc version so that we can use it in the template funcs
	templates.SetVersion(Version)
	version := strings.TrimSpace(string(assert.
		ReadFile(embedded, "VERSION")))
	templates.SetVersion(version)

	close(initDone)

diff --git a/assert/assert.go b/assert/assert.go
new file mode 100644
index 0000000..6cd7a1a
--- /dev/null
+++ b/assert/assert.go
@@ -0,0 +1,119 @@
package assert

import (
	"io"
	"io/fs"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"git.sr.ht/~sircmpwn/aerc/optional"
)

func Args(args []string, extra string) []string {
	remainder, err := optional.Args(args, extra)
	if err != nil {
		panic(err)
	}
	return remainder
}

func Open(fsys fs.FS, name string) fs.File {
	f, err := fsys.Open(name)
	if err != nil {
		panic(err)
	}
	return f
}

func ReadDir(fsys fs.FS, name string) []fs.DirEntry {
	dir, err := fs.ReadDir(fsys, name)
	if err != nil {
		panic(err)
	}
	return dir
}

func ReadFile(fsys fs.FS, name string) []byte {
	data, err := fs.ReadFile(fsys, name)
	if err != nil {
		panic(err)
	}
	return data
}

func Sub(fsys fs.FS, name string) fs.FS {
	sub, err := fs.Sub(fsys, name)
	if err != nil {
		panic(err)
	}
	return sub
}

func Manpath() []string {
	output, err := exec.Command("manpath").Output()
	if err != nil {
		panic(err)
	}
	return filepath.SplitList(strings.TrimSpace(string(output)))
}

func UserConfig() string {
	dir, err := os.UserConfigDir()
	if err != nil {
		panic(err)
	}
	return dir
}

func CopyFile(name string, r io.Reader, perm fs.FileMode) {
	if err := optional.CopyFile(name, r, perm); err != nil {
		panic(err)
	}
}

func IfNotExist(path string, f func(string)) {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		f(path)
	}
}

func Mkdir(dir string, perm os.FileMode) {
	if err := optional.Mkdir(dir, perm); err != nil {
		panic(err)
	}
}

func MkdirAll(dir string, perm os.FileMode) {
	if err := optional.MkdirAll(dir, perm); err != nil {
		panic(err)
	}
}

func ReadAll(r io.Reader) []byte {
	data, err := io.ReadAll(r)
	if err != nil {
		panic(err)
	}
	return data
}

func Remove(path string) {
	if err := optional.Remove(path); err != nil {
		panic(err)
	}
}

func RemoveAll(path string) {
	if err := optional.RemoveAll(path); err != nil {
		panic(err)
	}
}

func SedFile(name string, x optional.Executer, data interface{},
	perm fs.FileMode) {
	if err := optional.SedFile(name, x, data, perm); err != nil {
		panic(err)
	}
}
diff --git a/commands/help.go b/commands/help.go
index b27c2f0..bc2a0a4 100644
--- a/commands/help.go
+++ b/commands/help.go
@@ -2,10 +2,25 @@ package commands

import (
	"errors"
	"os"
	"strings"

	"git.sr.ht/~sircmpwn/aerc/widgets"
)

var HelpTopics = []string{
	"config",
	"imap",
	"maildir",
	"notmuch",
	"search",
	"sendmail",
	"smtp",
	"stylesets",
	"templates",
	"tutorial",
}

type Help struct{}

func init() {
@@ -13,19 +28,33 @@ func init() {
}

func (Help) Aliases() []string {
	return []string{"help"}
	return []string{"help", "man"}
}

func (Help) Complete(aerc *widgets.Aerc, args []string) []string {
	return nil
	var completions []string
	if len(args) == 0 {
		return HelpTopics
	}
	arg := args[len(args)-1]
	for _, topic := range HelpTopics {
		if strings.HasPrefix(topic, arg) {
			completions = append(completions, topic)
		}
	}
	return completions
}

func (Help) Execute(aerc *widgets.Aerc, args []string) error {
	page := "aerc"
	help := []string{"term", os.Args[0], "help", "aerc.1"}
	if len(args) == 2 {
		page = "aerc-" + args[1]
		for _, topic := range HelpTopics {
			if strings.HasPrefix(topic, args[1]) {
				help[3] = topic
			}
		}
	} else if len(args) > 2 {
		return errors.New("Usage: help [topic]")
	}
	return TermCore(aerc, []string{"term", "man", page})
	return TermCore(aerc, help)
}
diff --git a/commands/term.go b/commands/term.go
index c28c7d0..6012504 100644
--- a/commands/term.go
+++ b/commands/term.go
@@ -1,6 +1,7 @@
package commands

import (
	"os"
	"os/exec"

	"github.com/riywo/loginshell"
@@ -22,7 +23,6 @@ func (Term) Complete(aerc *widgets.Aerc, args []string) []string {
	return nil
}

// The help command is an alias for `term man` thus Term requires a simple func
func TermCore(aerc *widgets.Aerc, args []string) error {
	if len(args) == 1 {
		shell, err := loginshell.Shell()
@@ -35,7 +35,11 @@ func TermCore(aerc *widgets.Aerc, args []string) error {
	if err != nil {
		return err
	}
	tab := aerc.NewTab(term, args[1])
	tabname := args[1]
	if len(args) > 2 && args[1] == os.Args[0] {
		tabname = args[2]
	}
	tab := aerc.NewTab(term, tabname)
	term.OnTitle = func(title string) {
		if title == "" {
			title = args[1]
diff --git a/config/aerc.conf.in b/config/aerc.conf.tmpl
similarity index 94%
rename from config/aerc.conf.in
rename to config/aerc.conf.tmpl
index b9381a8..745b456 100644
--- a/config/aerc.conf.in
+++ b/config/aerc.conf.tmpl
@@ -70,8 +70,8 @@ next-message-on-delete=true
# The directories where the stylesets are stored. It takes a colon-separated
# list of directories.
#
# default: @SHAREDIR@/stylesets/
stylesets-dirs=@SHAREDIR@/stylesets/
# default: {{.}}/stylesets/
stylesets-dirs={{.}}/stylesets/

# Sets the styleset to use for the aerc ui elements.
#
@@ -163,9 +163,9 @@ address-book-cmd=
# You can also match on non-mimetypes, by prefixing with the header to match
# against (non-case-sensitive) and a comma, e.g. subject,text will match a
# subject which contains "text". Use header,~regex to match against a regex.
subject,~^\[PATCH=awk -f @SHAREDIR@/filters/hldiff
#text/html=@SHAREDIR@/filters/html
text/*=awk -f @SHAREDIR@/filters/plaintext
subject,~^\[PATCH=awk -f {{.}}/filters/hldiff
#text/html={{.}}/filters/html
text/*=awk -f {{.}}/filters/plaintext
#image/*=catimg -w $(tput cols) -

[triggers]
@@ -186,8 +186,8 @@ new-email=
# The directories where the templates are stored. It takes a colon-separated
# list of directories.
#
# default: @SHAREDIR@/templates/
template-dirs=@SHAREDIR@/templates/
# default: {{.}}/templates/
template-dirs={{.}}/templates/

# The template to be used for quoted replies.
#
diff --git a/doc/aerc-config.5 b/doc/aerc-config.5
new file mode 100644
index 0000000..43ccf5e
--- /dev/null
+++ b/doc/aerc-config.5
@@ -0,0 +1,1123 @@
.\" Generated by scdoc 1.9.0
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "aerc-config" "5" "2021-05-26"
.P
.SH NAME
.P
aerc-config - configuration file formats for \fBaerc\fR(1)
.P
.SH CONFIGURATION
.P
There are three aerc config files: \fBaerc.conf\fR, \fBbinds.conf\fR, and
\fBaccounts.conf\fR. The last one must be kept secret, as it may include your
account credentials. We look for these files in your XDG config home plus
"aerc", which defaults to ~/.config/aerc.
.P
Examples of these config files are typically included with your installation of
aerc and are usually installed in /usr/share/aerc.
.P
Each file uses the \fIini\fR format, and consists of sections with keys and values.
A line beginning with # is considered a comment and ignored, as are empty lines.
New sections begin with [section-name] on a single line, and keys and values are
separated with "=".
.P
.SH AERC.CONF
.P
This file is used for configuring the general appearance and behavior of aerc.
.P
.SS GENERAL OPTIONS
.P
These options are configured in the \fB[general]\fR section of aerc.conf.
.P
\fBdefault-save-path\fR
.RS 4
Used as a default path for save operations if no other path is specified.
.P
.RE
.SS UI OPTIONS
.P
These options are configured in the \fB[ui]\fR section of aerc.conf.
.P
\fBindex-format\fR
.RS 4
Describes the format for each row in a mailbox view. This field is
compatible with mutt's printf-like syntax.
.P
Default: %D %-17.17n %s
.P
.RE
.TS
allbox;c l
c l
c l
c l
c l
c l
c l
c l
c l
c l
c l
c l
c l
c l
c l
c l
c l
c l
c l
c l.
T{
\fBFormat specifier\fR
T}	T{
\fBDescription\fR
T}
T{
%%
T}	T{
literal %
T}
T{
%a
T}	T{
sender address
T}
T{
%A
T}	T{
reply-to address, or sender address if none
T}
T{
%C
T}	T{
message number
T}
T{
%d
T}	T{
formatted message timestamp
T}
T{
%D
T}	T{
formatted message timestamp converted to local timezone
T}
T{
%f
T}	T{
sender name and address
T}
T{
%F
T}	T{
author name, or recipient name if the message is from you. The address is shown if no name part.
T}
T{
%g
T}	T{
message labels (for example notmuch tags)
T}
T{
%i
T}	T{
message id
T}
T{
%n
T}	T{
sender name, or sender address if none
T}
T{
%r
T}	T{
comma-separated list of formatted recipient names and addresses
T}
T{
%R
T}	T{
comma-separated list of formatted CC names and addresses
T}
T{
%s
T}	T{
subject
T}
T{
%t
T}	T{
the (first) address the new email was sent to
T}
T{
%T
T}	T{
the account name which received the email
T}
T{
%u
T}	T{
sender mailbox name (e.g. "smith" in "smith@example.net")
T}
T{
%v
T}	T{
sender first name (e.g. "Alex" in "Alex Smith <smith@example.net>")
T}
T{
%Z
T}	T{
flags (O=old, N=new, r=answered, D=deleted, !=flagged, *=marked)
T}
.TE
.sp 1
\fBtimestamp-format\fR
.RS 4
See time.Time#Format at https://godoc.org/time#Time.Format
.P
Default: 2006-01-02 03:04 PM (ISO 8601 + 12 hour time)
.P
.RE
\fBsidebar-width\fR
.RS 4
Width of the sidebar, including the border. Set to zero to disable the
sidebar.
.P
Default: 20
.P
.RE
\fBempty-message\fR
.RS 4
Message to display when viewing an empty folder.
.P
Default: (no messages)
.P
.RE
\fBempty-dirlist\fR
.RS 4
Message to display when no folders exists or are all filtered.
.P
Default: (no folders)
.P
.RE
\fBmouse-enabled\fR
.RS 4
Enable mouse events in the ui, e.g. clicking and scrolling with the mousewheel
.P
Default: false
.P
.RE
\fBnew-message-bell\fR
.RS 4
Ring the bell when a new message is received.
.P
Default: true
.P
.RE
\fBpinned-tab-marker\fR
.RS 4
Marker to show before a pinned tab's name.
.P
Default: `
.P
.RE
\fBspinner\fR
.RS 4
Animation shown while loading, split by spinner-delimiter (below)
.P
Examples:
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
spinner = "-_-,_-_"
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
spinner = '. , .'
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
spinner = ",|,/,-"

.RE
.P
Default: "[..]    , [..]   ,  [..]  ,   [..] ,    [..],   [..] ,  [..]  , [..]   "
.P
.RE
\fBspinner-delimiter\fR
.RS 4
Spinner delimiter to split string into an animation
.P
Default: ","
.P
.RE
\fBsort\fR
.RS 4
List of space-separated criteria to sort the messages by, see \fBsort\fR
command in \fBaerc\fR(1) for reference. Prefixing a criterion with "-r "
reverses that criterion.
.P
Example: "from -r date"
.P
Default: ""
.P
.RE
\fBdirlist-format\fR
.RS 4
Describes the format string to use for the directory list
.P
Default: %n %>r
.P
.RE
.TS
allbox;c l
c l
c l
c l
c l.
T{
\fBFormat specifier\fR
T}	T{
\fBDescription\fR
T}
T{
%%
T}	T{
literal %
T}
T{
%n
T}	T{
directory name
T}
T{
%r
T}	T{
recent/unseen/total message count
T}
T{
%>X
T}	T{
make format specifier 'X' be right justified
T}
.TE
.sp 1
\fBnext-message-on-delete\fR
.RS 4
Moves to next message when the current message is deleted
.P
Default: true
.P
.RE
\fBcompletion-popovers\fR
.RS 4
Shows potential auto-completions for text inputs in popovers.
.P
Default: true
.P
.RE
\fBcompletion-delay\fR
.RS 4
How long to wait after the last input before auto-completion is triggered.
.P
Default: 250ms
.P
.RE
\fBstylesets-dirs\fR
.RS 4
The directories where the stylesets are stored. The config takes a
colon-seperated list of dirs.
.P
Default: "/usr/share/aerc/stylesets"
.P
.RE
\fBstyleset-name\fR
.RS 4
The name of the styleset to be used to style the ui elements. The
stylesets are stored in the 'stylesets' directory in the config
directory.
.P
Default: default
.P
Have a look at \fBaerc-stylesets\fR(7) as to how a styleset looks like.
.P
.P
.RE
.SS Contextual UI Configuration
.P
The UI configuration can be specialized for accounts, specific mail
directories and message subjects. The specializations are added using
contextual config sections based on the context.
.P
The contextual UI configuration is merged to the base UiConfig in the
following order:
\fBBase UIConfig > Account Context > Folder Context > Subject Context.\fR
.P
\fB[ui:account=<AccountName>]\fR
.RS 4
Adds account specific configuration with the account name.
.P
.RE
\fB[ui:folder=<FolderName>]\fR
.RS 4
Add folder specific configuration with the folder name.
.P
.RE
\fB[ui:folder~<Regex>]\fR
.RS 4
Add folder specific configuration for folders whose names match the regular
expression.
.P
.RE
\fB[ui:subject~<Regex>]\fR
.RS 4
Add specialized ui configuration for messages that match a given regular
expression.
.P
.RE
Example:
.nf
.RS 4
[ui:account=Work]
sidebar-width=\&.\&.\&.

[ui:folder=Sent]
index-format=\&.\&.\&.

[ui:folder~Archive/d+/\&.*]
index-format=\&.\&.\&.

[ui:subject~^[PATCH]
index-format=\&.\&.\&.
.fi
.RE
.P
.P
.SS VIEWER
.P
These options are configured in the \fB[viewer]\fR section of aerc.conf.
.P
\fBpager\fR
.RS 4
Specifies the pager to use when displaying emails. Note that some filters
may add ANSI escape sequences to add color to rendered emails, so you may
want to use a pager which supports ANSI.
.P
Default: less -R
.P
.RE
\fBalternatives\fR
.RS 4
If an email offers several versions (multipart), you can configure which
mimetype to prefer. For example, this can be used to prefer plaintext over
HTML emails.
.P
Default: text/plain,text/html
.P
.RE
\fBheader-layout\fR
.RS 4
Defines the default headers to display when viewing a message. To display
multiple headers in the same row, separate them with a pipe, e.g. "From|To".
Rows will be hidden if none of their specified headers are present in the
message.
.P
Default: From|To,Cc|Bcc,Date,Subject
.P
.RE
\fBshow-headers\fR
.RS 4
Default setting to determine whether to show full headers or only parsed
ones in message viewer.
.P
Default: false
.P
.RE
\fBalways-show-mime\fR
.RS 4
Whether to always show the mimetype of an email, even when it is just a single part.
.P
Default: false
.P
.RE
.SS COMPOSE
.P
These options are configured in the \fB[compose]\fR section of aerc.conf.
.P
\fBeditor\fR
.RS 4
Specifies the command to run the editor with. It will be shown in an
embedded terminal, though it may also launch a graphical window if the
environment supports it. Defaults to \fB$EDITOR\fR, or \fBvi\fR(1).
.P
.RE
\fBheader-layout\fR
.RS 4
Defines the default headers to display when composing a message. To display
multiple headers in the same row, separate them with a pipe, e.g. "To|From".
.P
Default: To|From,Subject
.P
.RE
\fBaddress-book-cmd\fR
.RS 4
Specifies the command to be used to tab-complete email addresses. Any
occurrence of "%s" in the address-book-cmd will be replaced with what the
user has typed so far.
.P
The command must output the completions to standard output, one completion
per line. Each line must be tab-delimited, with an email address occurring as
the first field. Only the email address field is required. The second field,
if present, will be treated as the contact name. Additional fields are
ignored.
.P
Example:
.RS 4
khard email --remove-first-line --parsable '%s'
.P
.RE
Default: none
.P
.RE
.SS FILTERS
.P
Filters allow you to pipe an email body through a shell command to render
certain emails differently, e.g. highlighting them with ANSI escape codes.
They are configured in the \fB[filters]\fR section of aerc.conf.
.P
The first filter which matches the email's mimetype will be used, so order
them from most to least specific.
.P
You can also match on non-mimetypes, by prefixing with the header to match
against (non-case-sensitive) and a comma, e.g. subject,text will match a
subject which contains "text". Use header,~regex to match against a regex.
.P
aerc ships with some default filters installed in the share directory (usually
\fI/usr/share/aerc/filters\fR). Note that these may have additional dependencies
that aerc does not have alone.
.P
.SS TRIGGERS
.P
Triggers specify commands to execute when certain events occur.
.P
They are configured in the \fB[triggers]\fR section of aerc.conf.
.P
\fBnew-email\fR
.RS 4
Executed when a new email arrives in the selected folder.
.P
e.g. new-email=exec notify-send "New email from %n" "%s"
.P
Default: ""
.P
Format specifiers from \fBindex-format\fR are expanded with respect to the new
message.
.P
.RE
.SS TEMPLATES
.P
Templates are used to populate the body of an email. The compose, reply
and forward commands can be called with the -T flag with the name of the
template name.
.P
aerc ships with some default templates installed in the share directory (usually
\fI/usr/share/aerc/templates\fR).
.P
These options are configured in the \fB[templates]\fR section of aerc.conf.
.P
\fBtemplate-dirs\fR
.RS 4
The directory where the templates are stored. The config takes a
colon-separated list of dirs.
.P
Default: "/usr/share/aerc/templates"
.P
.RE
\fBquoted-reply\fR
.RS 4
The template to be used for quoted replies.
.P
Default: "quoted_reply"
.P
.RE
\fBforwards\fR
.RS 4
The template to be used for forward as body.
.P
Default: "forward_as_body"
.P
.RE
.SH ACCOUNTS.CONF
.P
This file is used for configuring each mail account used for aerc. Each section
is the name of an account you want to configure, and the keys & values in that
section specify details of that account's configuration. In addition to the
options documented here, specific transports for incoming and outgoing emails
may have additional configuration parameters, documented on their respective man
pages.
.P
Note that many of these configuration options are written for you, such as
\fBsource\fR and \fBoutgoing\fR, when you run the account configuration wizard
(\fB:new-account\fR).
.P
\fBarchive\fR
.RS 4
Specifies a folder to use as the destination of the \fB:archive\fR command.
.P
Default: Archive
.P
.RE
\fBcopy-to\fR
.RS 4
Specifies a folder to copy sent mails to, usually "Sent".
.P
Default: none
.P
.RE
\fBdefault\fR
.RS 4
Specifies the default folder to open in the message list when aerc
configures this account.
.P
Default: INBOX
.P
.RE
\fBfolders\fR
.RS 4
Specifies the comma separated list of folders to display in the sidebar.
Names prefixed with ~ are interpreted as regular expressions.
.P
Default: all folders
.P
.RE
\fBfolders-exclude\fR
.RS 4
Specifies the comma separated list of folders to exclude from the sidebar.
Names prefixed with ~ are interpreted as regular expressions.
Note that this overrides anything from \fBfolders\fR.
.P
Default: no folders
.P
.RE
\fBfolders-sort\fR
.RS 4
Specifies a comma separated list of folders to be shown at the top of the
list in the provided order. Remaining folders will be sorted alphabetically.
.P
Default: none
.P
.RE
\fBfrom\fR
.RS 4
The default value to use for the From header in new emails. This should be
an RFC 5322-compatible string, such as "Your Name <you@example.org>".
.P
Default: none
.P
.RE
\fBaliases\fR
.RS 4
All aliases of the current account. These will be used to fill in the From:
field. Make sure that your email server accepts this value, or for example
use \fBaerc-sendmail\fR(5) in combination with msmtp and --read-envelope-from.
.P
Default: none
.P
.RE
\fBoutgoing\fR
.RS 4
Specifies the transport for sending outgoing emails on this account.  It
should be a connection string, and the specific meaning of each component
varies depending on the protocol in use.  See each protocol's man page for
more details:
.P
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
\fBaerc-smtp\fR(5)

.RE
.P
.RE
\fBoutgoing-cred-cmd\fR
.RS 4
Specifies an optional command that is run to get the outgoing account's
password. See each protocol's man page for more details.
.P
Default: none
.P
.RE
\fBpostpone\fR
.RS 4
Specifies the folder to save postponed messages to.
.P
Default: Drafts
.P
.RE
\fBsource\fR
.RS 4
Specifies the source for reading incoming emails on this account. This key
is required for all accounts. It should be a connection string, and the
specific meaning of each component varies depending on the protocol in use.
See each protocol's man page for more details:
.P
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
\fBaerc-imap\fR(5)
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
\fBaerc-maildir\fR(5)
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
\fBaerc-notmuch\fR(5)

.RE
.P
Default: none
.P
.RE
\fBsource-cred-cmd\fR
.RS 4
Specifies an optional command that is run to get the source account's
password. See each protocol's man page for more details.
.P
.RE
\fBsignature-file\fR
.RS 4
Specifies the file to read in order to obtain the signature to be added
to emails sent from this account.
.P
.RE
\fBsignature-cmd\fR
.RS 4
Specifies the command to execute in \fBsh\fR in order to obtain the
signature to be added to emails sent from this account. If the command
fails then \fBsignature-file\fR is used instead.
.P
.RE
.SH BINDS.CONF
.P
This file is used for configuring keybindings used in the aerc interactive
client. You may configure different keybindings for different contexts by
writing them into different \fB[sections]\fR of the ini file. The available contexts
are:
.P
\fB[messages]\fR
.RS 4
keybindings for the message list
.P
.RE
\fB[view]\fR
.RS 4
keybindings for the message viewer
.P
.RE
\fB[compose]\fR
.RS 4
keybindings for the message composer
.P
.RE
\fB[compose::editor]\fR
.RS 4
keybindings for the composer, when the editor is focused
.P
.RE
\fB[compose::review]\fR
.RS 4
keybindings for the composer, when reviewing the email before it's sent
.P
.RE
\fB[terminal]\fR
.RS 4
keybindings for terminal tabs
.P
.RE
You may also configure global keybindings by placing them at the beginning of
the file, before specifying any context-specific sections. For each \fBkey=value\fR
option specified, the \fIkey\fR is the keystrokes pressed (in order) to invoke this
keybinding, and \fIvalue\fR specifies keystrokes that aerc will simulate when the
keybinding is invoked. Generally this is used to execute commands, for example:
.P
.RS 4
rq = :reply -q<Enter>
.P
.RE
Pressing r, then q, will simulate typing in ":reply -q<Enter>", and execute
:reply -q accordingly. It is also possible to invoke keybindings recursively in
a similar fashion. Additionally, the following special options are available in
each binding context:
.P
\fB$noinherit\fR
.RS 4
If set to "true", global keybindings will not be effective in this context.
.P
Default: false
.P
.RE
\fB$ex\fR
.RS 4
This can be set to a keystroke which will bring up the command input in this
context.
.P
Default: <semicolon>
.P
.RE
In addition to letters, special keys may be specified in <angle brackets>. The
following special keys are supported:
.P
.TS
allbox;l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c
l c.
T{
\fBName\fR
T}	T{
\fBDescription\fR
T}
T{
space
T}	T{
" "
T}
T{
semicolon
T}	T{
;
T}
T{
tab
T}	T{

T}
T{
enter
T}	T{

T}
T{
up
T}	T{

T}
T{
down
T}	T{

T}
T{
right
T}	T{

T}
T{
left
T}	T{

T}
T{
pgup
T}	T{

T}
T{
pgdn
T}	T{

T}
T{
home
T}	T{

T}
T{
end
T}	T{

T}
T{
insert
T}	T{

T}
T{
delete
T}	T{

T}
T{
exit
T}	T{

T}
T{
cancel
T}	T{

T}
T{
print
T}	T{

T}
T{
pause
T}	T{

T}
T{
backtab
T}	T{

T}
T{
c-space
T}	T{
Ctrl+Space
T}
T{
c-a
T}	T{
Ctrl+a
T}
T{
c-b
T}	T{
Ctrl+b
T}
T{
c-c
T}	T{
Ctrl+c
T}
T{
c-d
T}	T{
Ctrl+d
T}
T{
c-e
T}	T{
Ctrl+e
T}
T{
c-f
T}	T{
Ctrl+f
T}
T{
c-g
T}	T{
Ctrl+g
T}
T{
c-h
T}	T{
Ctrl+h
T}
T{
c-i
T}	T{
Ctrl+i
T}
T{
c-j
T}	T{
Ctrl+j
T}
T{
c-k
T}	T{
Ctrl+k
T}
T{
c-l
T}	T{
Ctrl+l
T}
T{
c-m
T}	T{
Ctrl+m
T}
T{
c-n
T}	T{
Ctrl+n
T}
T{
c-o
T}	T{
Ctrl+o
T}
T{
c-p
T}	T{
Ctrl+p
T}
T{
c-q
T}	T{
Ctrl+q
T}
T{
c-r
T}	T{
Ctrl+r
T}
T{
c-s
T}	T{
Ctrl+s
T}
T{
c-t
T}	T{
Ctrl+t
T}
T{
c-u
T}	T{
Ctrl+u
T}
T{
c-v
T}	T{
Ctrl+v
T}
T{
c-w
T}	T{
Ctrl+w
T}
T{
c-x
T}	T{
Ctrl+x
T}
T{
c-y
T}	T{
Ctrl+y
T}
T{
c-z
T}	T{
Ctrl+z
T}
T{
c-]
T}	T{
Ctrl+]
T}
T{
c-[
T}	T{
Ctrl+[
T}
T{
c-^
T}	T{
Ctrl+^
T}
T{
c-_
T}	T{
Ctrl+_
T}
.TE
.sp 1
.SH SEE ALSO
.P
\fBaerc\fR(1) \fBaerc-imap\fR(5) \fBaerc-smtp\fR(5) \fBaerc-maildir\fR(5) \fBaerc-sendmail\fR(5)
\fBaerc-notmuch\fR(5) \fBaerc-stylesets\fR(7)
.P
.SH AUTHORS
.P
Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
source contributors. For more information about aerc development, see
https://git.sr.ht/~sircmpwn/aerc.
diff --git a/doc/aerc-imap.5 b/doc/aerc-imap.5
new file mode 100644
index 0000000..0754473
--- /dev/null
+++ b/doc/aerc-imap.5
@@ -0,0 +1,132 @@
.\" Generated by scdoc 1.9.0
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "aerc-imap" "5" "2021-05-26"
.P
.SH NAME
.P
aerc-imap - IMAP configuration for \fBaerc\fR(1)
.P
.SH SYNOPSIS
.P
aerc implements the IMAP protocol as specified by RFC 3501, with the following
IMAP extensions:
.P
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
IDLE (RFC 2177)

.RE
.P
.SH CONFIGURATION
.P
IMAP configuration may be done interactively with the :new-account command.
.P
In accounts.conf (see \fBaerc-config\fR(5)), the following IMAP-specific options are
available:
.P
\fBsource\fR
.RS 4
imap[s][+insecure|+oauthbearer]://username[:password]@hostname[:port]?[:oauth2_params]
.P
Remember that all fields must be URL encoded. The "@" symbol, when URL
encoded, is \fB%40\fR.
.P
The meaning of the scheme component is:
.P
\fBimap://\fR:
.RS 4
IMAP with STARTTLS
.P
.RE
\fBimap+insecure://\fR:
.RS 4
IMAP without STARTTLS
.P
.RE
\fBimaps\fR:
.RS 4
IMAP with TLS/SSL
.P
.RE
\fBimaps+oauthbearer://\fR
.RS 4
IMAP with TLS/SSL using OAUTHBEARER Authentication
.P
\fBoauth2_params:\fR
.P
If specified, the configured password is used as an refresh token that
is exchanged with an access token
.P
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
token_endpoint (required)
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
client_id (optional)
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
client_secret (optional)
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
scope (optional)

.RE
.P
Example:
imaps+oauthbearer://...?token_endpoint=https://...&client_id=
.P
.RE
.RE
\fBsource-cred-cmd\fR
.RS 4
Specifies the command to run to get the password for the IMAP
account. This command will be run using `sh -c [command]`. If a
password is specified in the \fBsource\fR option, the password will
take precedence over this command.
.P
Example:
.P
pass hostname/username
.P
.RE
.SH SEE ALSO
.P
\fBaerc\fR(1) \fBaerc-config\fR(5)
.P
.SH AUTHORS
.P
Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
source contributors. For more information about aerc development, see
https://git.sr.ht/~sircmpwn/aerc.
diff --git a/doc/aerc-maildir.5 b/doc/aerc-maildir.5
new file mode 100644
index 0000000..7e60cea
--- /dev/null
+++ b/doc/aerc-maildir.5
@@ -0,0 +1,50 @@
.\" Generated by scdoc 1.9.0
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "aerc-maildir" "5" "2021-05-26"
.P
.SH NAME
.P
aerc-maildir - maildir configuration for \fBaerc\fR(1)
.P
.SH SYNOPSIS
.P
aerc implements the maildir format.
.P
.SH CONFIGURATION
.P
Maildir accounts currently are not supported with the :new-account command and
must be added manually to the \fBaerc-config\fR(5) file.
.P
The following maildir-specific options are available:
.P
\fBsource\fR
.RS 4
maildir://path
.P
The \fBsource\fR indicates the path to the directory containing your maildirs
rather than one maildir specifically.
.P
The path portion of the URL following \fImaildir://\fR must be either an absolute
path prefixed by \fB/\fR or a path relative to your home directory prefixed with
\fB~\fR. For example:
.P
.RS 4
source = maildir:///home/me/mail
.P
source = maildir://~/mail
.P
.RE
.RE
.SH SEE ALSO
.P
\fBaerc\fR(1) \fBaerc-config\fR(5) \fBaerc-smtp\fR(5) \fBaerc-notmuch\fR(5)
.P
.SH AUTHORS
.P
Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
source contributors. For more information about aerc development, see
https://git.sr.ht/~sircmpwn/aerc.
diff --git a/doc/aerc-notmuch.5 b/doc/aerc-notmuch.5
new file mode 100644
index 0000000..7262c75
--- /dev/null
+++ b/doc/aerc-notmuch.5
@@ -0,0 +1,97 @@
.\" Generated by scdoc 1.9.0
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "aerc-notmuch" "5" "2021-05-26"
.P
.SH NAME
.P
aerc-notmuch - notmuch configuration for \fBaerc\fR(1)
.P
.SH SYNOPSIS
.P
aerc supports using the notmuch email system as a backend, for fast indexing
and searching.
.P
For this to be enabled, aerc needs to be build with notmuch support.
.br
Refer to the installation instructions for details.
.P
.SH CONFIGURATION
.P
Notmuch accounts currently are not supported with the :new-account command and
must be added manually.
.P
In accounts.conf (see \fBaerc-config\fR(5)), the following notmuch-specific
options are available:
.P
\fBsource\fR
.RS 4
notmuch://path
.P
The \fBsource\fR indicates the path to the directory containing your notmuch
database (usually a .notmuch folder).
.P
The path portion of the URL following \fInotmuch://\fR must be either an absolute
path prefixed by \fB/\fR or a path relative to your home directory prefixed with
\fB~\fR. For example:
.P
.RS 4
source = notmuch:///home/me/mail
.P
source = notmuch://~/mail
.P
.RE
.RE
\fBquery-map\fR
.RS 4
Path to a file containing a mapping from display name to notmuch query in
the form of NAME=QUERY.
.br
Multiple entries can be specified, one per line.
.br
Lines starting with '#' are ignored and serve as comments.
.P
e.g. inbox=tag:inbox and not tag:archived
.P
Default: none
.P
.RE
\fBexclude-tags\fR
.RS 4
Comma separated list of tags which will be excluded from query results,
unless explicitly mentioned in the query.
.br
This can for example be useful if you use an archive or spam tag.
.P
Default: none
.P
.RE
.SH USAGE
.P
Notmuch shows slightly different behaviour than for example imap.
.br
Some commands are simply unsupported because they have no proper counterpart
in notmuch, like :delete and :archive.
.br
Others are slightly different in semantics and mentioned below:
.P
\fBcf\fR <notmuch query>
.RS 4
The change folder command allows for arbitrary notmuch queries and should
usually be preferred over \fB:filter\fR as it will be much faster if you use
the notmuch database to do the filtering
.P
.P
.RE
.SH SEE ALSO
.P
\fBaerc\fR(1) \fBaerc-config\fR(5) \fBaerc-smtp\fR(5) \fBaerc-maildir\fR(5)
.P
.SH AUTHORS
.P
Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
source contributors. For more information about aerc development, see
https://git.sr.ht/~sircmpwn/aerc.
diff --git a/doc/aerc-search.1 b/doc/aerc-search.1
new file mode 100644
index 0000000..878de8a
--- /dev/null
+++ b/doc/aerc-search.1
@@ -0,0 +1,115 @@
.\" Generated by scdoc 1.9.0
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "aerc-search" "1" "2021-05-26"
.P
.SH IMAP
.P
\fBsearch\fR [-ruba] [-x <flag>] [-X <flag>] [-f <from>] [-t <to>] [-c <cc>] [terms...]
.RS 4
Searches the current folder for messages matching the given set of
conditions.
.P
Each space separated term of \fBterms\fR, if provided, is searched
case-insensitively among subject lines unless \fB-b\fR or \fB-a\fR are
provided.
.P
\fB-r\fR: Search for read messages
.P
\fB-u\fR: Search for unread messages
.P
\fB-x <flag>\fR, \fB-X <flag>\fR: Restrict search to messages with or without <flag>
.P
Use \fB-x\fR to search for messages with the flag set.
Use \fB-X\fR to search for messages without the flag set.
.P
Possible values are:
.P
Seen
.RS 4
Read messages
.P
.RE
Answered
.RS 4
Replied messages
.P
.RE
Flagged
.RS 4
Flagged messages
.P
.RE
\fB-b\fR: Search in the body of the messages
.P
\fB-a\fR: Search in the entire text of the messages
.P
\fB-f <from>\fR: Search for messages from <from>
.P
\fB-t <to>\fR: Search for messages to <to>
.P
\fB-c <cc>\fR: Search for messages cc'ed to <cc>
.P
.RE
.SH MAILDIR
.P
\fBsearch\fR [-ruba] [-x <flag>] [-X <flag>] [-f <from>] [-t <to>] [-c <cc>] [terms...]
.RS 4
Searches the current folder for messages matching the given set of
conditions.
.P
Each space separated term of \fBterms\fR, if provided, is searched
case-insensitively among subject lines unless \fB-b\fR or \fB-a\fR are
provided.
.P
\fB-r\fR: Search for read messages
.P
\fB-u\fR: Search for unread messages
.P
\fB-x <flag>\fR, \fB-X <flag>\fR: Restrict search to messages with or without <flag>
.P
Use \fB-x\fR to search for messages with the flag set.
Use \fB-X\fR to search for messages without the flag set.
.P
Possible values are:
.P
Seen
.RS 4
Read messages
.P
.RE
Answered
.RS 4
Replied messages
.P
.RE
Flagged
.RS 4
Flagged messages
.P
.RE
\fB-b\fR: Search in the body of the messages
.P
\fB-a\fR: Search in the entire text of the messages
.P
\fB-f <from>\fR: Search for messages from <from>
.P
\fB-t <to>\fR: Search for messages to <to>
.P
\fB-c <cc>\fR: Search for messages cc'ed to <cc>
.P
.RE
.SH NOTMUCH
.P
\fBsearch\fR <query...>
.RS 4
You can use the full notmuch query language as described in
\fBnotmuch-search-terms\fR(7).
.P
The query will only apply on top of the active folder query.
.P
Example: jump to next unread `:search tag:unread`
.RE
diff --git a/doc/aerc-sendmail.5 b/doc/aerc-sendmail.5
new file mode 100644
index 0000000..e47cd79
--- /dev/null
+++ b/doc/aerc-sendmail.5
@@ -0,0 +1,39 @@
.\" Generated by scdoc 1.9.0
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "aerc-sendmail" "5" "2021-05-26"
.P
.SH NAME
.P
aerc-sendmail - sendmail configuration for \fBaerc\fR(1)
.P
.SH SYNOPSIS
.P
aerc can defer to sendmail for the delivery of outgoing messages.
.P
.SH CONFIGURATION
.P
In accounts.conf (see \fBaerc-config\fR(5)), the following sendmail-specific
options are available:
.P
\fBoutgoing\fR
.RS 4
/path/to/sendmail
.P
This should be set to the path to the sendmail binary you wish to use,
which is generally /usr/bin/sendmail. aerc will execute it with a list of
recipients on the command line and pipe the message to deliver to stdin.
.P
.RE
.SH SEE ALSO
.P
\fBaerc\fR(1) \fBaerc-config\fR(5)
.P
.SH AUTHORS
.P
Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
source contributors. For more information about aerc development, see
https://git.sr.ht/~sircmpwn/aerc.
diff --git a/doc/aerc-smtp.5 b/doc/aerc-smtp.5
new file mode 100644
index 0000000..4128ac4
--- /dev/null
+++ b/doc/aerc-smtp.5
@@ -0,0 +1,96 @@
.\" Generated by scdoc 1.9.0
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "aerc-smtp" "5" "2021-05-26"
.P
.SH NAME
.P
aerc-smtp - SMTP configuration for \fBaerc\fR(1)
.P
.SH SYNOPSIS
.P
aerc implements the SMTP protocol as specified by RFC 5321.
.P
.SH CONFIGURATION
.P
SMTP configuration may be done interactively with the :new-account command.
.P
In accounts.conf (see \fBaerc-config\fR(5)), the following SMTP-specific options are
available:
.P
\fBoutgoing\fR
.RS 4
smtp[s][+plain|+login|+none|+oauthbearer]://username[:password]@hostname[:port]?[:oauth2_params]
.P
Remember that all fields must be URL encoded. The "@" symbol, when URL
encoded, is \fB%40\fR.
.P
The meaning of the scheme component is:
.P
\fBsmtp://\fR:
.RS 4
Unencrypted SMTP
.P
.RE
\fBsmtps://\fR:
.RS 4
SMTP with TLS/SSL
.P
.RE
Additionally, you can specify an authentication mechanism like so:
.P
\fB+none\fR:
.RS 4
No authentication is required to use this SMTP server. You may omit the
username and password in this case.
.P
.RE
\fB+plain\fR:
.RS 4
Authenticate with a username and password using AUTH PLAIN. This is the
default behavior.
.P
.RE
\fB+login\fR:
.RS 4
Authenticate with a username and password using AUTH LOGIN. This is an obsolete
protocol, but is required for some common webmail providers.
.P
.RE
\fB+oauthbearer\fR:
.RS 4
SMTP with TLS/SSL using OAUTHBEARER Authentication.  See documentation in
\fBaerc-imap\fR(5) for usage.
.P
.RE
.RE
\fBoutgoing-cred-cmd\fR
.RS 4
Specifies the command to run to get the password for the SMTP
account. This command will be run using `sh -c [command]`. If a
password is specified in the \fBoutgoing\fR option, the password will
take precedence over this command.
.P
Example:
.P
pass hostname/username
.P
.RE
\fBsmtp-starttls\fR
.RS 4
Set this to `yes` if the server uses STARTTLS. In that case you should also
use \fBsmtp\fR instead of \fBsmtps\fR.
.P
.RE
.SH SEE ALSO
.P
\fBaerc\fR(1) \fBaerc-config\fR(5)
.P
.SH AUTHORS
.P
Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
source contributors. For more information about aerc development, see
https://git.sr.ht/~sircmpwn/aerc.
diff --git a/doc/aerc-stylesets.7 b/doc/aerc-stylesets.7
new file mode 100644
index 0000000..95c7ae1
--- /dev/null
+++ b/doc/aerc-stylesets.7
@@ -0,0 +1,381 @@
.\" Generated by scdoc 1.9.0
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "aerc-stylesets" "7" "2021-05-26"
.P
.SH Name
.P
aerc-stylesets - styleset file specification for \fBaerc\fR(1)
.P
.SH SYNOPSIS
.P
aerc uses a simple configuration syntax to configure the styleset for
its ui.
.P
.SH Styleset Configuration
.P
Aerc uses a simple configuration file to describe a styleset. The
styleset is described as key, value pairs. In each line, the key
represents the style object it signifies and the color/atrribute of
that is modified.
.P
For example, in the line below, the foreground color of the
style object "msglist_unread" is set to "cornflowerblue"
.nf
.RS 4
msglist_unread\&.fg=cornflowerblue
.fi
.RE
.P
The configuration also allows wildcard matching of the style_objects
to configure multiple style objects at a time.
.P
.SS Style
The following options are available to be modified for each of the
style objects.
.P
\fBfg\fR
.RS 4
The foreground color of the style object is set.
.P
Syntax: `<style_object>.fg=<color>`
.P
.RE
\fBbg\fR
.RS 4
The background color of the style object is set.
.P
Syntax: `<style_object>.bg=<color>`
.P
.RE
\fBbold\fR
.RS 4
The bold attribute of the style object is set/unset.
.P
Syntax: `<style_object>.bold=<true|false|toggle>`
.P
.RE
\fBblink\fR
.RS 4
The blink attribute of the style object is set/unset.
\fIThe terminal needs to support blinking text\fR
.P
Syntax: `<style_object>.bold=<true|false|toggle>`
.P
.RE
\fBunderline\fR
.RS 4
The underline attribute of the style object is set/unset.
\fIThe terminal needs to support underline text\fR
.P
Syntax: `<style_object>.underline=<true|false|toggle>`
.P
.RE
\fBreverse\fR
.RS 4
Reverses the color of the style object. Exchanges the foreground
and background colors.
.P
Syntax: `<style_object>.reverse=<true|false|toggle>`
\fIIf the value is false, it doesn't change anything\fR
.P
.RE
\fBnormal\fR
.RS 4
All the attributes of the style object are unset.
.P
Syntax: `<style_object>.normal=<true>`
\fIThe value doesn't matter\fR
.P
.RE
\fBdefault\fR
.RS 4
Set the style object to the default style of the context. Usually
based on the terminal.
.P
Syntax: `<style_object>.default=<true>`
\fIThe value doesn't matter\fR
.P
.RE
.SS Style Objects
The style objects represent the various ui elements or ui instances for
styling.
.P
.TS
allbox;l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l
l l.
T{
\fBStyle Object\fR
T}	T{
\fBDescription\fR
T}
T{
default
T}	T{
The default style object used for normal ui elements while not using specialized configuration.
T}
T{
error
T}	T{
The style used to show errors.
T}
T{
warning 
T}	T{
The style used when showing warnings.
T}
T{
success
T}	T{
The style used for success messages.
T}
T{
title
T}	T{
The style object used to style titles in ui elements.
T}
T{
header
T}	T{
The style object used to style headers in ui elements.
T}
T{
statusline_default
T}	T{
The default style applied to the statusline.
T}
T{
statusline_error
T}	T{
The style used for error messages in statusline.
T}
T{
statusline_success
T}	T{
The style used for success messages in statusline.
T}
T{
msglist_default
T}	T{
The default style for messages in a message list.
T}
T{
msglist_unread
T}	T{
Unread messages in a message list.
T}
T{
msglist_read
T}	T{
Read messages in a message list.
T}
T{
msglist_flagged
T}	T{
The messages with the flagged flag.
T}
T{
msglist_deleted
T}	T{
The messages marked as deleted.
T}
T{
msglist_marked
T}	T{
The messages with the marked flag.
T}
T{
dirlist_default
T}	T{
The default style for directories in the directory list.
T}
T{
completion_default
T}	T{
The default style for the completion engine.
T}
T{
completion_gutter
T}	T{
The completion gutter.
T}
T{
completion_pill
T}	T{
The completion pill.
T}
T{
tab
T}	T{
The style for the tab bar.
T}
T{
stack
T}	T{
The style for ui stack element.
T}
T{
spinner
T}	T{
The style for the loading spinner.
T}
T{
border
T}	T{
The style used to draw borders. \fBOnly the background color is used\fR.
T}
T{
selector_default
T}	T{
The default style for the selector ui element.
T}
T{
selector_focused
T}	T{
The focused item in a selector ui element.
T}
T{
selector_chooser
T}	T{
The item chooser in a selector ui element.
T}
.TE
.sp 1
.SS fnmatch style wildcard matching
The styleset configuration can be made simpler by using the fnmatch
style wildcard matching for the style object.
.P
The special characters used in the fnmatch wildcards are:
.TS
allbox;l l
l l
l l.
T{
\fBPattern\fR
T}	T{
\fBMeaning\fR
T}
T{
*
T}	T{
Matches everything
T}
T{
?
T}	T{
Matches any single character
T}
.TE
.sp 1
For example, the following wildcards can be made using this syntax.
.TS
allbox;l l
l l
l l.
T{
\fBExample\fR
T}	T{
Description
T}
T{
*.fg=blue
T}	T{
Set the foreground color of all style objects to blue.
T}
T{
*list.bg=hotpink
T}	T{
Set the background color of all style objects that end in list  to hotpink.
T}
.TE
.sp 1
.SS Selected modifier
Selected modifier can be applied to any style object. The style provided for
the selected modifier are applied on top of the style object it corresponds to.
.P
If you would like to make sure message that are flagged as read in the msglist
appear in yellow foreground and black background. You can specify that with
this:
.P
.RS 4
msglist_default.selected.fg=yellow
.P
msglist_default.selected.bg=black
.P
.RE
If we specify the global style selected modifer using fnmatch as below:
.P
.RS 4
*.selected.reverse=toggle
.P
.RE
This toggles the reverse switch for selected version of all the style objects.
.P
.SS Layered styles
Some styles, (currently only the `msglist*` ones) are applied in layers. If
a style differs from the base (in this case `msglist_default`) then that style
applies, unless overridden by a higher layer. The order that `msglist` styles
are applied in is, from first to last:
.P
.nf
.RS 4
msglist_default
msglist_unread
msglist_read
msglist_flagged
msglist_deleted
msglist_marked
.fi
.RE
.P
So, the marked style will override all other msglist styles.
.P
.SS Colors
The color values are set using the values accepted by the tcell library.
The values can be one of the following.
.P
.RS 4
\fBdefault\fR
.RS 4
The color is set as per the system or terminal default.
.P
.RE
\fB<Color name>\fR
.RS 4
Any w3c approved color name is used to set colors for the style.
.P
.RE
\fB<Hex code>\fR
.RS 4
Hexcode for a color can be used. The format must be "#XXXXXX"
.P
.RE
.RE
diff --git a/doc/aerc-templates.7 b/doc/aerc-templates.7
new file mode 100644
index 0000000..e11b667
--- /dev/null
+++ b/doc/aerc-templates.7
@@ -0,0 +1,269 @@
.\" Generated by scdoc 1.9.0
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "aerc-templates" "7" "2021-05-26"
.P
.SH NAME
.P
aerc-templates - template file specification for \fBaerc\fR(1)
.P
.SH SYNOPSIS
.P
aerc uses the go "text/template" package for the template parsing.
Refer to the go text/template documentation for the general syntax.
.P
Template files are composed of headers, followed by a newline, followed by the
body text.
.P
Example:
.P
.nf
.RS 4
X-Clacks-Overhead: GNU Terry Pratchett

Hello,

Greetings,
Chuck
.fi
.RE
.P
If you have a template that doesn't add any header, it \fBmust\fR be preceded by a
newline, to avoid parsing parts of the body as header text.
.P
.SH MESSAGE DATA
.P
The following data can be used in templates. Though they are not all
available always.
.P
\fBAddresses\fR
.RS 4
An array of mail.Address. That can be used to add sender or recipient
names to the template.
.P
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
From: List of senders.
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
To: List of To recipients. Not always Available.
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
Cc: List of Cc recipients. Not always Available.
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
Bcc: List of Cc recipients. Not always Available.
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
OriginalFrom: List of senders of the original message.
Available for quoted reply and forward.

.RE
.P
Example:
.P
Get the name of the first sender.
.RE
.nf
.RS 4
	{{(index \&.From 0)\&.Name}}
.fi
.RE
.P
.RS 4
Get the email address of the first sender.
.RE
.nf
.RS 4
	{{(index \&.From 0)\&.Address}}
.fi
.RE
.P
\fBDate and Time\fR
.RS 4
The date and time information is always available and can be easily
formatted.
.P
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
Date: Date and Time information when the compose window is opened.
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
OriginalDate: Date and Time when the original message of received.
Available for quoted reply and forward.

.RE
.P
To format the date fields, \fIdateFormat\fR and \fItoLocal\fR are provided.
Refer to the \fITEMPLATE FUNCTIONS\fR section for details.
.P
.RE
\fBSubject\fR
.RS 4
The subject of the email is available for quoted reply and forward.
.RE
.nf
.RS 4
	{{\&.Subject}}
.fi
.RE
.P
\fBMIME Type\fR
.RS 4
MIME Type is available for quoted reply and forward.
.P
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
OriginalMIMEType: MIME type info of quoted mail part. Usually
"text/plain" or "text/html".

.RE
.P
.RE
\fBOriginal Message\fR
.RS 4
When using quoted reply or forward, the original message is available in a
field called ".OriginalText".
.RE
.nf
.RS 4
	{{\&.OriginalText}}
.fi
.RE
.P
.SH TEMPLATE FUNCTIONS
.P
Besides the standard functions described in go's text/template documentation,
aerc provides the following additional functions:
.P
\fBwrap\fR
.RS 4
Wrap the original text to the specified number of characters per line.
.RE
.nf
.RS 4
	{{wrap 72 \&.OriginalText}}
.fi
.RE
.P
\fBquote\fR
.RS 4
Prepends each line with "> ".
.RE
.nf
.RS 4
	{{quote \&.OriginalText}}
.fi
.RE
.P
\fBexec\fR
.RS 4
Execute external command, provide the second argument to its stdin.
.RE
.nf
.RS 4
	{{exec `/usr/local/share/aerc/filters/html` \&.OriginalText}}
.fi
.RE
.P
\fBtoLocal\fR
.RS 4
Convert the date to the local timezone as specified by the locale.
.RE
.nf
.RS 4
	{{toLocal \&.Date}}
.fi
.RE
.P
\fBdateFormat\fR
.RS 4
Format date and time according to the format passed as the second argument.
The format must be specified according to go's time package format.
.RE
.nf
.RS 4
	{{dateFormat \&.Date "Mon Jan 2 15:04:05 -0700 MST 2006"}}
.fi
.RE
.P
\fBversion\fR
.RS 4
Returns the version of aerc, which can be useful for things like X-Mailer.
.P
X-Mailer: aerc {{version}}
.P
.RE
\fBFunction chaining\fR
.RS 4
All of the template functions can be chained together if needed.
.P
Example: Automatic HTML parsing for text/html mime type messages
.RE
.nf
.RS 4
	{{if eq \&.OriginalMIMEType "text/html"}}
	{{exec `/usr/local/share/aerc/filters/html` \&.OriginalText | wrap 72 | quote}}
	{{else}}
	{{wrap 72 \&.OriginalText | quote}}
	{{end}}
.fi
.RE
.P
.SH SEE ALSO
.P
\fBaerc\fR(1) \fBaerc-config\fR(5)
.P
.SH AUTHORS
.P
Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
source contributors. For more information about aerc development, see
https://git.sr.ht/~sircmpwn/aerc.
diff --git a/doc/aerc-tutorial.7 b/doc/aerc-tutorial.7
new file mode 100644
index 0000000..30d31b8
--- /dev/null
+++ b/doc/aerc-tutorial.7
@@ -0,0 +1,218 @@
.\" Generated by scdoc 1.9.0
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "aerc-tutorial" "7" "2021-05-26"
.P
.SH NAME
.P
aerc - the world's best email client
.P
.SH INTRODUCTION
.P
Welcome to aerc! This tutorial will guide you through your first steps in using
the client. This tutorial is a man page - you can read it again later with
\fB:help tutorial\fR from aerc, or \fBman aerc-tutorial\fR from your terminal.
.P
First, let's introduce some basic keybindings. For convention, we'll use \fB<C-p>\fR
to represent Ctrl+p, which matches the convention used for writing keybindings
for aerc.
.P
\fB<C-p>\fR, \fB<C-n>\fR
.RS 4
Cycles to the previous or next tab
.P
.RE
Try using these now to switch between your message list and the tutorial. In
your message list, we use vim-style keys to get around.
.P
\fBk\fR, \fBj\fR
.RS 4
Scrolls up and down between messages
.P
.RE
\fB<C-u>\fR, \fB<C-d>\fR
.RS 4
Scrolls half a page up or down
.P
.RE
\fBg\fR, \fBG\fR
.RS 4
Selects the first or last message, respectively
.P
.RE
\fBK\fR, \fBJ\fR
.RS 4
Switches between folders in the sidebar
.P
.RE
\fB<Enter>\fR
.RS 4
Opens the selected message
.P
.RE
You can also search the selected folder with \fB/\fR, or filter with \fB\\\fR. When
searching you can use n and p to jump to the next and previous result.
Filtering hides any non-matching message.
.P
.SH THE MESSAGE VIEWER
.P
Press \fB<Enter>\fR to open a message. By default, the message viewer will display
your message using \fBless\fR(1). This should also have familiar, vim-like
keybindings for scrolling around in your message.
.P
Multipart messages (messages with attachments, or messages with several
alternative formats) show a part selector on the bottom of the message viewer.
.P
\fB<C-k>\fR, \fB<C-j>\fR
.RS 4
Cycle between parts of a multipart message
.P
.RE
\fBq\fR
.RS 4
Close the message viewer
.P
.RE
To show HTML messages, uncomment the \fBtext/html\fR filter in your aerc.conf
file (which is probably in ~/.config/aerc/) and install its dependencies: w3m
and dante-utils.
.P
You can also do many tasks you could do in the message list from here, like
replying to emails, deleting the email, or view the next and previous message
(\fBJ\fR and \fBK\fR).
.P
.SH COMPOSING MESSAGES
.P
Return to the message list by pressing \fBq\fR to dismiss the message viewer. Once
there, let's compose a message.
.P
\fBC\fR
.RS 4
Compose a new message
.P
.RE
\fBrr\fR
.RS 4
Reply-all to a message
.P
.RE
\fBrq\fR
.RS 4
Reply-all to a message, and pre-fill the editor with a quoted version of the
message being replied to
.P
.RE
\fBRr\fR
.RS 4
Reply to a message
.P
.RE
\fBRq\fR
.RS 4
Reply to a message, and pre-fill the editor with a quoted version of the
message being replied to
.P
.RE
For now, let's use \fBC\fR to compose a new message. The message composer will
appear. You should see To, From, and Subject lines, as well as your \fB$EDITOR\fR.
You can use \fB<Tab>\fR or \fB<C-j>\fR and \fB<C-k>\fR to cycle between these fields (tab
won't cycle between fields once you enter the editor, but \fB<C-j>\fR and \fB<C-k>\fR
will).
.P
Let's send an email to yourself. Note that the To and From headers expect RFC
5322 addresses, e.g. \fBJohn Doe <john@example.org>\fR, or simply
\fB<john@example.org>\fR. Separate multiple recipients with commas. Go ahead and
fill out an email, then close the editor.
.P
The message review screen is shown next. You have a chance now to revise the
email before it's sent. Press \fBy\fR to send the email if it looks good.
.P
\fBNote\fR: when using the terminal in the message view, you can summon aerc's ex
command line by using \fB<C-x>\fR. ':' is sent to the editor.
.P
.SH USING THE TERMINAL
.P
aerc comes with an embedded terminal, which you've already used to view and edit
emails. We can also use this for other purposes, such as referencing a git
repository while reviewing a patch. From the message list, we can use the
following keybindings to open a terminal:
.P
\fB<C-t>\fR
.RS 4
Opens a new terminal tab, running your shell
.P
.RE
\fB$\fR, \fB!\fR
.RS 4
Prompts for a command to run, then opens a new terminal tab running that
command
.P
.RE
\fB|\fR
.RS 4
Prompts for a command to run, then pipes the selected email into that
command and displays the result on a new terminal tab
.P
.RE
Try pressing \fB$\fR and entering "top". You can also use the \fB:cd\fR command to
change aerc's working directory, and the directory in which new terminals run.
Use \fB:pwd\fR to see it again if you're not sure where you are.
.P
.SH ADDITIONAL NOTES
.P
.SS COMMANDS
.P
Every keybinding is ultimately bound to an aerc command. You can also summon the
command line by pressing ':', then entering one of these commands. See \fBaerc\fR(1)
or \fB:help\fR for a full list of commands.
.P
.SS MESSAGE FILTERS
.P
When displaying messages in the message viewer, aerc will pipe them through a
\fImessage filter\fR first. This allows you to decode messages in non-plaintext
formats, add syntax highlighting, etc. aerc ships with a few default filters:
.P
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
Emails which begin with "[PATCH" will be piped into a filter for rendering
git-format-patch and hg export emails.
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
text/html is rendered with w3m in a network sandbox
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
text/* is rendered with a simple filter for coloring quoted text

.RE
.P
.SS CUSTOMIZING AERC
.P
Aerc is highly customizable. Review \fBaerc-config\fR(5) (or use \fB:help config\fR) to
learn more about how to add custom keybindings, install new message filters,
change its appearance and behavior, and so on.
.P
.SH AUTHORS
.P
Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
source contributors. For more information about aerc development, see
https://git.sr.ht/~sircmpwn/aerc.
diff --git a/doc/aerc.1 b/doc/aerc.1
new file mode 100644
index 0000000..8773c2d
--- /dev/null
+++ b/doc/aerc.1
@@ -0,0 +1,620 @@
.\" Generated by scdoc 1.9.0
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "aerc" "1" "2021-05-26"
.P
.SH NAME
.P
aerc - the world's best email client
.P
.SH SYNOPSIS
.P
\fIaerc\fR [COMMAND [OPTION...] | mailto:...]
.P
For a guided tutorial, use \fB:help tutorial\fR from aerc, or \fBaerc help tutorial\fR
from your terminal.
.P
.SH PREEMPTIVE COMMANDS
.P
\fBversion\fR
.RS 4
Prints the \fIaerc\fR version and exit.
.P
.RE
\fBlicense\fR
.RS 4
Prints the \fIaerc\fR license and exit.
.P
.RE
\fBhelp\fR [<-i|-u> [EXEC OPTION...] | TOPIC ]
.RS 4
\fB-i\fR Install embedded man pages to primary `manpath`.
.P
\fB-u\fR Uninstall man pages from all `manpath`.
.P
Otherwise, show main or topic man page and exit.
.P
.RE
\fBconfig\fR [<-i|-u> [EXEC OPTION...] | FILE ]
.RS 4
\fB-i\fR Install embedded config files for user.
.P
\fB-u\fR Uninstall config files from user.
.P
Otherwise, list all or show select embedded config files and exit.
.P
.RE
\fBmailto:...\fR
.RS 4
Opens the composer with the address in the "to" field.
If \fIaerc\fR is already running, the composer is started in this instance,
otherwise \fIaerc\fR will be started.
.P
.RE
.SH EXEC OPTIONS
.P
\fB-n\fR	Dryrun, print but don't run operations.
.P
\fB-q\fR	Quiet, supress warnings.
.P
\fB-v\fR	Verbose, print each operation before execution.
.P
.SH RUNTIME COMMANDS
.P
To execute a command, press ':' to bring up the command interface. Commands may
also be bound to keys, see \fBaerc-config\fR(5) for details. In some contexts, such
as the terminal emulator, '<c-x>' is used to bring up the command interface.
.P
Different commands work in different contexts, depending on the kind of tab you
have selected.
.P
Aerc stores a history of commands, which can be cycled through in command mode.
Pressing the up key cycles backwards in history, while pressing down cycles
forwards.
.P
.SS GLOBAL COMMANDS
.P
These commands work in any context.
.P
\fBcd\fR <directory>
.RS 4
Changes aerc's current working directory.
.P
.RE
\fBchange-tab\fR [+|-]<tab name or index>
.RS 4
Changes the focus to the tab with the given name. If a number is given,
it's treated as an index. If + or - is specified, the number is interpreted
as a delta from the selected tab.
.P
.RE
\fBexec\fR <command...>
.RS 4
Executes an arbitrary command in the background. Aerc will set the 
environment variables \fB$account\fR and \fB$folder\fR when the command is
executed from an Account tab or an opened message.
.P
\fBNote\fR: commands executed in this way are not executed with the shell.
.P
.RE
\fBpwd\fR
.RS 4
Displays aerc's current working directory in the status bar.
.P
.RE
\fBset\fR <category>.<option> <value>
.RS 4
Changes the value of a configuration parameter at runtime. The category is
the name of the [heading] for the config option you wish to change, and the
option is the name of the config option. For example, to change this option:
.P
[ui]
.br
	index-format=before
.P
Use :set ui.index-format after.
.P
.RE
\fBterm\fR [command...]
.RS 4
Opens a new terminal tab with a shell running in the current working
directory, or the specified command.
.P
.RE
\fBmove-tab\fR [+|-]<index>
.RS 4
Moves the selected tab to the given index. If + or - is specified, the
number is interpreted as a delta from the selected tab.
.P
.RE
\fBprev-tab\fR [n], \fBnext-tab\fR [n]
.RS 4
Cycles to the previous or next tab in the list, repeating n times
(default: 1).
.P
.RE
\fBpin-tab\fR
.RS 4
Moves the current tab to the left of all non-pinned tabs and displays
the \fBpinned-tab-marker\fR (default: `) to the left of the tab title.
.P
.RE
\fBunpin-tab\fR
.RS 4
Removes the \fBpinned-tab-marker\fR from the current tab and returns the tab
to its previous location.
.P
.RE
\fBprompt\fR <prompt> <command...>
.RS 4
Displays the prompt on the status bar, waits for user input, then appends
that input as the last argument to the command and executes it. The input is
passed as one argument to the command, unless it is empty, in which case no
extra argument is added.
.P
.RE
\fBchoose\fR -o <key> <text> <command> [-o <key> <text> <command>]...
.RS 4
Prompts the user to choose from various options.
.P
.RE
\fBquit\fR
.RS 4
Exits aerc.
.P
.RE
.SS MESSAGE COMMANDS
.P
These commands are valid in any context that has a selected message (e.g. the
message list, the message in the message viewer, etc).
.P
\fBarchive\fR <scheme>
.RS 4
Moves the selected message to the archive. The available schemes are:
.P
\fBflat\fR: No special structure, all messages in the archive directory
.P
\fByear\fR: Messages are stored in folders per year
.P
\fBmonth\fR: Messages are stored in folders per year and subfolders per month
.P
.RE
\fBcopy\fR <target>
.RS 4
Copies the selected message to the target folder.
.P
.RE
\fBdelete\fR
.RS 4
Deletes the selected message.
.P
.RE
\fBrecall\fR
.RS 4
Opens the selected message for re-editing. Messages can only be
recalled from the postpone directory.
.P
.RE
\fBforward\fR [-A] [address...]
.RS 4
Opens the composer to forward the selected message to another recipient.
.P
\fB-A\fR: Forward the message as an RFC 2822 attachment.
.P
.RE
\fBmove\fR <target>
.RS 4
Moves the selected message to the target folder.
.P
.RE
\fBpipe\fR [-bmp] <cmd>
.RS 4
Downloads and pipes the selected message into the given shell command, and
opens a new terminal tab to show the result. By default, the selected
message part is used in the message viewer and the full message is used in
the message list.
.P
\fB-b\fR: Run the command in the background instead of opening a terminal tab
.P
\fB-m\fR: Pipe the full message
.P
\fB-p\fR: Pipe just the selected message part, if applicable
.P
.RE
\fBreply\fR [-aq] [-T <template-file>]
.RS 4
Opens the composer to reply to the selected message.
.P
\fB-a\fR: Reply all
.P
\fB-q\fR: Insert a quoted version of the selected message into the reply editor
.P
\fB-T\fR: Use the specified template file for creating the initial message body
.P
.RE
\fBread\fR [-t]
.RS 4
Marks the marked or selected messages as read.
.P
\fB-t\fR: Toggle the messages between read and unread.
.P
.RE
\fBunread\fR [-t]
.RS 4
Marks the marked or selected messages as unread.
.P
\fB-t\fR: Toggle the messages between read and unread.
.P
.RE
\fBflag\fR [-t] [-a | -x <flag>]
.RS 4
Sets (enables) a certain flag on the marked or selected messages.
.P
\fB-t\fR: Toggle the flag instead of setting (enabling) it.
.P
\fB-a\fR: Mark message as answered/unanswered.
.P
\fB-x <flag>\fR: Mark message with specific flag.
.P
The available flags are (adapted from RFC 3501, section 2.3.2):
.P
Seen
.RS 4
Message has been read
.P
.RE
Answered
.RS 4
Message has been answered
.P
.RE
Flagged
.RS 4
Message is flagged for urgent/special attention
.P
.RE
.RE
\fBunflag\fR [-t] <flag>
.RS 4
Operates exactly like \fBflag\fR, defaulting to unsetting (disabling) flags.
.P
.RE
\fBmodify-labels\fR <[+-]label>...
.RS 4
Modify message labels (e.g. notmuch tags). Labels prefixed with a '+' are
added, those prefixed with a '-' removed. As a convenience, labels without
either operand add the specified label.
.P
Example: `modify-labels +inbox -spam unread` adds the labels inbox and unread
and removes spam
.P
.RE
\fBunsubscribe\fR
.RS 4
Attempt to automatically unsubscribe the user from the mailing list through
use of the List-Unsubscribe header. If supported, aerc may open a compose
window pre-filled with the unsubscribe information or open the unsubscribe
URL in a web browser.
.P
.RE
.SS MESSAGE LIST COMMANDS
.P
\fBclear\fR
.RS 4
Clears the current search or filter criteria.
.P
.RE
\fBcf\fR <folder>
.RS 4
Change the folder shown in the message list.
.P
.RE
\fBcompose\fR [-H] [<body>]
.RS 4
Open the compose window to send a new email. The new email will be sent with
the current account's outgoing transport configuration. For details on
configuring outgoing mail delivery consult \fBaerc-config\fR(5).
.P
\fB-H\fR <header>
.RS 4
Add the specified header to the message, e.g. 'compose -H "X-Custom: custom
value"'
.P
.RE
.RE
\fBfilter\fR [options] <terms...>
.RS 4
Similar to \fBsearch\fR, but filters the displayed messages to only the search
results. See the documentation for \fBsearch\fR for more details.
.P
.RE
\fBmkdir\fR <name>
.RS 4
Creates a new folder for this account and changes to that folder.
.P
This is not supported on the 'notmuch' backend.
.P
.RE
\fBrmdir\fR [-f]
.RS 4
Removes the current folder.
.P
By default, it will fail if the directory is non-empty (see \fB-f\fR).
.P
\fB-f\fR
.RS 4
Remove the directory even if it contains messages.
.P
.RE
This is not supported on the 'notmuch' backend.
.P
Some programs that sync maildirs may recover deleted directories (e.g.
offlineimap).  These can either be specially configured to properly
handle directory deletion, or special commands need to be run to delete
directories (e.g. 'offlineimap --delete-folder').
.P
It is possible, with a slow connection and the 'imap' backend, that new
messages arrive in the directory before they show up - using 'rmdir' at
this moment would delete the directory and such new messages before the
user sees them.
.P
.RE
\fBnext\fR <n>[%], \fBprev\fR <n>[%]
.RS 4
Selects the next (or previous) message in the message list. If specified as
a percentage, the percentage is applied to the number of messages shown on
screen and the cursor advances that far.
.P
.RE
\fBnext-folder\fR <n>, \fBprev-folder\fR <n>
.RS 4
Cycles to the next (or previous) folder shown in the sidebar, repeated n
times (default: 1).
.P
.RE
\fBnext-result\fR, \fBprev-result\fR
.RS 4
Selects the next or previous search result.
.P
.RE
\fBsearch\fR
.RS 4
Searches the current folder.
The search syntax is dependent on the underlying backend.
Refer to \fBaerc-search\fR(1) for details
.P
.RE
\fBselect\fR <n>
.RS 4
Selects the nth message in the message list (and scrolls it into view if
necessary).
.P
.RE
\fBsort\fR [[-r] <criterion>]...
.RS 4
Sorts the message list by the given criteria. \fB-r\fR sorts the
immediately following criterion in reverse order.
.P
Available criteria:
.P
.RE
.TS
allbox;l c
l c
l c
l c
l c
l c
l c
l c
l c.
T{
\fBCriterion\fR
T}	T{
\fBDescription\fR
T}
T{
arrival
T}	T{
Date and time of the messages arrival
T}
T{
cc
T}	T{
Addresses in the "cc" field
T}
T{
date
T}	T{
Date and time of the message
T}
T{
from
T}	T{
Addresses in the "from" field
T}
T{
read
T}	T{
Presence of the read flag
T}
T{
size
T}	T{
Size of the message
T}
T{
subject
T}	T{
Subject of the message
T}
T{
to
T}	T{
Addresses in the "to" field
T}
.TE
.sp 1
\fBview\fR
.RS 4
Opens the message viewer to display the selected message.
.P
.RE
.SS MESSAGE VIEW COMMANDS
.P
\fBclose\fR
.RS 4
Closes the message viewer.
.P
.RE
\fBnext\fR <n>[%], \fBprev\fR <n>[%]
.RS 4
Selects the next (or previous) message in the message list. If specified as
a percentage, the percentage is applied to the number of messages shown on
screen and the cursor advances that far.
.P
.RE
\fBnext-part\fR, \fBprev-part\fR
.RS 4
Cycles between message parts being shown. The list of message parts is shown
at the bottom of the message viewer.
.P
.RE
\fBopen\fR [args...]
.RS 4
Saves the current message part in a temporary file and opens it
with the system handler. Any given args are forwarded to the open handler
.P
.RE
\fBsave\fR [-fp] <path>
.RS 4
Saves the current message part to the given path.
If the path is not an absolute path, general.default-save-path will be
prepended to the path given.
If path ends in a trailing slash or if a folder exists on disc,
aerc assumes it to be a directory.
When passed a directory :save infers the filename from the mail part if
possible, or if that fails, uses "aerc_$DATE".
.P
\fB-f\fR: Overwrite the destination whether or not it exists
.P
\fB-p\fR: Create any directories in the path that do not exist
.P
.RE
\fBmark\fR [-atv]
.RS 4
Marks messages. Commands will execute on all marked messages instead of the
highlighted one if applicable. The flags below can be combined as needed.
.P
\fB-a\fR: Apply to all messages in the current folder
.P
\fB-t\fR: toggle the mark state instead of marking a message
.P
\fB-v\fR: Enter / leave visual mark mode
.P
.RE
\fBunmark\fR [-at]
.RS 4
Unmarks messages. The flags below can be combined as needed.
.P
\fB-a\fR: Apply to all messages in the current folder
.P
\fB-t\fR: toggle the mark state instead of unmarking a message
.P
.RE
.SS MESSAGE COMPOSE COMMANDS
.P
\fBabort\fR
.RS 4
Close the composer without sending, discarding the message in progress.
.P
.RE
\fBattach\fR <path>
.RS 4
Attaches the file at the given path to the email.
.P
.RE
\fBdetach\fR [path]
.RS 4
Detaches the file with the given path from the composed email. If no path is
specified, detaches the first attachment instead.
.P
.RE
\fBcc\fR [addresses], \fBbcc\fR [addresses]
.RS 4
Sets the Cc or Bcc header to the given addresses. If an editor for the header
is not currently visible in the compose window, a new one will be added.
.P
.RE
\fBedit\fR
.RS 4
(Re-) opens your text editor to edit the message in progress.
.P
.RE
\fBnext-field\fR, \fBprev-field\fR
.RS 4
Cycles between input fields in the compose window.
.P
.RE
\fBpostpone\fR
.RS 4
Saves the current state of the message to the \fBpostpone\fR folder for the
current account.
.P
.RE
\fBsave\fR [-p] <path>
.RS 4
Saves the selected message part to the specified path. If -p is selected,
aerc will create any missing directories in the specified path. If the path
specified is a directory or ends in /, aerc will use the attachment filename
if available or a generated name if not.
.P
.RE
\fBsend\fR
.RS 4
Sends the message using this accounts default outgoing transport
configuration. For details on configuring outgoing mail delivery consult
\fBaerc-config\fR(5).
.P
.RE
\fBheader\fR [-f] <field> [value]
.RS 4
Add a new email header. If the header already exists, -f must be
specified to replace the given value.
.P
.RE
\fBtoggle-headers\fR
.RS 4
Toggles the visibility of the message headers.
.P
.RE
.SS TERMINAL COMMANDS
.P
\fBclose\fR
.RS 4
Closes the terminal.
.P
.RE
.SH LOGGING
.P
Aerc does not log by default, but collecting log output can be useful for
troubleshooting and reporting issues. Redirecting stdout when invoking aerc will
write log messages to that file:
.P
.RS 4
$ aerc > log
.P
.RE
.SH SEE ALSO
.P
\fBaerc-config\fR(5) \fBaerc-imap\fR(5) \fBaerc-smtp\fR(5) \fBaerc-maildir\fR(5)
\fBaerc-sendmail\fR(5) \fBaerc-tutorial\fR(7)
.P
.SH AUTHORS
.P
Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
source contributors. For more information about aerc development, see
https://git.sr.ht/~sircmpwn/aerc.
diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd
index f678a0a..746779f 100644
--- a/doc/aerc.1.scd
+++ b/doc/aerc.1.scd
@@ -6,21 +6,46 @@ aerc - the world's best email client

# SYNOPSIS

_aerc_ [-v] [mailto:...]
_aerc_ [COMMAND [OPTION...] | mailto:...]

For a guided tutorial, use *:help tutorial* from aerc, or *man aerc-tutorial*
For a guided tutorial, use *:help tutorial* from aerc, or *aerc help tutorial*
from your terminal.

# OPTIONS
# PREEMPTIVE COMMANDS

*-v*
	Prints the installed version of aerc and exits.
*version*
	Prints the _aerc_ version and exit.

*license*
	Prints the _aerc_ license and exit.

*help* [<-i|-u> [EXEC OPTION...] | TOPIC ]
	*-i* Install embedded man pages to primary `manpath`.

	*-u* Uninstall man pages from all `manpath`.

	Otherwise, show main or topic man page and exit.

*config* [<-i|-u> [EXEC OPTION...] | FILE ]
	*-i* Install embedded config files for user.

	*-u* Uninstall config files from user.

	Otherwise, list all or show select embedded config files and exit.

*mailto:...*
	Opens the composer with the address in the "to" field.
	If _aerc_ is already running, the composer is started in this instance,
	otherwise _aerc_ will be started.

# EXEC OPTIONS

*-n*	Dryrun, print but don't run operations.

*-q*	Quiet, supress warnings.

*-v*	Verbose, print each operation before execution.

# RUNTIME COMMANDS

To execute a command, press ':' to bring up the command interface. Commands may
diff --git a/embedded.go b/embedded.go
new file mode 100644
index 0000000..47e2ab7
--- /dev/null
+++ b/embedded.go
@@ -0,0 +1,217 @@
package main

import (
	"embed"
	"fmt"
	"io"
	"io/fs"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"text/template"

	"git.sr.ht/~sircmpwn/aerc/assert"
	"git.sr.ht/~sircmpwn/aerc/optional"
)

//go:embed LICENSE VERSION
//go:embed config/*.tmpl config/*.conf
//go:embed doc/*.1 doc/*.5 doc/*.7
//go:embed filters
//go:embed stylesets
//go:embed templates
var embedded embed.FS

func help(args []string) {
	const aercDash = "aerc-"
	var prefix string
	args = assert.Args(args, "iu")
	switch {
	case optional.Bools['i']:
		installEmbeddedHelp()
	case optional.Bools['u']:
		uninstallHelp()
	case len(args) == 0:
		manEmbeddedHelp("aerc.1")
	default:
		if args[0] == "aerc.1" || strings.HasPrefix(args[0], aercDash) {
			prefix = args[0]
		} else {
			prefix = fmt.Sprint(aercDash, args[0])
		}
		for _, e := range assert.ReadDir(embedded, "doc") {
			if strings.HasPrefix(e.Name(), prefix) {
				manEmbeddedHelp(e.Name())
				return
			}
		}
		panic("no such help")
	}
}

func manEmbeddedHelp(name string) {
	doc := assert.Sub(embedded, "doc")
	cmd := exec.Command("man", "-l", "-")
	cmd.Stdin = assert.Open(doc, name)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		panic(err)
	}
}

func uninstallHelp() {
	for _, manroot := range assert.Manpath() {
		manrootFS := os.DirFS(manroot)
		for _, sec := range []string{"man1", "man5", "man7"} {
			for _, e := range optional.ReadDir(manrootFS, sec) {
				if !strings.HasPrefix(e.Name(), "aerc") {
					continue
				}
				p := filepath.Join(manroot, sec, e.Name())
				if err := optional.Remove(p); err != nil {
					optional.Warning("rm", p, err)
				}
			}
		}
	}
}

func installEmbeddedHelp() {
	manroot := assert.Manpath()[0]
	sub := assert.Sub(embedded, "doc")
	for _, e := range assert.ReadDir(sub, ".") {
		name := e.Name()
		r := assert.Open(sub, name)
		sec := func(s string) string {
			return filepath.Join(manroot, s, name)
		}
		switch {
		case strings.HasSuffix(name, ".1"):
			assert.CopyFile(sec("man1"), r, 0644)
		case strings.HasSuffix(name, ".5"):
			assert.CopyFile(sec("man5"), r, 0644)
		case strings.HasSuffix(name, ".7"):
			assert.CopyFile(sec("man7"), r, 0644)
		}
	}
}

func konfig(args []string) {
	userConfigAerc := filepath.Join(assert.UserConfig(), "aerc")
	args = assert.Args(args, "iu")
	switch {
	case optional.Bools['i']:
		installEmbeddedConfig()
	case optional.Bools['u']:
		uninstallUserConfig()
	case len(args) == 0:
		listEmbeddedConfig()
	case strings.HasPrefix(args[0], "filters"),
		strings.HasPrefix(args[0], "stylesets"),
		strings.HasPrefix(args[0], "templates"):
		prefix := filepath.Base(args[0])
		sub := assert.Sub(embedded, filepath.Dir(args[0]))
		for _, e := range assert.ReadDir(sub, ".") {
			if !strings.HasPrefix(e.Name(), prefix) {
				continue
			}
			io.Copy(os.Stdout, assert.Open(sub, e.Name()))
			return
		}
		panic("no such file")
	default:
		sub := assert.Sub(embedded, "config")
		for _, e := range assert.ReadDir(sub, ".") {
			if !strings.HasPrefix(e.Name(), args[0]) {
				continue
			}
			if strings.HasSuffix(e.Name(), ".tmpl") {
				from := filepath.Join("config", e.Name())
				t, err := template.ParseFS(embedded, from)
				if err != nil {
					panic(err)
				}
				t.Execute(os.Stdout, userConfigAerc)
			} else {
				io.Copy(os.Stdout, assert.Open(sub, e.Name()))
			}
			return
		}
		panic("no such config")
	}
}

func installEmbeddedConfig() {
	if os.Geteuid() == 0 {
		return
	}
	uc := assert.UserConfig()
	ac := func(elem ...string) string {
		return filepath.Join(uc, "aerc", filepath.Join(elem...))
	}
	ex := func(elem ...string) string {
		return ac("examples", filepath.Join(elem...))
	}
	r := func(sub fs.FS, name string) io.Reader {
		return assert.Open(sub, name)
	}
	assert.Mkdir(ac(), 0755)
	assert.Mkdir(ex(), 0755)
	sub := assert.Sub(embedded, "config")
	for _, e := range assert.ReadDir(sub, ".") {
		name := e.Name()
		switch {
		case name == "accounts.conf":
			assert.CopyFile(ex(name), r(sub, name), 0600)
		case strings.HasSuffix(name, ".tmpl"):
			to := strings.TrimSuffix(name, ".tmpl")
			t := template.Must(template.New(name).
				Parse(string(assert.ReadAll(r(sub, name)))))
			assert.SedFile(ex(to), t, ac(), 0644)
			assert.IfNotExist(ac(to), func(path string) {
				assert.SedFile(path, t, ac(), 0644)
			})
		case strings.HasSuffix(name, ".conf"):
			assert.CopyFile(ex(name), r(sub, name), 0644)
			assert.IfNotExist(ac(name), func(p string) {
				assert.CopyFile(p, r(sub, name), 0644)
			})
		}
	}
	for _, dir := range []string{"filters", "stylesets", "templates"} {
		assert.Mkdir(ac(dir), 0755)
		assert.Mkdir(ex(dir), 0755)
		sub = assert.Sub(embedded, dir)
		for _, e := range assert.ReadDir(sub, ".") {
			name := e.Name()
			assert.CopyFile(ex(dir, name), r(sub, name), 0644)
			assert.IfNotExist(ac(dir, name), func(p string) {
				assert.CopyFile(p, r(sub, name), 0644)
			})
		}
	}
}

func uninstallUserConfig() {
	if os.Geteuid() == 0 {
		return
	}
	userConfigAerc := filepath.Join(assert.UserConfig(), "aerc")
	if _, err := os.Stat(userConfigAerc); os.IsNotExist(err) {
		return
	}
	assert.RemoveAll(userConfigAerc)
}

func listEmbeddedConfig() {
	for _, e := range assert.ReadDir(embedded, "config") {
		fmt.Println(strings.TrimSuffix(e.Name(), ".tmpl"))
	}
	for _, sub := range []string{"filters", "stylesets", "templates"} {
		for _, e := range assert.ReadDir(embedded, sub) {
			fmt.Println(filepath.Join(sub, e.Name()))
		}
	}
}
diff --git a/go.mod b/go.mod
index 44030e1..ae2ffdc 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module git.sr.ht/~sircmpwn/aerc

go 1.13
go 1.16

require (
	git.sr.ht/~sircmpwn/getopt v0.0.0-20190808004552-daaf1274538b
diff --git a/optional/optional.go b/optional/optional.go
new file mode 100644
index 0000000..451a24c
--- /dev/null
+++ b/optional/optional.go
@@ -0,0 +1,147 @@
package optional

import (
	"errors"
	"fmt"
	"io"
	"io/fs"
	"os"
	"strings"

	"git.sr.ht/~sircmpwn/getopt"
)

const NewFileFlags = os.O_WRONLY | os.O_CREATE | os.O_TRUNC

var (
	Bools   map[rune]bool
	Strings map[rune]string
)

func Args(args []string, extra string) ([]string, error) {
	Bools = make(map[rune]bool)
	Strings = make(map[rune]string)
	options := fmt.Sprint("nqv", extra)
	for i, o := range options {
		if i == len(options)-1 || options[i+1] != ':' {
			Bools[o] = false
		} else {
			Strings[o] = ""
		}
	}
	opts, optind, err := getopt.Getopts(args, options)
	if err != nil {
		prefix := fmt.Sprint(os.Args[0], ": ")
		err = errors.New(strings.TrimPrefix(err.Error(), prefix))
		return args, err
	}
	args = args[optind:]
	for _, opt := range opts {
		if _, ok := Bools[opt.Option]; ok {
			Bools[opt.Option] = true
		} else if _, ok = Bools[opt.Option]; ok {
			Strings[opt.Option] = opt.Value
		}
	}
	return args, err
}

func Dryrun() bool  { return Bools['n'] }
func Quiet() bool   { return Bools['q'] }
func Verbose() bool { return Bools['v'] }

func Note(v ...interface{}) (int, error) {
	if Dryrun() || Verbose() {
		return fmt.Fprintln(os.Stdout, v...)
	}
	return 0, nil
}

func Warning(v ...interface{}) (int, error) {
	if !Quiet() {
		return fmt.Fprintln(os.Stderr, v...)
	}
	return 0, nil
}

func CopyFile(name string, r io.Reader, perm fs.FileMode) error {
	Note(">", name)
	if Dryrun() {
		return nil
	}
	f, err := os.OpenFile(name, NewFileFlags, perm)
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = io.Copy(f, r)
	return err
}

func Mkdir(dir string, perm os.FileMode) error {
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		Note("mkdir", dir)
		if !Dryrun() {
			return os.Mkdir(dir, perm)
		}
	}
	return nil
}

func MkdirAll(dir string, perm os.FileMode) error {
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		Note("mkdir -p", dir)
		if !Dryrun() {
			return os.MkdirAll(dir, perm)
		}
	}
	return nil
}

func ReadDir(fsys fs.FS, name string) []fs.DirEntry {
	dir, _ := fs.ReadDir(fsys, name)
	return dir
}

func ReadFile(fsys fs.FS, name string) []byte {
	data, _ := fs.ReadFile(fsys, name)
	return data
}

func Remove(path string) error {
	if _, err := os.Stat(path); err == nil {
		Note("rm", path)
		if !Dryrun() {
			return os.Remove(path)
		}
	}
	return nil
}

func RemoveAll(path string) error {
	if _, err := os.Stat(path); err == nil {
		Note("rm -r", path)
		if !Dryrun() {
			return os.RemoveAll(path)
		}
	}
	return nil
}

type Executer interface {
	Execute(wr io.Writer, data interface{}) error
}

func SedFile(name string, x Executer, data interface{},
	perm fs.FileMode) error {
	Note(">", name)
	if Dryrun() {
		return nil
	}
	f, err := os.OpenFile(name, NewFileFlags, perm)
	if err != nil {
		return err
	}
	defer f.Close()
	return x.Execute(f, data)
}
diff --git a/config/default_styleset b/stylesets/default
similarity index 100%
rename from config/default_styleset
rename to stylesets/default
-- 
2.20.1