Interaction with the outside world.
;;; external.el --- Cunene: My emacs configuration. -*- lexical-binding: t -*-
;; Author: Marco Craveiro <marco_craveiro@gmail.com> URL:
;; https://github.com/mcraveiro/prelude Version: 0.0.3 Keywords: convenience
;; This file is not part of GNU Emacs.
;;; Commentary:
;; General editor configuration
;;; License:
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License
;; as published by the Free Software Foundation; either version 3
;; of the License, or (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Code:
(defun cunene/create-named-bash-shell (name)
"Starts a new named bash shell. Bash must be in the path.
NAME is the postfix for the buffer name."
(interactive "sName: ")
(let
((explicit-shell-file-name "bash")
(explicit-bash-args '("--login" "-i"))
(buffer-name (concat "*shell - " name "*")))
(shell)
(rename-buffer buffer-name)))
(global-set-key (kbd "C-x M") 'cunene/create-named-bash-shell)
Links:
Todo:
(use-package eshell
:config
(add-hook 'eshell-mode-hook
(lambda ()
(setq-local imenu-generic-expression
'(("Prompt" " $ \\(.*\\)" 1)))))
(require 'em-hist)
(require 'em-alias)
(add-to-list
'eshell-command-aliases-list (list "ll" "ls -l"))
(defalias 'ff 'find-file)
(use-package eshell-git-prompt
:config
(setq-default eshell-directory-name (cunene/cache-concat "eshell"))
(eshell-git-prompt-use-theme 'powerline)
(define-advice eshell-git-prompt-powerline-dir (:override () short)
"Show only last directory."
(file-name-nondirectory (directory-file-name default-directory))))
:bind (:map eshell-hist-mode-map
("<down>" . 'next-line)
("<up>" . 'previous-line)
;; ([remap eshell-previous-matching-input-from-input] . helm-eshell-history)
;; ([remap eshell-list-history] . helm-eshell-history)
))
;; Start a new eshell even if one is active.
(global-set-key (kbd "C-x M") (lambda () (interactive) (eshell t)))
;; Start a regular shell if you prefer that.
(global-set-key (kbd "C-x M-m") 'shell)
(defun eshell/z (&optional regexp)
"Navigate to a previously visited directory in eshell, or to
any directory proferred by `consult-dir'."
(let ((eshell-dirs (delete-dups
(mapcar 'abbreviate-file-name
(ring-elements eshell-last-dir-ring)))))
(cond
((and (not regexp) (featurep 'consult-dir))
(let* ((consult-dir--source-eshell `(:name "Eshell"
:narrow ?e
:category file
:face consult-file
:items ,eshell-dirs))
(consult-dir-sources (cons consult-dir--source-eshell
consult-dir-sources)))
(eshell/cd (substring-no-properties
(consult-dir--pick "Switch directory: ")))))
(t (eshell/cd (if regexp (eshell-find-previous-directory regexp)
(completing-read "cd: " eshell-dirs)))))))
(defun cunene/create-named-eshell (name)
"Create an eshell buffer named NAME."
(interactive "sName: ")
(let
((buffer-name (concat "*shell - " name "*")))
(eshell)
(rename-buffer buffer-name)))
(global-set-key (kbd "C-x m") 'cunene/create-named-eshell)
(use-package project-shells)
;; (use-package deadgrep
;; :ensure t)
(use-package rg)
;; hard-code location of Chrome and Edge on Windows.
(defvar cunene/browse-url-edge-program
(if (eq system-type 'windows-nt)
"C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
"/opt/microsoft/msedge/msedge")
"The name by which to invoke the Edge program.")
(if (eq system-type 'windows-nt)
(setq browse-url-chrome-program "C:/Program Files/Google/Chrome/Application/chrome"))
(defvar cunene/browse-url-edge-arguments ""
"Additional arguments for Edge.")
(defun cunene/browse-url-edge (url &optional _new-window)
"Ask the Google Edge WWW browser to load URL.
Default to the URL around or before point. The strings in
variable `cunene/browse-url-edge-arguments' are also passed to
Google Edge.
The optional argument NEW-WINDOW is not used."
(interactive (browse-url-interactive-arg "URL: "))
(setq url (browse-url-encode-url url))
(let* ((process-environment (browse-url-process-environment)))
(apply #'start-process
(concat "google-edge " url) nil
cunene/browse-url-edge-program
(append
cunene/browse-url-edge-arguments
(list url)))))
(defvar cunene/browsers
'(("Chrome" . browse-url-chrome)
("EWW" . eww-browse-url)
("Edge" . cunene/browse-url-edge)
("Firefox" . browse-url-firefox))
"Available web browsers.")
(defvar cunene/last-browser nil
"Last browser selected by the user.")
(defun cunene/browse-url (&rest args)
"Select the prefered browser from a menu before opening the URL.
If ARGS are supplied, will always ask. Else it remember the user choice."
(interactive)
(if (or
(null cunene/last-browser) ;; no previous browser?
(not (null (cl-first (cdr args))))) ;; any args supplied other than the URL?
(progn
(setq cunene/last-browser (completing-read "WWW browser: " cunene/browsers nil t ""))
(apply (cdr (assoc cunene/last-browser cunene/browsers)) args))
(apply (cdr (assoc cunene/last-browser cunene/browsers)) args)))
(setq browse-url-browser-function #'cunene/browse-url)
;; Sourced from here:
;; - https://emacs.stackexchange.com/questions/50433/add-browser-bookmark-to-bookmark-browser
;; FIXME this breaks bookmark display at present.
(require 'bookmark)
(defun cunene/bookmark-url (url)
"Add URL to bookmarks."
(interactive "sBookmark URL: ")
(if (assoc url bookmark-alist)
(user-error "%s is already bookmarked" url)
(push `(,url . ((handler . ,(lambda (bookmark)
(browse-url (car bookmark))))))
bookmark-alist)))
;; Make addresses clickable
(global-goto-address-mode)
(use-package ssh
:config (add-hook 'ssh-mode-hook
(lambda ()
(setq ssh-directory-tracking-mode t)
(push '(ssh-mode comint-input-ring comint-input-ring-index comint-bol) consult-mode-histories)
(shell-dirtrack-mode t)
(setq dirtrackp nil))))
(require 'tramp)
(setq tramp-default-method "ssh")
(setq ssh-explicit-args nil)
(tramp-change-syntax 'default)
;; Putty is expected to be on the path.
(when (string-equal system-type "windows-nt")
(setq ssh-program "putty")
(add-to-list 'tramp-methods
`("plinkw"
(tramp-login-program "plink")
;; ("%h") must be a single element, see `tramp-compute-multi-hops'.
(tramp-login-args (("-l" "%u") ("-P" "%p") ("-t")
("%h") ("\"")
(,(format
"env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'"
tramp-terminal-type
"$"))
("/bin/sh") ("\"")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-default-port 22))
))
(use-package prodigy
:bind ("C-c 8" . #'prodigy)
:config
;; (load "~/.config/emacs/services.el" 'noerror)
)
(use-package inf-mongo)
;; Examples:
;; (cunene/mongo-oid-from-date "2023-03-09")
;; (cunene/mongo-oid-from-date)
(defun cunene/mongo-oid-from-date (&optional date)
"Return a valid MongoDB ObjectId for the specified DATE."
(let ((timestamp
(format "%x"
(time-to-seconds
(date-to-time (or date (current-time)))))) ;; FXIME: current time needs conversion
(machine-id (s-pad-right 3 "\x00" (format "%x" (cl-random 16777216))))
(pid (s-pad-right 2 "\x00" (format "%x" (emacs-pid))))
(increment (s-pad-right 3 "\x00" (format "%x" (cl-random 16777216)))))
(format "%s%s%s%s" timestamp machine-id pid increment))
)
(defun cunene/object-id-to-timestamp (start end)
"Given a region with a mongo ObjectId, return the timestamp.
START and END mark the region."
(interactive "r")
(let*
((object-id (buffer-substring-no-properties (mark) (point)))
(timestamp-hex (substring-no-properties object-id 0 8))
(timestamp-num (string-to-number timestamp-hex 16)))
(message "Timestamp: %s"
(format-time-string "%Y-%m-%d %a %H:%M:%S" timestamp-num)))
)
(defun cunene/timet-to-timestamp (start end)
"Given a region with a UNIX timestamp in time_t, return the human timestamp.
START and END mark the region."
(interactive "r")
(let*
((time-t-string (buffer-substring-no-properties (mark) (point)))
(timestamp-num (string-to-number time-t-string))
(timestamp-time (seconds-to-time timestamp-num)))
(message "Timestamp: %s"
(format-time-string "%Y-%m-%d %a %H:%M:%S" timestamp-time)))
)
;;; external.el ends here