#+TITLE: Personal Password Generator #+AUTHOR: Howard X. Abrams #+EMAIL: howard.abrams@gmail.com #+DATE: 2021-01-11 #+FILETAGS: :emacs: A literate programming version for Emacs code to generate and store passwords. #+BEGIN_SRC emacs-lisp :exports none ;;; ha-passwords.el --- A literate programming version for Emacs code to generate and store passwords. -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2021 Howard X. Abrams ;; ;; Author: Howard X. Abrams ;; Maintainer: Howard X. Abrams ;; Created: January 11, 2021 ;; ;; This file is not part of GNU Emacs. ;; ;; *NB:* Do not edit this file. Instead, edit the original literate file at: ;; /Users/howard.abrams/other/hamacs/ha-passwords.org ;; And tangle the file to recreate this one. ;; ;;; Code: #+END_SRC * Introduction Let's assume that I store a bunch of words in data files: #+BEGIN_SRC emacs-lisp (defvar ha-passwords-data-files (list (expand-file-name "adjectives.txt" (expand-file-name "data" hamacs-source-dir)) (expand-file-name "colors.txt" (expand-file-name "data" hamacs-source-dir)) (expand-file-name "nouns.txt" (expand-file-name "data" hamacs-source-dir))) "List of file name containing a data lines for our password generator. Order of these files matter.") (defvar ha-passwords-data nil "Contains a list of lists of words that we can choose.") #+END_SRC You can see where I'm going with this, can't you? Let's read them into list variables. #+BEGIN_SRC emacs-lisp (defun ha-passwords--read-data-file (filename) (with-temp-buffer (insert-file-contents filename) (split-string (buffer-string) "\n" t))) #+END_SRC Now we just get three or so words from our list of lists: #+BEGIN_SRC emacs-lisp (defun ha-passwords-words () (unless ha-passwords-data (setq ha-passwords-data (--map (ha-passwords--read-data-file it) ha-passwords-data-files))) (--map (nth (random (length it)) it) ha-passwords-data)) #+END_SRC Let's make a password: #+BEGIN_SRC emacs-lisp (defun ha-passwords-generate (&optional separator) (unless separator (setq separator "-")) (let* ((choices '("!" "@" "#" "$" "%" "^" "&" "*")) (choice (random (length choices))) (number (1+ choice))) (->> (ha-passwords-words) (s-join separator) (s-capitalize) (s-append (nth choice choices)) (s-append (number-to-string number))))) #+END_SRC #+BEGIN_SRC emacs-lisp (defun generate-password (&optional separator) (interactive) (let ((passphrase (ha-passwords-generate separator))) (kill-new passphrase) (message "Random password: %s" passphrase))) #+END_SRC * Keybindings Got make it easy to call: #+BEGIN_SRC emacs-lisp (ha-leader "a g" '("generate passwd" . generate-password)) #+END_SRC * Technical Artifacts :noexport: This will =provide= a code name, so that we can =require= this. #+BEGIN_SRC emacs-lisp :exports none (provide 'ha-passwords) ;;; ha-passwords.el ends here #+END_SRC #+DESCRIPTION: A literate programming version for Emacs code to generate and store passwords. #+PROPERTY: header-args:sh :tangle no #+PROPERTY: header-args:emacs-lisp :tangle yes #+PROPERTY: header-args :results none :eval no-export :comments no mkdirp yes #+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil date:nil #+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil #+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js