CLtL p 360 ff: The Readtable
COPY-READTABLE (CLtL, p 361)
*PRINT-CASE* (CLtL, p 372)
Category: ADDITION/CHANGE
Edit history: Version 1, 15-Feb-89, by Dalton
Version 2, 23-Mar-89, by Dalton,
(completely new proposal after comments from
Pitman, Gray, Masinter, and<EMAIL_ADDRESS>Version 3, 16-Jun-89, by Dalton
(very minor changes in presentation
and some additions to the discussion)
Version 4, 22-Jun-89, by Dalton
(removal of the FUNCTION proposal and a different
specification for :INVERT after discussion with Moon)
Version 5, 23-Jun-89, by Dalton
(minor revisions in presentation and better test case,
as suggested by Pitman; also fixed some errors)
Version 6, 24-Jun-89, by Dalton (small correction)
Version 7, 2-Jul-89, by Masinter (as amended, Jun89X3J13)
Problem Description:
The Common Lisp reader always converts unescaped constituent
characters to upper case. (See CLtL, p 337, step 8, point 1.)
This behavior is not always desirable.
1. Lisp applications often use the Lisp reader to read their data.
This is often significantly easier than writing input routines
from scratch, especially if the input can be structured as lists.
However, certain applications want to make use of case distinctions,
and Common Lisp makes this unreasonably difficult. (You must define
every letter as a read macro and have the macro function read the
rest of the symbol, or else you must write a reader from scratch.)
2. Some programming languages distinguish between upper and lower
case in identifiers, and useful conventions are often built around
such distinctions. For example, in C, constants are often written
in upper case and variables in lower. In Mesa(?) and Smalltalk(?),
a capital letter is used to indicate the beginning of a new word
in identifiers made up of several words. In Edinburgh Prolog,
variables begin with upper-case letters and constant symbols do
not. The case-insensitivity of the Common Lisp reader makes
it difficult to use conventions of this sort.
Proposal (READ-CASE-SENSITIVITY:READTABLE-KEYWORDS)
Define a new settable function, (READTABLE-CASE <readtable>) to
control the reader's interpretation of case. The following values
may be given: :UPCASE, :DOWNCASE, :PRESERVE, and :INVERT.
When the value is :UPCASE, unescaped constituent characters
are converted to upper-case, as specified by CLtL on page 337.
When the value is :DOWNCASE, unescaped constituent characters
are converted to lower-case.
When the value is :PRESERVE, the case of all characters remains
unchanged.
When the value is :INVERT, then if all of the unescaped letters
in the extended token are of the same case, those (unescaped)
letters are converted to the opposite case.
COPY-READTABLE copies the setting of READTABLE-CASE. The value of
READTABLE-CASE for the standard readtable is :UPCASE.
The READTABLE-CASE of *READTABLE* also has significance when printing
The case in which letters are printed, when vertical-bar syntax is not
used, is determined as follows:
When READTABLE-CASE is :UPCASE, upper-case letters are printed
in the case specified by *PRINT-CASE*, and lower-case letters
are printed in their own case.
When READTABLE-CASE is :DOWNCASE, lower-case letters are printed
in the case specified by *PRINT-CASE*, and upper-case letters
are printed in their own case.
When READTABLE-CASE is :PRESERVE, all letters are printed in their
own case.
When READTABLE-CASE is :INVERT, the case of all letters in single-
case symbol names is inverted. Mixed-case symbol names are printed
as-is.
The rules for escaping letters in symbol names are also affected by
the READTABLE-CASE. If *PRINT-ESCAPE* is true, letters are escaped
as follows:
When READTABLE-CASE is :UPCASE, all lower-case letters must be
escaped.
When READTABLE-CASE is :DOWNCASE, all upper-case letters must be
escaped.
When READTABLE-CASE is :PRESERVE, no letters need be escaped.
When READTABLE-CASE is :INVERT, no letters need be escaped.
Rationale:
There are a number of different ways to achieve case-sensitivity.
This proposal is fairly simple but provides all of the functionality
that one could reasonably expect.
By using a property of the readtable, we avoid introducing a new
special variable. Any code that wishes to control all of the
reader's parameters already takes *READTABLE* into account. A new
special variable would require such code to change.
:DOWNCASE is included for symmetry with :UPCASE.
:INVERT is included so that case conventions can be used in Common
Lisp code without requiring that the names of symbols in the "LISP"
package be written in upper case. (Opinions vary as to whether is
is advisable to use such conventions, but this proposal leaves that
choice to the user.)
:INVERT has an effect only for single-case names so that mixed-
case names can be interpreted in a more straightforward way.
In order to avoid complex interactions between the case setting of
the readtable and *PRINT-CASE*, this proposal specifies a
significance for *PRINT-CASE* only when the case setting is :UPCASE
or :DOWNCASE. The meaning of *PRINT-CASE* when the readtable
setting is :DOWNCASE was chosen for its simplicity and for symmetry
with :UPCASE while still being useful.
Test Cases:
;;; Test 1 -- reading
(defun test1 ()
(let ((*readtable* (copy-readtable nil)))
(format t "READTABLE-CASE Input Symbol-name~
~%-----------------------------------~
~%")
(dolist (readtable-case '(:upcase :downcase :preserve :invert))
(setf (readtable-case *readtable*) readtable-case)
(dolist (input '("ZEBRA" "Zebra" "zebra"))
(format t "~&:~A~16T~A~24T~A"
(string-upcase readtable-case)
input
(symbol-name (read-from-string input)))))))
The output from (TEST1) should be as follows:
READTABLE-CASE Input Symbol-name
-----------------------------------
:UPCASE ZEBRA ZEBRA
:UPCASE Zebra ZEBRA
:UPCASE zebra ZEBRA
:DOWNCASE ZEBRA zebra
:DOWNCASE Zebra zebra
:DOWNCASE zebra zebra
:PRESERVE ZEBRA ZEBRA
:PRESERVE Zebra Zebra
:PRESERVE zebra zebra
:INVERT ZEBRA zebra
:INVERT Zebra Zebra
:INVERT zebra ZEBRA
;;; Test 2 -- printing
(defun test2 ()
(let ((*readtable* (copy-readtable nil))
(format t "READTABLE-CASE *PRINT-CASE* Symbol-name Output~
~%--------------------------------------------------~
~%")
(dolist (readtable-case '(:upcase :downcase :preserve :invert))
(setf (readtable-case *readtable*) readtable-case)
(dolist (print-case '(:upcase :downcase :capitalize))
(dolist (symbol '(|ZEBRA| |Zebra| |zebra|))
(setq *print-case* print-case)
(format t "~&:~A~15T:~A~29T~A~42T~A"
(string-upcase readtable-case)
(string-upcase print-case)
(prin1-to-string symbol)))))))
The output from (TEST2) should be as follows:
READTABLE-CASE *PRINT-CASE* Symbol-name Output
--------------------------------------------------
:UPCASE :UPCASE ZEBRA ZEBRA
:UPCASE :UPCASE Zebra |Zebra|
:UPCASE :UPCASE zebra |zebra|
:UPCASE :DOWNCASE ZEBRA zebra
:UPCASE :DOWNCASE Zebra |Zebra|
:UPCASE :DOWNCASE zebra |zebra|
:UPCASE :CAPITALIZE ZEBRA Zebra
:UPCASE :CAPITALIZE Zebra |Zebra|
:UPCASE :CAPITALIZE zebra |zebra|
:DOWNCASE :UPCASE ZEBRA |ZEBRA|
:DOWNCASE :UPCASE Zebra |Zebra|
:DOWNCASE :UPCASE zebra ZEBRA
:DOWNCASE :DOWNCASE ZEBRA |ZEBRA|
:DOWNCASE :DOWNCASE Zebra |Zebra|
:DOWNCASE :DOWNCASE zebra zebra
:DOWNCASE :CAPITALIZE ZEBRA |ZEBRA|
:DOWNCASE :CAPITALIZE Zebra |Zebra|
:DOWNCASE :CAPITALIZE zebra Zebra
:PRESERVE :UPCASE ZEBRA ZEBRA
:PRESERVE :UPCASE Zebra Zebra
:PRESERVE :UPCASE zebra zebra
:PRESERVE :DOWNCASE ZEBRA ZEBRA
:PRESERVE :DOWNCASE Zebra Zebra
:PRESERVE :DOWNCASE zebra zebra
:PRESERVE :CAPITALIZE ZEBRA ZEBRA
:PRESERVE :CAPITALIZE Zebra Zebra
:PRESERVE :CAPITALIZE zebra zebra
:INVERT :UPCASE ZEBRA zebra
:INVERT :UPCASE Zebra Zebra
:INVERT :UPCASE zebra ZEBRA
:INVERT :DOWNCASE ZEBRA zebra
:INVERT :DOWNCASE Zebra Zebra
:INVERT :DOWNCASE zebra ZEBRA
:INVERT :CAPITALIZE ZEBRA zebra
:INVERT :CAPITALIZE Zebra Zebra
:INVERT :CAPITALIZE zebra ZEBRA
Current Practice:
While there may not be any current implementation that supports
exactly this proposal, several implementations provide some means
for changing case sensitivity.
Franz Inc's ExCL has a function, EXCL:SET-CASE-MODE, that sets both
the "preferred case" (the case of characters in the print names of
standard symbols such as CAR) and whether or not the reader is case-
sensitive.
In Symbolics Common Lisp, the function SET-CHARACTER-TRANSLATION
can be used to make the translation of a letter be that same letter,
thus achieving case-sensitivity.
Xerox Medley has a function for setting a readtable flag that
determines case sensitivity.
Cost to Implementors:
Fairly small. The reader will be slightly slower and readtables
will be slightly more complex.
Cost to Users:
Slight. Programmers must already take into account the possibility
that *READTABLE* will be a non-standard readtable. Case-sensitivity
is no worse than character macros in this respect.
Cost of Non-Adoption:
Applications that want to read mixed-case expressions will not
be able to use the Common Lisp reader to do so (except, perhaps,
by tortuous use of read macros).
Programming styles that rely on case distinctions (without escape
characters) will effectively be impossible in Common Lisp.
Benefits:
Applications will be able to read mixed-case expressions.
Programmers will be able to make use of case distinctions.
Aesthetics:
For the proposal:
The language will have greater symmetry, because it will be
possible to control the treatment of case on both input and output
instead of only on output (as is now the case).
The language will look less old-fashioned.
Against the proposal:
It is, perhaps, inconsistent to control case-sensitivity by a
readtable operation when other aspects of the reader, such as the
input base and the default float format (not to mention the
package), are controlled by special variables. However, it can be
argued that character-level syntax is determined chiefly by the
readtable. Case-sensitivity can be seen as analogous to character
macros in this respect.
Discussion:
Dalton supports the proposal READTABLE-KEYWORDS.
Version 1 of the proposal suggested a new global variable rather
than a property of the readtable. Pitman was strongly opposed to
that proposal and gave convincing arguments that it should be
dropped. Gray suggested that the readtable property should be a
function. Versions 2 and 3 included a FUNCTION proposal as well
as the KEYWORD one. But at the March 1989 X3J13 meeting it was
felt that there should be only a single proposal and, since
opinion seemed to favor the KEYWORD proposal, the FUNCTION
proposal was dropped.
In earlier versions of the proposal, :INVERT worked a letter at
a time (rather than operating on extended tokens) so that, for
example, Zebra read as zEBRA. However, the purpose of :INVERT
is to let the programmer get the standard internal case (ie,
upper case) by writing lower case rather than upper. This
matters when referring to single-case symbols such as those
in the LISP package. But, in most cases, mixed-case identifiers
will already have the right case. For example, one would use
TheNextWindow to get TheNextWindow, not tHEnEXTwINDOW.


Pick your pizza size
Small $5
Medium $7
Large $9
XLarge $13
Pick any topping(s) you want to have.
Add cost


Home
About
Editions
Contact
Click here to subscribe to
e-flip
To Subscribe, Publish Your Article, Feedback, Suggestions & Complaints Please Contact
Sai Bhatt K
<EMAIL_ADDRESS>+91<PHONE_NUMBER>
PUBLISH YOUR ARTICLE HERE
QUIZ


Ink.Dom.Browser no longer detects some IE11 mobile browsers as Safari
Fix a bug in Modal when open() is called with no arguments and there's an onShow callback present.
When a Carousel does not have a stage, the error message now makes some more sense than "a is not defined".
Do not crash with <option> elements in FormValidator_2
Do a better feature detection of the vh/vw units, for old IOS safari.
Fix SmoothScroller adding "active" classes in <li> elements, but never removing them
3.1.9
CSS
Hotfix release, updates FontAwesome files.
3.1.8
CSS
Fixes round corners when there's only one child in the .button-group element.
Fixes vertical alignment in Safari.
Base font settings are now defined with the font property and the $base-font-weight,$base-font-stretch and $base-font-variant variables were added.
JS
Dropdown does not need to be passed a 'target' option anymore, it can find its menu by itself
Modal will not stop propagation of events any more
Modal's onShow callback now takes an object with the modal trigger. It now is function (modalInstance, { trigger }) {}
Modal getModalElement, getShadeElement methods, which return the corresponding DOM elements which make up the modal
Pagination JS now supports chevron and dotted mode at the same time.
FormValidator_2 now supports a data-lang option to set its language to something else.
FormValidator_2 FormElement instances now have forceInvalid and forceValid methods, so you can arbitrarily say an input is valid or invalid and bypass all validation rules.
Support Opera Mini, which does not have onscroll, in LazyLoad
InkArray.forEachObj, for iterating an object's key/value pairs as you do in InkArray.forEach.
Fixed an Ink.UI.DatePicker bug in Chrome, which didn't let you select the field.
3.1.7
JS
InkEvent.throttle preventDefault and bind options
Fixed bug in Ajax, when requests are abort()ed, they should not generate errors any more
Adds LazyLoad to Autoload with the .ink-lazyload class
Add loadedClass (data-loaded-class="class-name") option to put classes in LazyLoaded elements when they are loaded so they can be styled.
Adds TL phones to Ink.Util.Validator
Adds EAN validation to Ink.Util.Validator and Ink.UI.FormValidator_2
Fixes multiple onInViewport callbacks in Ink.UI.LazyLoad_1
Make FormValidator's "matches" rule match form elements without a [rules] attribute, because those may not be validated.
Modal now uses Flex and VH/VH CSS dimensions remove or lighten the necessity for javascript layout. It is more smooth and a lot faster too! It gracefully degrades into using some javascript layout, or fully rely on it, on older browsers.
Toggle will now pass (newState, { element }) as arguments to the onChangeState callback, instead of just the new state
DatePicker bugfixes
when isAccordion, the closeOnClick option of a toggle will default to false.
DatePicker lang option, to set the language to Portuguese easily, and an Ink.Util.I18n instance to help create more languages.
Minor breaking change: Ink.UI.Toggle no longer supports detecting whether the toggled element is currently visible (using getComputedStyle) in order to set its initial state. To achieve the same effect, set the class of the first target to be the same as the classNameOn option (which defaults to 'show-all'). This may break some things, but it improves the predictability and usability of the component. d497ba5
getInstance() function in UI component classes. Use it like this: var myModal = Modal.getInstance('#element-with-a-modal'). This deprecates the need of disabling Ink.UI.Autoload to interact with UI components.
Do not pollute elements with data-instance attributes. This also fixes a memory leak when UI components are removed from the DOM.
If you were using requireModules to load modules asynchronously (eg. not using ink-all.js), now there is no default URL for the Ink namespace. This will only affect you if you are using requireModules asynchronously and are not calling setPath() yourself. We're not bumping a major because this is not likely to affect anyone although, theoretically, it's a breaking change.
CSS
Removes a fade() call left over from the old LESS source (#349)
JS
Fixing FormValidator
Removing the default Ink.setPath() call. We removed this because it causes surprising results and brings no benefits, and causes people to accidentally use https://js.ink.sapo.pt every time they misspelled a module name. Now you will get an error.
Drops the makefiles and unifies the dependency management and build process with grunt and bower.
Changes the repository structure. Source code is now kept under "src" and compiled/distributable code is kept in the "dist" folder.
CSS
Layout
Default ink-grid maximum width increased to 1400px.
Adds 2 breakpoints: "tiny" for screen widths below 320px and "xlarge" for screen widths over 1200px. The new breakpoints are disabled by default. To use them you'll need to edit src/less/grid.less and src/less/config/__grid.less and uncomment the code that creates the additional breakpoints.
Adds breakpoint dependent spacing and column horizontal alignment classes i.e. small-top-space, small-push-center.
Adds breakpoint dependent text alignment classes i.e. small-align-center.
Adds breakpoint dependent gutters i.e. small-gutters.
Adds "double" size variant for gutters and spacing class i.e. double-gutters.
Improves CSS selector specificity to avoid class name collisions in several components.
Several bug fixes.
JavaScript
UI
Adds UI Carousel component.
Improves UI Sticky component.
Improves UI DatePicker component.
Improves UI Common.options() component. enables UI modules to receive options of several types including Numbers, Booleans and Selectors (this improves most other components)
Renames Ink.UI.Aux to Ink.UI.Common.
Global fixes and changes
Core Event API change/addition. Integrated Bean ( https://github.com/fat/bean ) in the module. New methods on the API ( on, one, off, clone, fire ). Also created observeDelegated(element, eventName, selector, callback)
Ink.Dom.Element.create() can now call Ink.Dom.Event functions for quick creation and placement of elements: InkElement.create('div', { insertBottom: document.body });
Ink.Dom.Element.wrap() and unwrap.
Core Ajax
Formvalidator v1
Treeview
SortableList
Tagfield
Table
Modal
Sticky
Datepicker
Promoted Ink.Autoload to an Ink module. It now has the Autoload.run() function for running Autoload on dynamically generated content.
structural change: Ink.js Git submodule dropped, now Ink and Ink.js are the same repository
Javascript
Ink.UI.Sticky bugfixes
Ink.UI.Draggables improved
Ink.Dom.Event improvements: throttle (limit the amount of times a function can be called) and observeMulti (attaches an event to a selector or array of elements).
Ink.UI.Toggle now toggles several elements at once, if the selector selects many elements.
Added more spacing and gutter size options. E. g. .half-space, .quarter-space, top-space,
.bottom-space, .left-space, .right-space, .half-gutters, .horizontal-gutters and much more.


{% extends "core/sms/base.html" %} {% block content %} Dear {{fullname}} Your Phone Verification code is {{phone_verification_code}}. {% endblock %}


Image gallery
With caption fom data tags
A nice image gallery with animated caption drawn from the image data tags. Made with CSS3 for modern browsers. Less modern browsers or non-browser (like Internet Explorer) may encounter problems with showing the layout correctly.


Application form
Do you have a Tapdesk Account?
 You will not receive any commissions on qualified sales that close after you delete your account. You will have access to the affiliate portal until your final payoff transaction has been completed. After that, your data will be deleted.
This action can be undone before your final payoff transaction is completed. Once the payoff transaction is completed, this action cannot be undone.


May 13th, 2019
"Electronic mail (email or e-mail) is a method of exchanging messages ("mail") between people using electronic devices. Invented by Ray Tomlinson, email first entered limited use in the 1960s and by the mid-1970s had taken the form now recognized as email." I Email has been around for more than 50 years now. As we go further on our timeline, folks from new generations are starting to forget the beauty of email. This article will discuss the problems with the current state of emails and the ways to bring back joy into it.
When you ask someone to check their email, I am sure they would rather use their phone if they do not have one open already on their computer. The reason for this is the discomfort people have opening their email services in their browsers. The key for this discomfort is time. When I open my email on my laptop, it takes about 5-6 seconds to just open my browser, 2-3 more seconds to enter the email address, and God knows how much longer until my inbox actually opens. Looking at you, Gmail.
People want their services to work fast and without any delays. Phones have apps that open and become operational with just a tap of a finger. However, phone apps are not very extensive in their functionality (attaching files, sorting mail, flagging email, bulk delete) and they do not offer a full range of formatting tools. By all means, they never had to, they are just expected to perform the most basic options.
Due to all the convenience that mobile apps offer, people choose to use it all the time instead of full clients, therefore limiting the number of actions they can make. They just reserve themselves to most basic functionality. Which is very and very unfortunate. Instead of progressing and learning new tools and better ways to perform tasks, users prefer to stick to what they know. This is not only an email problem, it is a general issue with most if not all technologies.
In reality, email is a fantastic way of communication. Indeed, it was the only way to communicate over the Internet back in 1970s and 1980s. As the time progresses and we create our future, developers around the world tried to work on email clients and unfortunately made them more unintuitive and less user-friendly. This beautiful way of communication became this big hassle of navigating to intermediate apps and typing a message.
Is there a solution for this unfortunate turn of events and overcomplication of email technology? I wish to introduce you to Mutt
email client that brings back joy and happiness into emailing each other.
Mutt is a text-based email client developed by Michael Elkins in 1995 for UNIX-like systems. I want to say that this is truly the way emails were meant to be used. Before I start getting angry emails, I am aware of other fantastic TUI
and ncurses
email clients, such as: Gnus, Elm, and Alpine (Used by Brian Kernighan!). However, it is safe to say that Mutt
is the most extensive, feature-rich, actively developed, and well-supported by its community. Just to list some of its features, please take a look at the excerpt from Mutt’s website below:
color support
active development community
full control of message headers when composing
highly customizable, including keybindings and macros
postpone message composition indefinetly for later recall
easily include attachments when composing, even from the command line
easy to install (uses GNU autoconf)
translation into at least 20 languages
small and efficient
It’s free! (no cost and GPL'ed)
and so much more!
Mutt
accompanied with offlineimap
will allow you to have all your emails saved on your machine so you will have a 24/7 access to them even if you do not have internet connection. You can write an email and postpone it indefinitely until your internet connection comes back. It also takes 0.1 seconds to boot it up and start composing a message. Do not forget about the aesthetics and romance with the terminal. Let us talk about the actual setup and what you have to do to be happy with your email experience.
As you might know, email service in itself is relaying on several layers of protocols to retrieve and send mail. There is also POP3 protocol similar to IMAP. I will not discuss the differences between them, but I can assure you that IMAP is always a better choice as it is more organized in its nature. Internet Message Access Protocol or IMAP is used to retrieve all email messages from a mail server over a TCP/IP connection. This is the protocol we will use to download all our messages and store them locally. Simple Mail Transfer Protocol or SMTP is used for sending messages and handling remote mail server message transferring.
You can imagine that Mutt
email client will rely on both of the protocols to operate normally. And you will be right. offlineimap
is a program that allows us to use IMAP protocol and store all messages directly on our machine. There is also an option where you could use Mutt
without offlineimap
, it would mean that everytime you want to open your mailbox, Mutt will contact your mail server to download list of your messages. This is a very time expensive operation as it greatly depends on your bandwidth, internet location, and physical location from the mail server. Also, it would not allow you to access your messages without a constant internet connection. For this article, I will include full offlineimap
configuration before we start using Mutt
.
If you are using one of the bigger Linux distributions (Ubuntu, Fedora, Debian, and etc), it should already be installed. Try runnig % offlineimap
to see if you have an active executable.
|
NOTE
|
% indicates that we are in the terminal. Everything after % should be executed.
|
If you do not have it installed, you can run % sudo pacman -S offlineimap
on Arch Linux to install it or use python package manager pip to install it.
% pip install --user offlineimap
That should get you a fresh copy of offlineimap
.
offlineimap
as a UNIX application, uses a configuration file, conveniently called .offlineimaprc
. To make things easier, touch the file in your home directory or open your favorite tex editor, emacs, and write down the following:
~/.offlineimaprc
----------------
[general]
metadata = ~/.offlineimap
# You can change mymail to something else
accounts = mymail
socktimeout = 60
[Account mymail]
localrepository = local-mymail
remoterepository = remote-mymail
[Repository local-mymail]
type = Maildir
localfolders = ~/.mail/mymail
[Repository remote-mymail]
type = IMAP
remotehost = imap.site.com # edit this
remoteuser = myusername # edit this
remotepass = mypassword # edit this
ssl = yes
realdelete = no
sslcacertfile = /etc/ssl/certs/ca-certificates.crt
This config file just gives us some details about how to contact the IMAP server and how to save it. mymail
is any name of your choice. For my university mail, I have it named kumail
, feel free to name it whatever name is convenient for you.
Local Repository gives info where it store all our email data, that would be .mail/_mymail_
directory in your home directory. Remote repository is a bit more trickier but not difficult. It just specifies what you mail server is. Find your IMAP server, ports are not really important because they are usually the default ones (993). For example, my university has its IMAP server on imap.ku.edu. Username and password should be pretty obvious.
Just run the command below to synchronize your email server and your local mailbox.
% offlineimap
It will take a while to run this command for the first time because it has to download everything. Depending on your mailbox size, it may take a non-trivial time. Just be patient and let it do the magic for you. It is also a good advice for life. Just live the best you can, it will play itself out in the best way possible. Also, a little bit of faith always helps.
With this, we should be ready to comfortably start configuring our new email client.
So far, we talked about Mutt
, but there is also a fork of it (same software with more features), called NeoMutt
. We will be using it instead of Mutt
as it is more extensible, faster, and backward-compatible with Mutt
. You have same configuration files for both of them.
Installation of NeoMutt
is super straight forward. Just pick your favorite flavor of Linux and install a package called neomutt
. For Arch Linux, it just would be
% sudo pacman -S neomutt
Consult with the official downloads page for a list of the biggest distributions and how to install package on them.
For the sake of brevity, I will brake down the configuration into multiple chunks. Firstly, I will talk about basic installation just to get a barebone version working, securing your password, and best of them all, making it super colorful, with signatures, ANSI escape sequences, and other cool stuff.
Just to get you started, the drill is the same as the last time, but now it would be called ~/.muttrc
The config file has a lot of different entries, so to keep it short, I will include the config file and it will be an exercise for the reader to get the meaning of the entries (this will be simple, I promise).
# This should go to ~/.muttrc
# Set up all the folders
set folder="~/.mail/mymail"
mailboxes = +INBOX
mailboxes = +'Sent Items'
mailboxes = +'Deleted Items'
set spoolfile = +INBOX
set trash = +'Deleted Items'
set postponed = +'Drafts'
set record = +'Sent Items'
# Sort by reverse date
set sleep_time = 0
set sort = 'reverse-date'
# Default sending charset
set send_charset="utf-8"
# SMTP FOR SENDING EMAIL
set realname="Big Lebowski" # edit this
set my_user=myusername # edit this
set my_pass=mypassword # edit this
set from =<EMAIL_ADDRESS># edit this
set smtp_url=smtp://$my_user:$my_pass@authsmtp.site.com:587 # edit this
# Sending mail options
set edit_headers=yes
set use_from = yes
set fast_reply=yes
set include=no
# SSL options
set ssl_force_tls = yes
set ssl_starttls = yes
# Default text editor
set editor = $EDITOR
# Ways to open the mail messages
auto_view text/html
alternative_order text/plain text/html
# Headers
my_hdr X-Info: Keep It Simple, Stupid.
my_hdr X-Operating-System: `uname -s`, kernel `uname -r`
my_hdr User-Agent: Every email client sucks, this one just sucks less.
set markers = no
set mark_old = no
set forward_format = "Fwd: %s" # format of subject when forwarding
set forward_decode # decode when forwarding
set forward_quote # include message in forwards
set reverse_name # reply as whomever it was to
#set include # include message in replies
auto_view text/html
auto_view application/pgp-encrypted
alternative_order text/plain text/enriched text/html
set rfc2047_parameters = yes
# Date and index formatting styles
set date_format="%m-%d-%y %T"
set index_format="%2C | %Z [%d] %-30.30F (%-4.4c) %s"# -*-muttrc-*-
You can easily leave everything as it is, just edit all the lines with # edit this
. Please pay a close attention to the line set smtp_url...
. You have to find your SMTP server address and port number (usually 587). After that, your email should be operational!
You might not like that we store your password in plain text in your ~/.muttrc
. I do not like it either. In this section, we will encrypt your email password and only you should be able te unlock it. We will encrypt your password with GPG. To do so, you have to have a pair of keys: public and private. To read more about public and private key encryption, visit its Wikipedia page.
We will make you a pair of your own encryption keys to store your password in a very very secure way.
The following command will get you through everything
% gpg --gen-key
Make a new directory in your home directory with % mkdir ~/.mutt
You have to create your password with % echo set my_pass = '_mypassword_' > ~/.mutt/mypass
|
IMPORTANT
|
Put a space before the command so your system will not save your plain text password in its shell history. |
Encrypt the file with % gpg -r my_email -e ~/.mutt/mypass
, where my_email
is the email address you used when you created your key. You will have a new file called mypass.gpg
that is your actual encrypted password.
You can decrypt it and get the contents with % gpg -d ~/.mutt/mypass.gpg
Remove the old file with % rm mypass
Add the following line to the top of your ~/.muttrc
: source "gpg -dq $HOME/.mutt/mypass.gpg |"
Now, you can get rid of the plain text password from your ~/.muttrc
and you are done! Try opening NeoMutt, it should ask you for your gpg password if you set up one.
Make your signature in the ~/.mutt/mysig.sig
, for example
~/.mutt/mysig.sig
-----------------
Jack Bauer
Director of C.T.U.
Don't call me
Add the line below to include your signature in every new email message. set signature = "$HOME/.mutt/mysig.sig"
If you are feeling dangerous, you can start signing your emails, encrypting them, armored signatures, and other cool stuff. To do that, download link:./gpg.rc[this file], add that to your ~/.mutt/
directory, create one if you don’t have it, and add the following line to your ~/.muttrc
: source ~/.mutt/gpg.rc
Press p
when composing email to see the available options.
Download link:./mailcap[this file], move the file to the ~/.mutt/
directory, add this line to your configuration file set mailcap_path = ~/.mutt/mailcap
Make your NeoMutt look really good. Same drill.
Download link:./color.mutt[this file], move the file to the ~/.mutt/
directory, add this line to your configuration file source $HOME/.mutt/color.mutt
MAKE EMAIL GREAT AGAIN ◼


--- layout: default title: BlogSpot ---
I'm student at Open University Cyprus. This blog is a start of my own work in Photography and Videography. Read more about my life...