Smart operator looks promising, but I have not tried it so I can't speak for it. A prebuilt solution would be ideal, but if none are sufficient, it would be very easy to wrap write this functionality and wrap it in a minor mode though.
Here's my go:
(defvar auto-punc-punctuation-members (string-to-list ".,:;?!") "List of charactesr to insert spaces after") (defvar auto-punc-ignore-members (string-to-list " \t") "List of characters to not auto insert spaces before") (defun auto-punc-maybe-do () "If the last entered character is not in `auto-punc-punctuation-members' or `auto-punc-ignore-members', and the prior character is in `auto-punc-punctuation-members', insert a space between the two characters. " (when (and auto-space-punctuation-mode (not (member (char-before) (append auto-punc-punctuation-members auto-punc-ignore-members))) (member (char-before (1- (point))) auto-punc-punctuation-members)) (backward-char 1) (insert " ") (forward-char 1))) (define-minor-mode auto-space-punctuation-mode "Automatically inserts spaces between some punctuation and other characters." :init-value nil :lighter "._a" :keymap nil (make-variable-buffer-local 'post-self-insert-hook) (if auto-space-punctuation-mode (add-hook 'post-self-insert-hook 'auto-punc-maybe-do) (remove-hook 'post-self-insert-hook 'auto-punc-maybe-do)))
You could simply add it to your init and auto enable it when you want like
(add-hook 'text-mode-hook 'auto-space-punctuation-mode)
Everytime you insert a character the function auto-punc-maybe-do runs, read the docstring to ensure this is the behavior you want. Basically if you type punctuation, then anything that is not punctuation or whitespace, a space will be inserted automatically.