From bb0f1801402e98266d2554a5f002dc8ce0419808 Mon Sep 17 00:00:00 2001 From: Robin Jarry Date: Sat, 19 Feb 2022 14:06:57 +0100 Subject: config: do not hardcode sharedir Instead of using a static SHAREDIR at compile time, use a list of standard paths to use at runtime for templates, config files and stylesets. This implies removing all default filters in the default configuration. Replace them with basic commands. New users can configure the filters as they wish. Signed-off-by: Robin Jarry --- .gitignore | 1 - Makefile | 13 +-- aerc.go | 8 +- config/aerc.conf | 268 ++++++++++++++++++++++++++++++++++++++++++++++ config/aerc.conf.in | 257 -------------------------------------------- config/config.go | 66 ++++++++---- doc/aerc-config.5.scd | 28 +++-- lib/templates/template.go | 8 ++ 8 files changed, 350 insertions(+), 299 deletions(-) create mode 100644 config/aerc.conf delete mode 100644 config/aerc.conf.in diff --git a/.gitignore b/.gitignore index 5d04c977..b4af105f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ /aerc.debug log raw.log -aerc.conf *.1 *.5 *.7 diff --git a/Makefile b/Makefile index a1973d26..9c8b9219 100644 --- a/Makefile +++ b/Makefile @@ -10,8 +10,6 @@ SHAREDIR?=$(PREFIX)/share/aerc MANDIR?=$(PREFIX)/share/man GO?=go GOFLAGS?= -LDFLAGS:=-X main.Prefix=$(PREFIX) -LDFLAGS+=-X main.ShareDir=$(SHAREDIR) LDFLAGS+=-X main.Version=$(VERSION) GOSRC:=$(shell find * -name '*.go') @@ -30,7 +28,7 @@ DOCS := \ aerc-templates.7 \ aerc-stylesets.7 -all: aerc aerc.conf $(DOCS) +all: aerc $(DOCS) aerc: $(GOSRC) $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $@ @@ -47,9 +45,6 @@ checkfmt: exit 1; \ fi -aerc.conf: config/aerc.conf.in - sed -e 's:@SHAREDIR@:$(SHAREDIR):g' > $@ < config/aerc.conf.in - .PHONY: debug debug: aerc.debug @echo 'Run `./aerc.debug` and use this command in another terminal to attach a debugger:' @@ -73,9 +68,9 @@ doc: $(DOCS) RM?=rm -f clean: - $(RM) $(DOCS) aerc.conf aerc + $(RM) $(DOCS) aerc -install: $(DOCS) aerc aerc.conf +install: $(DOCS) aerc 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 @@ -91,7 +86,7 @@ install: $(DOCS) aerc aerc.conf 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/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 diff --git a/aerc.go b/aerc.go index 6467c616..555b3a31 100644 --- a/aerc.go +++ b/aerc.go @@ -86,10 +86,8 @@ func getCompletions(aerc *widgets.Aerc, cmd string) []string { return completions } -var ( - ShareDir string - Version string -) +// set at build time +var Version string func usage() { log.Fatal("Usage: aerc [-v] [mailto:...]") @@ -152,7 +150,7 @@ func main() { logger = log.New(logOut, "", log.LstdFlags) logger.Println("Starting up aerc") - conf, err := config.LoadConfigFromFile(nil, ShareDir, logger) + conf, err := config.LoadConfigFromFile(nil, logger) if err != nil { fmt.Fprintf(os.Stderr, "Failed to load config: %v\n", err) os.Exit(1) diff --git a/config/aerc.conf b/config/aerc.conf new file mode 100644 index 00000000..2c928f69 --- /dev/null +++ b/config/aerc.conf @@ -0,0 +1,268 @@ +# +# aerc main configuration + +[ui] +# +# Describes the format for each row in a mailbox view. This field is compatible +# with mutt's printf-like syntax. +# +# Default: %D %-17.17n %Z %s +index-format=%-20.20D %-17.17n %Z %s + +# +# See time.Time#Format at https://godoc.org/time#Time.Format +# +# Default: 2006-01-02 03:04 PM (ISO 8601 + 12 hour time) +timestamp-format=2006-01-02 03:04 PM + +# +# Index-only time format for messages that were received/sent today. +# If this is not specified, timestamp-format is used instead. +# +# Default: "03:04 PM" (12 hour time) +this-day-time-format=03:04 PM + +# +# Index-only time format for messages that were received/sent within the last +# 7 days. If this is not specified, timestamp-format is used instead. +# +# Default: "Monday 03:04 PM" (Week day + 12 hour time) +this-week-time-format=Monday 03:04 PM + +# +# Index-only time format for messages that were received/sent this year. +# If this is not specified, timestamp-format is used instead. +# +# Default: "January 02" (Month + month day) +this-year-time-format=January 02 + +# +# Width of the sidebar, including the border. +# +# Default: 20 +sidebar-width=20 + +# +# Message to display when viewing an empty folder. +# +# Default: (no messages) +empty-message=(no messages) + +# Message to display when no folders exists or are all filtered +# +# Default: (no folders) +empty-dirlist=(no folders) + +# Enable mouse events in the ui, e.g. clicking and scrolling with the mousewheel +# +# Default: false +mouse-enabled=false + +# +# Ring the bell when new messages are received +# +# Default: true +new-message-bell=true + +# Marker to show before a pinned tab's name. +# +# Default: ` +pinned-tab-marker='`' + +# Describes the format string to use for the directory list +# +# Default: %n %>r +dirlist-format=%n %>r + +# Delay after which the messages are actually listed when entering a directory. +# This avoids loading messages when skipping over folders and makes the UI more +# responsive. If you do not want that, set it to 0s. +# +# Default: 200ms +dirlist-delay=200ms + +# List of space-separated criteria to sort the messages by, see *sort* +# command in *aerc*(1) for reference. Prefixing a criterion with "-r " +# reverses that criterion. +# +# Example: "from -r date" +# +# Default: "" +sort= + +# Moves to next message when the current message is deleted +# +# Default: true +next-message-on-delete=true + +# The directories where the stylesets are stored. It takes a colon-separated +# list of directories. If this is unset or if a styleset cannot be found, the +# following paths will be used as a fallback in that order: +# +# ~/.config/aerc/stylesets +# ~/.local/share/aerc/stylesets +# /usr/local/share/aerc/stylesets +# /usr/share/aerc/stylesets +# +# default: "" +stylesets-dirs= + +# Uncomment to use box-drawing characters for vertical and horizontal borders. +# +# Default: spaces +# border-char-vertical=│ +# border-char-horizontal=─ + +# Sets the styleset to use for the aerc ui elements. +# +# Default: default +styleset-name=default + +# Activates fuzzy search for IMAP folders: the typed string is search in the +# folder tree in any position, not necessarily at the beginning. +#fuzzy-folder-complete=false + +#[ui:account=foo] +# +# Enable threading in the ui. Only works with notmuch:// and imap:// accounts +# (when the server supports it). +# +# Default: false +#threading-enabled=false + +[viewer] +# +# Specifies the pager to use when displaying emails. Note that some filters +# may add ANSI codes to add color to rendered emails, so you may want to use a +# pager which supports ANSI codes. +# +# Default: less -R +pager=less -R + +# +# 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. +# +# Default: text/plain,text/html +alternatives=text/plain,text/html + +# +# Default setting to determine whether to show full headers or only parsed +# ones in message viewer. +# +# Default: false +show-headers=false + +# +# Layout of headers 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. +# +# Default: From|To,Cc|Bcc,Date,Subject +header-layout=From|To,Cc|Bcc,Date,Subject + +# Whether to always show the mimetype of an email, even when it is just a single part +# +# Default: false +always-show-mime=false + +# How long to wait after the last input before auto-completion is triggered. +# +# Default: 250ms +completion-delay=250ms + +# +# Global switch for completion popovers +# +# Default: true +completion-popovers=true + +[compose] +# +# 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 $EDITOR, or vi. +editor= + +# +# Default header fields to display when composing a message. To display +# multiple headers in the same row, separate them with a pipe, e.g. "To|From". +# +# Default: To|From,Subject +header-layout=To|From,Subject + +# +# 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. +# +# 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. +address-book-cmd= + +# +# Allow to address yourself when replying +# +# Default: true +reply-to-self=true + +[filters] +# +# 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. +# +# The first filter which matches the email's mimetype will be used, so order +# them from most to least specific. +# +# 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=colordiff +#text/html=pandoc -f html -t plain +#image/*=catimg -w $(tput cols) - + +[triggers] +# +# Triggers specify commands to execute when certain events occur. +# +# Example: +# new-email=exec notify-send "New email from %n" "%s" + +# +# Executed when a new email arrives in the selected folder +new-email= + +[templates] +# Templates are used to populate email bodies automatically. +# + +# The directories where the templates are stored. It takes a colon-separated +# list of directories. If this is unset or if a template cannot be found, the +# following paths will be used as a fallback in that order: +# +# ~/.config/aerc/templates +# ~/.local/share/aerc/templates +# /usr/local/share/aerc/templates +# /usr/share/aerc/templates +# +# default: "" +template-dirs= + +# The default template to be used for new messages. +# +# default: new_message +new-message=new_message + +# The default template to be used for quoted replies. +# +# default: quoted_reply +quoted-reply=quoted_reply + +# The default template to be used for forward as body. +# +# default: forward_as_body +forwards=forward_as_body diff --git a/config/aerc.conf.in b/config/aerc.conf.in deleted file mode 100644 index 98cd679c..00000000 --- a/config/aerc.conf.in +++ /dev/null @@ -1,257 +0,0 @@ -# -# aerc main configuration - -[ui] -# -# Describes the format for each row in a mailbox view. This field is compatible -# with mutt's printf-like syntax. -# -# Default: %D %-17.17n %Z %s -index-format=%-20.20D %-17.17n %Z %s - -# -# See time.Time#Format at https://godoc.org/time#Time.Format -# -# Default: 2006-01-02 03:04 PM (ISO 8601 + 12 hour time) -timestamp-format=2006-01-02 03:04 PM - -# -# Index-only time format for messages that were received/sent today. -# If this is not specified, timestamp-format is used instead. -# -# Default: "03:04 PM" (12 hour time) -this-day-time-format=03:04 PM - -# -# Index-only time format for messages that were received/sent within the last -# 7 days. If this is not specified, timestamp-format is used instead. -# -# Default: "Monday 03:04 PM" (Week day + 12 hour time) -this-week-time-format=Monday 03:04 PM - -# -# Index-only time format for messages that were received/sent this year. -# If this is not specified, timestamp-format is used instead. -# -# Default: "January 02" (Month + month day) -this-year-time-format=January 02 - -# -# Width of the sidebar, including the border. -# -# Default: 20 -sidebar-width=20 - -# -# Message to display when viewing an empty folder. -# -# Default: (no messages) -empty-message=(no messages) - -# Message to display when no folders exists or are all filtered -# -# Default: (no folders) -empty-dirlist=(no folders) - -# Enable mouse events in the ui, e.g. clicking and scrolling with the mousewheel -# -# Default: false -mouse-enabled=false - -# -# Ring the bell when new messages are received -# -# Default: true -new-message-bell=true - -# Marker to show before a pinned tab's name. -# -# Default: ` -pinned-tab-marker='`' - -# Describes the format string to use for the directory list -# -# Default: %n %>r -dirlist-format=%n %>r - -# Delay after which the messages are actually listed when entering a directory. -# This avoids loading messages when skipping over folders and makes the UI more -# responsive. If you do not want that, set it to 0s. -# -# Default: 200ms -dirlist-delay=200ms - -# List of space-separated criteria to sort the messages by, see *sort* -# command in *aerc*(1) for reference. Prefixing a criterion with "-r " -# reverses that criterion. -# -# Example: "from -r date" -# -# Default: "" -sort= - -# Moves to next message when the current message is deleted -# -# Default: true -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/ - -# Uncomment to use box-drawing characters for vertical and horizontal borders. -# -# Default: spaces -# border-char-vertical=│ -# border-char-horizontal=─ - -# Sets the styleset to use for the aerc ui elements. -# -# Default: default -styleset-name=default - -# Activates fuzzy search for IMAP folders: the typed string is search in the -# folder tree in any position, not necessarily at the beginning. -#fuzzy-folder-complete=false - -#[ui:account=foo] -# -# Enable threading in the ui. Only works with notmuch:// and imap:// accounts -# (when the server supports it). -# -# Default: false -#threading-enabled=false - -[viewer] -# -# Specifies the pager to use when displaying emails. Note that some filters -# may add ANSI codes to add color to rendered emails, so you may want to use a -# pager which supports ANSI codes. -# -# Default: less -R -pager=less -R - -# -# 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. -# -# Default: text/plain,text/html -alternatives=text/plain,text/html - -# -# Default setting to determine whether to show full headers or only parsed -# ones in message viewer. -# -# Default: false -show-headers=false - -# -# Layout of headers 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. -# -# Default: From|To,Cc|Bcc,Date,Subject -header-layout=From|To,Cc|Bcc,Date,Subject - -# Whether to always show the mimetype of an email, even when it is just a single part -# -# Default: false -always-show-mime=false - -# How long to wait after the last input before auto-completion is triggered. -# -# Default: 250ms -completion-delay=250ms - -# -# Global switch for completion popovers -# -# Default: true -completion-popovers=true - -[compose] -# -# 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 $EDITOR, or vi. -editor= - -# -# Default header fields to display when composing a message. To display -# multiple headers in the same row, separate them with a pipe, e.g. "To|From". -# -# Default: To|From,Subject -header-layout=To|From,Subject - -# -# 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. -# -# 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. -address-book-cmd= - -# -# Allow to address yourself when replying -# -# Default: true -reply-to-self=true - -[filters] -# -# 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. -# -# The first filter which matches the email's mimetype will be used, so order -# them from most to least specific. -# -# 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 -#image/*=catimg -w $(tput cols) - - -[triggers] -# -# Triggers specify commands to execute when certain events occur. -# -# Example: -# new-email=exec notify-send "New email from %n" "%s" - -# -# Executed when a new email arrives in the selected folder -new-email= - -[templates] -# Templates are used to populate email bodies automatically. -# - -# The directories where the templates are stored. It takes a colon-separated -# list of directories. -# -# default: @SHAREDIR@/templates/ -template-dirs=@SHAREDIR@/templates/ - -# The default template to be used for new messages. -# -# default: new_message -new-message=new_message - -# The default template to be used for quoted replies. -# -# default: quoted_reply -quoted-reply=quoted_reply - -# The default template to be used for forward as body. -# -# default: forward_as_body -forwards=forward_as_body diff --git a/config/config.go b/config/config.go index 185a14c0..f730fe45 100644 --- a/config/config.go +++ b/config/config.go @@ -296,14 +296,28 @@ func parseCredential(cred, command string) (string, error) { return u.String(), nil } -func installTemplate(root, sharedir, name string) error { - if _, err := os.Stat(root); os.IsNotExist(err) { - err := os.MkdirAll(root, 0755) +var defaultDirs []string = []string{ + path.Join(xdg.ConfigHome(), "aerc"), + path.Join(xdg.DataHome(), "aerc"), + "/usr/local/share/aerc", + "/usr/share/aerc", +} + +func installTemplate(root, name string) error { + var err error + if _, err = os.Stat(root); os.IsNotExist(err) { + err = os.MkdirAll(root, 0755) if err != nil { return err } } - data, err := ioutil.ReadFile(path.Join(sharedir, name)) + var data []byte + for _, dir := range defaultDirs { + data, err = ioutil.ReadFile(path.Join(dir, name)) + if err == nil { + break + } + } if err != nil { return err } @@ -446,20 +460,30 @@ func (config *AercConfig) LoadConfig(file *ini.File) error { if templateDirs != "" { config.Templates.TemplateDirs = strings.Split(templateDirs, ":") } - for key, val := range templatesSec.KeysHash() { - if key == "template-dirs" { - continue - } - // we want to fail during startup if the templates are not ok - // hence we do a dummy execute here - _, err := templates.ParseTemplateFromFile( - val, config.Templates.TemplateDirs, templates.DummyData()) - if err != nil { - return err - } - } } + // append default paths to template-dirs and styleset-dirs + for _, dir := range defaultDirs { + config.Ui.StyleSetDirs = append( + config.Ui.StyleSetDirs, path.Join(dir, "stylesets"), + ) + config.Templates.TemplateDirs = append( + config.Templates.TemplateDirs, path.Join(dir, "templates"), + ) + } + + // we want to fail during startup if the templates are not ok + // hence we do dummy executes here + t := config.Templates + if err := templates.CheckTemplate(t.NewMessage, t.TemplateDirs); err != nil { + return err + } + if err := templates.CheckTemplate(t.QuotedReply, t.TemplateDirs); err != nil { + return err + } + if err := templates.CheckTemplate(t.Forwards, t.TemplateDirs); err != nil { + return err + } if err := config.Ui.loadStyleSet( config.Ui.StyleSetDirs); err != nil { return err @@ -506,7 +530,7 @@ func validateBorderChars(section *ini.Section, config *UIConfig) error { return nil } -func LoadConfigFromFile(root *string, sharedir string, logger *log.Logger) (*AercConfig, error) { +func LoadConfigFromFile(root *string, logger *log.Logger) (*AercConfig, error) { if root == nil { _root := path.Join(xdg.ConfigHome(), "aerc") root = &_root @@ -519,7 +543,7 @@ func LoadConfigFromFile(root *string, sharedir string, logger *log.Logger) (*Aer // if it doesn't exist copy over the template, then load if _, err := os.Stat(filename); errors.Is(err, os.ErrNotExist) { - if err := installTemplate(*root, sharedir, "aerc.conf"); err != nil { + if err := installTemplate(*root, "aerc.conf"); err != nil { return nil, err } } @@ -572,7 +596,7 @@ func LoadConfigFromFile(root *string, sharedir string, logger *log.Logger) (*Aer NextMessageOnDelete: true, CompletionDelay: 250 * time.Millisecond, CompletionPopovers: true, - StyleSetDirs: []string{path.Join(sharedir, "stylesets")}, + StyleSetDirs: []string{}, StyleSetName: "default", // border defaults BorderCharVertical: ' ', @@ -602,7 +626,7 @@ func LoadConfigFromFile(root *string, sharedir string, logger *log.Logger) (*Aer }, Templates: TemplateConfig{ - TemplateDirs: []string{path.Join(sharedir, "templates")}, + TemplateDirs: []string{}, NewMessage: "new_message", QuotedReply: "quoted_reply", Forwards: "forward_as_body", @@ -636,7 +660,7 @@ func LoadConfigFromFile(root *string, sharedir string, logger *log.Logger) (*Aer filename = path.Join(*root, "binds.conf") binds, err := ini.Load(filename) if err != nil { - if err := installTemplate(*root, sharedir, "binds.conf"); err != nil { + if err := installTemplate(*root, "binds.conf"); err != nil { return nil, err } if binds, err = ini.Load(filename); err != nil { diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd index ce53f9ba..1992b59f 100644 --- a/doc/aerc-config.5.scd +++ b/doc/aerc-config.5.scd @@ -208,10 +208,18 @@ These options are configured in the *[ui]* section of aerc.conf. Default: spaces *stylesets-dirs* - The directories where the stylesets are stored. The config takes a - colon-separated list of dirs. + The directories where the stylesets are stored. The config takes + a colon-separated list of dirs. If this is unset or if a styleset cannot + be found, the following paths will be used as a fallback in that order: - Default: "/usr/share/aerc/stylesets" + ``` + ~/.config/aerc/stylesets + ~/.local/share/aerc/stylesets + /usr/local/share/aerc/stylesets + /usr/share/aerc/stylesets + ``` + + Default: "" *styleset-name* The name of the styleset to be used to style the ui elements. The @@ -398,10 +406,18 @@ _/usr/share/aerc/templates_). These options are configured in the *[templates]* section of aerc.conf. *template-dirs* - The directory where the templates are stored. The config takes a - colon-separated list of dirs. + The directory where the templates are stored. The config takes + a colon-separated list of dirs. If this is unset or if a template cannot + be found, the following paths will be used as a fallback in that order: - Default: "/usr/share/aerc/templates" + ``` + ~/.config/aerc/templates + ~/.local/share/aerc/templates + /usr/local/share/aerc/templates + /usr/share/aerc/templates + ``` + + Default: "" *new-message* The default template to be used for new messages. diff --git a/lib/templates/template.go b/lib/templates/template.go index 6d66d8eb..9c71c463 100644 --- a/lib/templates/template.go +++ b/lib/templates/template.go @@ -227,3 +227,11 @@ func ParseTemplateFromFile(templateName string, templateDirs []string, data inte } return &body, nil } + +func CheckTemplate(templateName string, templateDirs []string) error { + if templateName != "" { + _, err := ParseTemplateFromFile(templateName, templateDirs, DummyData()) + return err + } + return nil +} -- cgit