diff --git a/config/index.html b/config/index.html index 3e7762c..4d0bf54 100644 --- a/config/index.html +++ b/config/index.html @@ -3,7 +3,6 @@ https://sqrtminusone.xyz/configs/readme/ - diff --git a/configs/console/index.html b/configs/console/index.html index 9666c29..b87b4f0 100644 --- a/configs/console/index.html +++ b/configs/console/index.html @@ -76,7 +76,8 @@
-

No matter from which side you approach penguins, more always come from behind

+

No matter from which side you approach penguins, more always come from behind

+ @@ -411,7 +412,8 @@

Micromamba

I’ve moved from conda to micromamba because it’s faster.

-

managed by ‘mamba init’ !!!

+

managed by ‘mamba init’ !!!

+

Yeah, tell this to yourself

init_mamba () {
     export MAMBA_EXE="/home/pavel/.guix-extra-profiles/dev/dev/bin/micromamba";
@@ -1286,7 +1288,7 @@
     
  • Android notes
  • diff --git a/configs/desktop/index.html b/configs/desktop/index.html index d97f512..280a1a4 100644 --- a/configs/desktop/index.html +++ b/configs/desktop/index.html @@ -725,8 +725,8 @@
    (cl-loop while (windmove-find-other-window opposite-dir) do (windmove-do-window-select opposite-dir))))))

    Update the monitor list

    -
    (defun my/exwm-refresh-monitors ()
    -  (interactive)
    +
    (defun my/exwm-refresh-monitors (&optional refresh)
    +  (interactive (list t))
       (setq my/exwm-monitor-list (my/exwm-xrandr-monitor-list))
       (cl-loop for i from 0 to (1- exwm-workspace-number)
                for monitor = (plist-get exwm-randr-workspace-monitor-plist
    @@ -735,7 +735,8 @@
                do
                (setf (plist-get exwm-randr-workspace-monitor-plist i)
                      (car my/exwm-monitor-list)))
    -  (exwm-randr-refresh))
    +  (when refresh
    +    (exwm-randr-refresh)))
     

    Completions

    Setting up some completion interfaces that fit particularly well to use with EXWM. While rofi also works, I want to use Emacs functionality wherever possible to have one completion interface everywhere.

    ivy-posframe

    @@ -4189,7 +4190,7 @@ office - libreoffice + libreoffice-fresh office diff --git a/configs/emacs/index.html b/configs/emacs/index.html index 1e2692c..0cd7525 100644 --- a/configs/emacs/index.html +++ b/configs/emacs/index.html @@ -76,7 +76,8 @@
    -

    One day we won’t hate one another, no young boy will march to war and I will clean up my Emacs config. But that day isn’t today.

    +

    One day we won’t hate one another, no young boy will march to war and I will clean up my Emacs config. But that day isn’t today.

    + @@ -892,6 +893,11 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
    (message "Processed %s as emacs config module" (buffer-file-name)))) (add-hook 'org-babel-post-tangle-hook #'my/modules--post-tangle) +

    Launch Emacs with the remote env (for TRAMP):

    +
    (defun my/emacs-tramp ()
    +  (interactive)
    +  (with-environment-variables (("EMACS_ENV" "remote"))
    +    (start-process "emacs-tramp" nil "emacs")))
     

    Performance

    Measure startup speed

    A small function to print out the loading time and number of GCs during the loading. Can be useful as a point of data for optimizing Emacs startup time.

    @@ -987,7 +993,7 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp

    I have a problem with emacs-lisp-mode as initial-major-mode because in my config it loads lispy, which loads org-mode.

    So until I’ve made a better loading screen, this will do.

    (setq initial-major-mode 'fundamental-mode)
    -(setq initial-scratch-message "Hello there <3\n\n")
    +(setq initial-scratch-message "Hallo Leben")
     

    General settings

    Keybindings

    general.el

    @@ -1516,7 +1522,8 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp (general-imap "M-TAB" 'company-yasnippet)

    Input Method

    -

    I have to switch layouts all the time, especially in LaTeX documents, because for some reason the Bolsheviks abandoned the idea of replacing Russian Cyrillic letters with Latin ones.

    +

    I have to switch layouts all the time, especially in LaTeX documents, because for some reason the Bolsheviks abandoned the idea of replacing Russian Cyrillic letters with Latin ones.

    + @@ -1644,6 +1651,62 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp (number-to-string number) (line-beginning-position) (line-end-position))))) +
    Edit string a point
    +

    A function to edit the string at point in a temporary buffer with chosen major mode. Somewhat like org-edit-special.

    +
    (defvar my/edit-elisp-string--window-config nil)
    +
    +(defun my/edit-elisp-string ()
    +  (interactive)
    +  (if (org-src-edit-buffer-p)
    +      (org-edit-src-exit)
    +    (let* ((bounds (bounds-of-thing-at-point 'string))
    +           (orig-buf (current-buffer))
    +           (orig-str (when bounds
    +                       (buffer-substring-no-properties (car bounds) (cdr bounds)))))
    +      (unless bounds
    +        (user-error "No string under cursor"))
    +      ;; Not sure if there's a better way
    +      (let* ((mode (intern
    +                    (completing-read
    +                     "Major mode: " obarray
    +                     (lambda (sym)
    +                       (and (commandp sym)
    +                            (string-suffix-p "-mode" (symbol-name sym))))
    +                     t)))
    +             (edit-buf (generate-new-buffer "*string-edit*")))
    +        (setq edit-elisp-string--window-config (current-window-configuration))
    +        (with-current-buffer edit-buf
    +          (insert (string-replace
    +                   "\\\"" "\"" (substring orig-str 1 -1)))
    +          (funcall mode)
    +          (use-local-map (copy-keymap (current-local-map)))
    +          ;; Confirm edit
    +          (local-set-key
    +           (kbd "C-c '")
    +           (lambda ()
    +             (interactive)
    +             (let ((new-str (buffer-substring-no-properties
    +                             (point-min) (point-max))))
    +               (with-current-buffer orig-buf
    +                 (delete-region (car bounds) (cdr bounds))
    +                 (goto-char (car bounds))
    +                 (insert (prin1-to-string new-str))))
    +             (kill-buffer edit-buf)
    +             (when edit-elisp-string--window-config
    +               (set-window-configuration edit-elisp-string--window-config))))
    +          ;; Cancel edit
    +          (local-set-key
    +           (kbd "C-c C-k")
    +           (lambda ()
    +             (interactive)
    +             (kill-buffer edit-buf)
    +             (when edit-elisp-string--window-config
    +               (set-window-configuration edit-elisp-string--window-config)))))
    +        (pop-to-buffer edit-buf)))))
    +
    +(general-define-key
    + :keymaps '(emacs-lisp-mode-map lisp-interaction-mode-map)
    + "C-c '" #'my/edit-elisp-string)
     

    Working with projects

    Packages related to managing projects.

    I used to have Treemacs here, but in the end decided that dired with dired-sidebar does a better job. Dired has its separate section in “Applications”.

    @@ -5132,7 +5195,8 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp (my-leader-def :keymaps 'org-mode-map "SPC b" '(:wk "org-babel") - "SPC b" org-babel-map)) + "SPC b" org-babel-map + "SPC h" #'consult-org-heading))

    Managing a literate programming project

    A few tricks to do literate programming. I actually have only one (sqrt-data), and I’m not convinced in the benefits of the approach…

    Anyway, Org files are better off in a separated directory (e.g. org). So I’ve come up with the following solution to avoid manually prefixing the :tangle arguments.

    @@ -6217,21 +6281,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp (cl-function (lambda (&rest args &key error-thrown &allow-other-keys) (message "Got error: %S" error-thrown))))) my/weather-value) -

    Let’s also try to log the current mood:

    -
    (defun my/get-mood ()
    -  (let* ((crm-separator " ")
    -         (crm-local-completion-map
    -          (let ((map (make-sparse-keymap)))
    -            (set-keymap-parent map crm-local-completion-map)
    -            (define-key map " " 'self-insert-command)
    -            map))
    -         (vertico-sort-function nil))
    -    (mapconcat
    -     #'identity
    -     (completing-read-multiple
    -      "How do you feel: "
    -      my/mood-list)
    -     " ")))
     

    And here’s the function that creates a drawer with such information. At the moment, it’s:

    (defun my/set-journal-header ()
    @@ -6267,9 +6315,7 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
               (when title
                 (setq string (concat string title)))
               (when (> (length string) 0)
    -            (org-set-property "EMMS_Track" string))))))
    -  (when-let (mood (my/get-mood))
    -    (org-set-property "Mood" mood)))
    +            (org-set-property "EMMS_Track" string)))))))
     
     (add-hook 'org-journal-after-entry-create-hook
               #'my/set-journal-header)
    @@ -6370,7 +6416,8 @@ Didn’t work out as I expected, so I’ve made org-journal-tagsAbout installing the package on Guix (CREDIT: thanks @Ashraz on the SystemCrafters discord)

    So, for all those interested: unfortunately, org-roam (or rather emacsql-sqlite) cannot compile the sqlite.c and emacsql.c due to missing headers (linux/falloc.h) on Guix. You would have to properly set all the include paths on Guix, and also adjust the PATH to have gcc actually find as later on in the compilation process.

    -

    Instead, you should remove all Org-Roam related packages from your Emacs installation (via M-x package-delete org-roam RET and M-x package-autoremove RET y RET) and then use the Guix package called emacs-org-roam.

    +

    Instead, you should remove all Org-Roam related packages from your Emacs installation (via M-x package-delete org-roam RET and M-x package-autoremove RET y RET) and then use the Guix package called emacs-org-roam.

    +

    References:

    • Hitchhiker’s Rough Guide to Org roam V2
    • @@ -7110,7 +7157,10 @@ Didn’t work out as I expected, so I’ve made org-journal-tags ("beamer" "\\documentclass[presentation]{beamer}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))))) + ("\\subsubsection{%s}" . "\\subsubsection*{%s}")))) + (with-eval-after-load 'ox-beamer + (add-to-list 'org-beamer-environments-extra + '("dummy" "d" "\\begin{dummyenv}" "\\end{dummyenv}")))) ;; Make sure to eval the function when org-latex-classes list already exists (with-eval-after-load 'ox-latex @@ -9657,7 +9707,8 @@ Didn’t work out as I expected, so I’ve made org-journal-tagswallabag is a self-hosted “read it later” app.

      This might be the best online reading advice I’ve heard:

      -

      I have a different approach: waiting periods. Every time I come across something I may want to read/watch, I’m totally allowed to. No limits! The only requirement is I have to save it to Pocket, and then choose to consume it at a later time.

      +

      I have a different approach: waiting periods. Every time I come across something I may want to read/watch, I’m totally allowed to. No limits! The only requirement is I have to save it to Pocket, and then choose to consume it at a later time.

      +

      Source: Tiago Forte - The Secret Power of ‘Read It Later’ Apps

      (use-package wallabag
         :straight (:host github :repo "chenyanming/wallabag.el" :files (:defaults "default.css" "emojis.alist"))
      @@ -9802,7 +9853,8 @@ Didn’t work out as I expected, so I’ve made org-journal-tagsScroll to the previous mention.

      alphapapa 🐃​> And, yes, that is a currently unsolved problem. As I said, in the future we can try using a different API endpoint to access those notifications similarly to Element. In the meantime, you can load old messages (e.g. “C-u 1000 M-v” to load 1000 old ones at a time), until you find it, maybe using “C-s sqrtm” to search for messages mentioning you.

      -

      Or you can load up Element for a moment to see what the mention was, if that’s easier.

      +

      Or you can load up Element for a moment to see what the mention was, if that’s easier.

      +
      (defun my/ement-about-me-p (event)
         (let ((me (ement-user-id (ement-session-user ement-session))))
           (or
      @@ -10651,12 +10703,13 @@ Didn’t work out as I expected, so I’ve made org-journal-tagsAs I mentioned earlier, my current options to manage a particular node are:

      • git;
      • -
      • MEGA - for files that don’t fit into git, such as DOCX documents, photos, etc.;
      • +
      • MEGA - for files that don’t fit into git, such as DOCX documents, photos, etc. (UPD 2025.10.22 - MEGA has been banned in Russia, of course…);
      • +
      • ownCloud Infinite Scale (self-hosted by me) via rclone - instead of MEGA.
      • “nothing” - for something that I don’t need to sync across machines, e.g. database dumps.
      -

      Another tool I considered was restic. It’s an interesting backup & sync solution with built-in encryption, snapshots, etc.

      -

      However, a challenge I encountered is that its repositories are only accessible via restic. So, even if I use something like MEGA as a backend, I won’t be able to use the MEGA file-sharing features, which I occasionally want for document or photo folders. Hence, for now, I’m more interested in synchronizing the file tree in MEGA with MEGAcmd (and also clean up the mess up there).

      -

      Another interesting tool is rclone, which provides a single interface for multiple services like Google Drive, Dropbox, S3, WebDAV. It also supports MEGA, but it requires turning off the two-factor authentication, which I don’t want.

      +

      rclone is nice because it provides a single interface for multiple services like Google Drive, Dropbox, S3, WebDAV. It also supported MEGA, but it required turning off 2FA, which I didn’t want.

      +

      So the MEGA functionality used MEGAcmd. I’ll keep it for now.

      +

      Another tool I considered was restic. It’s an interesting backup & sync solution with built-in encryption, snapshots, etc., but the repositories are only accessible via restic, which prevents using file-sharing features.

      Implementation

      Dependencies

      We’ll a package called ini.el to parse INI files.

      @@ -10675,7 +10728,7 @@ Didn’t work out as I expected, so I’ve made org-journal-tags

      Each “area” is an Org header with the folder tag; the Org hierarchy forms the file tree. A header can have the following properties:

      • machine - a list of hostnames for which the node is active (or nil)
      • -
      • kind - mega, git, or dummy
      • +
      • kind - mega, rclone:<remote>, git, or dummy. For now, only one option per node; I’ll probably change that in the future.
      • remote - remote URL for git
      • symlink - in case the folder has to be symlinked somewhere else
      @@ -10689,16 +10742,16 @@ Didn’t work out as I expected, so I’ve made org-journal-tags
      :END: **** 10.03.A Artifacts :PROPERTIES: -:kind: mega +:kind: rclone:ocis :END: **** 10.03.D Documents :PROPERTIES: -:kind: mega +:kind: rclone:ocis :END: **** 10.03.R Repos ***** 10.03.R.00 digital-trajectories-deploy :PROPERTIES: -:kind: mega +:kind: rclone:ocis :END: ***** 10.03.R.01 digital-trajectories-backend :PROPERTIES: @@ -10740,14 +10793,17 @@ Didn’t work out as I expected, so I’ve made org-journal-tags (setf (alist-get :symlink val) symlink)) (when (org-element-property :PROJECT heading) (setf (alist-get :project val) t)) - (when-let* ((kind-str (org-element-property :KIND heading)) - (kind (intern kind-str))) - (setf (alist-get :kind val) kind) - (when (equal kind 'git) + (when-let* ((kind-str (org-element-property :KIND heading))) + (when (string-match-p (rx bos "rclone:") kind-str) + (setf (alist-get :remote val) + (substring kind-str 7)) + (setq kind-str "rclone")) + (when (equal kind-str "git") (let ((remote (org-element-property :REMOTE heading))) (unless remote (user-error "No remote for %s" (alist-get :name val))) - (setf (alist-get :remote val) remote)))) + (setf (alist-get :remote val) remote))) + (setf (alist-get :kind val) (intern kind-str))) (setf (alist-get :name val) (org-element-property :raw-value heading) (alist-get :path val) new-path) val))) @@ -11039,6 +11095,258 @@ Didn’t work out as I expected, so I’ve made org-journal-tags (format "mega-sync -d \"%s\"" (substring path 0 (1- (length path)))) "Mega remove sync" 4))))) +
      rclone
      +

      This section wraps the bisync command for rclone, which implements two-way sync.

      +

      The general approach is:

      +
        +
      • Consider the directory unsynced if it doesn’t have the .rclone-test-<remote> file, which is used with the –check-access and –check-filename path. --check-access prevents rclone from running unless the check file exists in both places (i.e., locally and remotely).
      • +
      • For unsynced directories, run rclone mkdir to create remote directory, touch and rclone touch to create the check file.
      • +
      • For unsynced directories, run the sync command with the –resync flag for initial sync.
      • +
      • For all directories, create a bash script that would run the sync command normally.
      • +
      +

      First, default options for rclone bisync:

      +

      +
      (defconst my/index--rclone-options
      +  `("--create-empty-src-dirs"
      +    "--resilient"
      +    "--metadata"
      +    "--filters-file"
      +    ,(expand-file-name "~/.config/rclone/filters-bisync")))
      +

      A filters file for rclone:

      +
      - .*
      +- ~*
      +- .debris
      +

      Not yet sure what’s that supposed to be.

      +
      (defconst my/index--rclone-script-path "~/bin/rclone-scripts/")
      +

      First, get folders to be synced from the tree:

      +
      (defun my/index--rclone-get-folders (tree)
      +  "Get TREE nodes to be synced with rclone.
      +
      +Return a list of alists with the following keys:
      +- `:local-path' - path in the local filesystem
      +- `:remote-path' - path in the remote
      +- `:remote' - name of the remote."
      +  (cl-loop for node in tree
      +           if (eq (alist-get :kind node) 'rclone)
      +           collect
      +           `((:local-path . ,(file-name-as-directory (alist-get :path node)))
      +             (:remote-path
      +              . ,(concat (alist-get :remote node)
      +                         ":" (my/index--mega-local-path
      +                              (file-name-as-directory (alist-get :path node)))))
      +             (:remote . ,(alist-get :remote node)))
      +           append (my/index--rclone-get-folders
      +                   (alist-get :children node))))
      +

      Then, get the sync command:

      +
      (defun my/index--rclone-make-command (local-path remote-path remote)
      +  "Make a bisync command to sync LOCAL-PATH and REMOTE-PATH.
      +
      +REMOTE is the name of the remote."
      +  (string-join
      +   `("rclone"
      +     "bisync"
      +     ,(format "\"%s\"" local-path)
      +     ,(format "\"%s\"" remote-path)
      +     ,@my/index--rclone-options
      +     "--check-filename"
      +     ,(format ".rclone-test-%s" remote))
      +   " "))
      +

      A python script to run rclone.

      +

      +
      import subprocess
      +import json
      +import sys
      +
      +REMOTE = '<rclone-remote>'
      +FOLDERS = json.loads('<rclone-folders-json>')
      +OPTIONS = json.loads('<rclone-options>')
      +
      +
      +def rclone_make_command(local_path, remote_path, remote):
      +    return [
      +        'rclone',
      +        'bisync',
      +        local_path,
      +        remote_path,
      +        *OPTIONS,
      +        '--check-filename',
      +        f'.rclone-test-{REMOTE}',
      +        '--verbose',
      +        '--color',
      +        'NEVER',
      +        '--use-json-log',
      +        '--stats',
      +        '9999m'
      +    ]
      +
      +
      +def parse_rclone_stats(log_output):
      +    log = log_output.splitlines()
      +    log.reverse()
      +    for line in log:
      +        try:
      +            log_entry = json.loads(line)
      +            if 'stats' in log_entry:
      +                return log_entry['stats']
      +        except json.JSONDecodeError:
      +            continue
      +
      +    return None
      +
      +
      +def process_output(output):
      +    if output is None:
      +        print('(empty)')
      +    for line in output.splitlines():
      +        try:
      +            datum = json.loads(line)
      +            print(datum['msg'])
      +        except Exception:
      +            print(line)
      +
      +def rclone_run(folder):
      +    command = rclone_make_command(
      +        folder['local-path'], folder['remote-path'], folder['remote']
      +    )
      +    try:
      +        result = subprocess.run(command, check=True, capture_output=True, text=True)
      +    except subprocess.CalledProcessError as e:
      +        print(f'=== Error syncing {folder['local-path']} ===')
      +        print(f'Command: {' '.join(command)}')
      +        print(f'--- STDOUT ---')
      +        process_output(e.stdout)
      +        print(f'--- STDERR ---')
      +        process_output(e.stderr)
      +        return {'success': False, 'stats': {}}
      +    return {'success': True, 'stats': parse_rclone_stats(result.stderr)}
      +
      +
      +def notify(summary, body, level='normal', expire_time=5000):
      +    subprocess.run(['notify-send', '-u', level, '-t', str(expire_time), summary, body])
      +
      +# Source: https://stackoverflow.com/questions/1094841/get-a-human-readable-version-of-a-file-size
      +def sizeof_fmt(num, suffix='B'):
      +    for unit in ('', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi'):
      +        if abs(num) < 1024.0:
      +            return f'{num:3.1f}{unit}{suffix}'
      +        num /= 1024.0
      +    return f'{num:.1f}Yi{suffix}'
      +
      +
      +def rclone_run_all(folders):
      +    error_folders = []
      +    total_bytes = 0
      +    total_transfers = 0
      +    total_deleted = 0
      +    total_renamed = 0
      +    for folder in folders:
      +        print(f'Running rclone for {folder}')
      +        res = rclone_run(folder)
      +        if not res['success']:
      +            error_folders.append(folder['local-path'])
      +        else:
      +            total_bytes += res.get('stats', {}).get('bytes', 0)
      +            total_transfers += res.get('stats', {}).get('transfers', 0)
      +            total_deleted += res.get('stats', {}).get('deletes', 0)
      +            total_renamed += res.get('stats', {}).get('renames', 0)
      +    if len(error_folders) > 0:
      +        error_msg = f'Sync error for remote {REMOTE}!'
      +        for folder in error_folders:
      +            error_msg += '''\n- ''' + folder
      +        notify(f'rclone sync {REMOTE}', error_msg, level='critical')
      +    else:
      +        msg = ''
      +        if total_transfers > 0:
      +            msg += f'''Transferred {total_transfers} files ({sizeof_fmt(total_bytes)})\n'''
      +        if total_deleted > 0:
      +            msg += f'''Deleted {total_transfers} files\n'''
      +        if total_renamed > 0:
      +            msg += f'''Renamed {total_renamed} files\n'''
      +        if len(msg) > 0:
      +            notify(f'rclone sync {REMOTE}', msg)
      +
      +if __name__ == '__main__':
      +    rclone_run_all(FOLDERS)
      +

      A function that templates the script above:

      +
      (defun my/index--rclone-script (remote folders)
      +  (let ((script "
      +<<rclone-sync-script>>
      +"))
      +    (setq script
      +          (thread-last script
      +                       (string-trim)
      +                       (string-replace "<rclone-remote>" remote)
      +                       (string-replace "<rclone-folders-json>"
      +                                       (json-encode folders))
      +                       (string-replace "<rclone-options>"
      +                                       (json-encode my/index--rclone-options))))
      +    script))
      +
      (defun my/index--rclone-script-loc (remote)
      +  (concat (file-name-as-directory
      +           (expand-file-name my/index--rclone-script-path))
      +          (format "rclone_%s.py" remote)))
      +

      And checks if the script needs to be updated:

      +
      (defun my/index--rclone-script-saved-p (remote folders)
      +  (let* ((script (my/index--rclone-script remote folders))
      +         (script-loc (my/index--rclone-script-loc remote)))
      +    (when (file-exists-p script-loc)
      +      (with-temp-buffer
      +        (insert-file-contents script-loc)
      +        (equal (string-trim (buffer-string)) script)))))
      +

      Putting everything together:

      +
      (defun my/index--rclone-commands (tree)
      +  "Get commands to set up sync with rclone in TREE.
      +
      +TREE is a form a defined by `my/index--tree-get'.  This is supposed to
      +be the tree narrowed to the current machine (`my/index--tree-narrow').
      +
      +The return value is a list of commands as defined by
      +`my/index--commands-display'."
      +  (let ((folders (my/index--rclone-get-folders tree))
      +        commands
      +        sync-items-per-remote)
      +    (dolist (folder folders)
      +      (pcase-let*
      +          ((`((:local-path . ,local-path) (:remote-path . ,remote-path)
      +              (:remote . ,remote))
      +            folder)
      +           (test-file-name (format ".rclone-test-%s" remote))
      +           (test-file-local (concat local-path test-file-name))
      +           (test-file-remote (concat remote-path test-file-name)))
      +        (unless (file-exists-p test-file-local)
      +          (push
      +           (list (format "touch \"%s\"" test-file-local) "Create local test files" 3)
      +           commands)
      +          (push
      +           (list (format "rclone mkdir \"%s\"" remote-path)
      +                 "Create remote directories" 3)
      +           commands)
      +          (push
      +           (list (format "rclone touch \"%s\"" test-file-remote) "Create remote test-file" 4)
      +           commands)
      +          (push
      +           (list
      +            (concat (my/index--rclone-make-command local-path remote-path remote)
      +                    " --resync")
      +            (format "Initial sync for %s" remote) 8)
      +           commands))
      +        (push folder
      +              (alist-get remote sync-items-per-remote nil nil #'equal))))
      +    (unless (file-exists-p my/index--rclone-script-path)
      +      (push (list (format "mkdir -p \"%s\"" (expand-file-name
      +                                             my/index--rclone-script-path))
      +                  "Create rclone sync scripts directory" 9)
      +            commands))
      +    (cl-loop for (remote . folders) in sync-items-per-remote
      +             unless (my/index--rclone-script-saved-p remote folders)
      +             do (push
      +                 (list
      +                  (format "cat <<EOF > %s\n%s\nEOF"
      +                          (my/index--rclone-script-loc remote)
      +                          (my/index--rclone-script remote (nreverse folders)))
      +                  "Update rclone sync script" 10)
      +                 commands))
      +    (nreverse commands)))
       
      Git repos

      To sync git, we just need to clone the required git repos. Removing the repos is handled by the folder sync commands.

      (defun my/index--git-commands (tree)
      @@ -11226,13 +11534,14 @@ Didn’t work out as I expected, so I’ve made org-journal-tags  (let* ((full-tree (my/index--tree-retrive)))
           (my/index--tree-verify full-tree)
           (let* ((tree (my/index--tree-narrow full-tree))
      -           (mega-commands (my/index--mega-commands full-tree tree))
      +           ;; (mega-commands (my/index--mega-commands full-tree tree))
      +           (rclone-commands (my/index--rclone-commands tree))
                  (mapping (my/index--filesystem-tree-mapping full-tree tree))
                  (folder-commands (my/index--filesystem-commands mapping))
                  (git-commands (my/index--git-commands tree))
                  (waka-commands (my/index--wakatime-commands tree))
                  (symlink-commands (my/index-get-symlink-commands tree)))
      -      (my/index--commands-display (append mega-commands folder-commands git-commands
      +      (my/index--commands-display (append rclone-commands folder-commands git-commands
                                                 waka-commands symlink-commands)))))
       

      The last piece is the navigation interface.

      diff --git a/configs/index.xml b/configs/index.xml index c5f7d46..20cc17a 100644 --- a/configs/index.xml +++ b/configs/index.xml @@ -12,7 +12,7 @@ https://sqrtminusone.xyz/configs/console/ Mon, 01 Jan 0001 00:00:00 +0000 https://sqrtminusone.xyz/configs/console/ - <blockquote> <p>No matter from which side you approach penguins, more always come from behind</p></blockquote> <ul> <li>A friend of mine</li> </ul> <h2 id="colors">Colors</h2> <p>Noweb function to get colors.</p> <p><a id="code-snippet--get-color"></a></p> <div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#008000">let</span> ((<span style="color:#19177c">color</span> (<span style="color:#008000">or</span> (<span style="color:#19177c">my/color-value</span> <span style="color:#19177c">name</span>)))) </span></span><span style="display:flex;"><span> (<span style="color:#008000">if</span> (<span style="color:#00f">&gt;</span> <span style="color:#008000">quote</span> <span style="color:#666">0</span>) </span></span><span style="display:flex;"><span> (<span style="color:#00f">concat</span> <span style="color:#ba2121">&#34;\&#34;&#34;</span> <span style="color:#19177c">color</span> <span style="color:#ba2121">&#34;\&#34;&#34;</span>) </span></span><span style="display:flex;"><span> <span style="color:#19177c">color</span>)) </span></span></code></pre></div><p><a id="code-snippet--get-fg-for-color"></a></p> <div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#008000">let</span> ((<span style="color:#19177c">val</span> (<span style="color:#008000">if</span> (<span style="color:#19177c">ct-light-p</span> (<span style="color:#19177c">my/color-value</span> <span style="color:#19177c">name</span>)) </span></span><span style="display:flex;"><span> (<span style="color:#19177c">my/color-value</span> <span style="color:#19177c">&#39;black</span>) </span></span><span style="display:flex;"><span> (<span style="color:#19177c">my/color-value</span> <span style="color:#19177c">&#39;white</span>)))) </span></span><span style="display:flex;"><span> (<span style="color:#008000">if</span> (<span style="color:#00f">eq</span> <span style="color:#008000">quote</span> <span style="color:#666">1</span>) </span></span><span style="display:flex;"><span> (<span style="color:#00f">concat</span> <span style="color:#ba2121">&#34;\&#34;&#34;</span> <span style="color:#19177c">val</span> <span style="color:#ba2121">&#34;\&#34;&#34;</span>) </span></span><span style="display:flex;"><span> <span style="color:#19177c">val</span>)) </span></span></code></pre></div><div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#008000">setq-local</span> <span style="color:#19177c">org-confirm-babel-evaluate</span> <span style="color:#800">nil</span>) </span></span></code></pre></div><h2 id="dot-profile"><code>.profile</code></h2> <h3 id="environment">Environment</h3> <div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#008000">export</span> <span style="color:#19177c">QT_QPA_PLATFORMTHEME</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;qt5ct&#34;</span> </span></span><span style="display:flex;"><span><span style="color:#008000">export</span> <span style="color:#19177c">QT_AUTO_SCREEN_SCALE_FACTOR</span><span style="color:#666">=</span><span style="color:#666">0</span> </span></span></code></pre></div><p>Set ripgrep config path</p> <div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#008000">export</span> <span style="color:#19177c">RIPGREP_CONFIG_PATH</span><span style="color:#666">=</span><span style="color:#19177c">$HOME</span>/.config/ripgrep/ripgreprc </span></span></code></pre></div><p>hledger path</p> <div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#008000">export</span> <span style="color:#19177c">LEDGER_FILE</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;</span><span style="color:#19177c">$HOME</span><span style="color:#ba2121">/30-39 Life/32 org-mode/ledger/ledger.journal&#34;</span> </span></span></code></pre></div><p>Checking if running inside termux</p> + <blockquote> <p>No matter from which side you approach penguins, more always come from behind</p> </blockquote> <ul> <li>A friend of mine</li> </ul> <h2 id="colors">Colors</h2> <p>Noweb function to get colors.</p> <p><a id="code-snippet--get-color"></a></p> <div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#008000">let</span> ((<span style="color:#19177c">color</span> (<span style="color:#008000">or</span> (<span style="color:#19177c">my/color-value</span> <span style="color:#19177c">name</span>)))) </span></span><span style="display:flex;"><span> (<span style="color:#008000">if</span> (<span style="color:#00f">&gt;</span> <span style="color:#008000">quote</span> <span style="color:#666">0</span>) </span></span><span style="display:flex;"><span> (<span style="color:#00f">concat</span> <span style="color:#ba2121">&#34;\&#34;&#34;</span> <span style="color:#19177c">color</span> <span style="color:#ba2121">&#34;\&#34;&#34;</span>) </span></span><span style="display:flex;"><span> <span style="color:#19177c">color</span>)) </span></span></code></pre></div><p><a id="code-snippet--get-fg-for-color"></a></p> <div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#008000">let</span> ((<span style="color:#19177c">val</span> (<span style="color:#008000">if</span> (<span style="color:#19177c">ct-light-p</span> (<span style="color:#19177c">my/color-value</span> <span style="color:#19177c">name</span>)) </span></span><span style="display:flex;"><span> (<span style="color:#19177c">my/color-value</span> <span style="color:#19177c">&#39;black</span>) </span></span><span style="display:flex;"><span> (<span style="color:#19177c">my/color-value</span> <span style="color:#19177c">&#39;white</span>)))) </span></span><span style="display:flex;"><span> (<span style="color:#008000">if</span> (<span style="color:#00f">eq</span> <span style="color:#008000">quote</span> <span style="color:#666">1</span>) </span></span><span style="display:flex;"><span> (<span style="color:#00f">concat</span> <span style="color:#ba2121">&#34;\&#34;&#34;</span> <span style="color:#19177c">val</span> <span style="color:#ba2121">&#34;\&#34;&#34;</span>) </span></span><span style="display:flex;"><span> <span style="color:#19177c">val</span>)) </span></span></code></pre></div><div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#008000">setq-local</span> <span style="color:#19177c">org-confirm-babel-evaluate</span> <span style="color:#800">nil</span>) </span></span></code></pre></div><h2 id="dot-profile"><code>.profile</code></h2> <h3 id="environment">Environment</h3> <div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#008000">export</span> <span style="color:#19177c">QT_QPA_PLATFORMTHEME</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;qt5ct&#34;</span> </span></span><span style="display:flex;"><span><span style="color:#008000">export</span> <span style="color:#19177c">QT_AUTO_SCREEN_SCALE_FACTOR</span><span style="color:#666">=</span><span style="color:#666">0</span> </span></span></code></pre></div><p>Set ripgrep config path</p> <div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#008000">export</span> <span style="color:#19177c">RIPGREP_CONFIG_PATH</span><span style="color:#666">=</span><span style="color:#19177c">$HOME</span>/.config/ripgrep/ripgreprc </span></span></code></pre></div><p>hledger path</p> <div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#008000">export</span> <span style="color:#19177c">LEDGER_FILE</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;</span><span style="color:#19177c">$HOME</span><span style="color:#ba2121">/30-39 Life/32 org-mode/ledger/ledger.journal&#34;</span> </span></span></code></pre></div><p>Checking if running inside termux</p> Desktop @@ -26,7 +26,7 @@ https://sqrtminusone.xyz/configs/emacs/ Mon, 01 Jan 0001 00:00:00 +0000 https://sqrtminusone.xyz/configs/emacs/ - <blockquote> <p>One day we won&rsquo;t hate one another, no young boy will march to war and I will clean up my Emacs config. But that day isn&rsquo;t today.</p></blockquote> <ul> <li>Me, <span class="timestamp-wrapper"><span class="timestamp">&lt;2021-05-27 Thu 17:35&gt; </span></span> in commit 93a0573. Adapted from <a href="https://www.youtube.com/watch?v=pIdBinlW40E">The Dark Element - &ldquo;The Pallbearer Walks Alone&rdquo;</a>. T_T</li> </ul> <h2 id="introduction">Introduction</h2> <p>My configuration of <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a>, an awesome <del>text editor</del> piece of software that can do almost anything.</p> <p>At the moment of writing this, that &ldquo;almost anything&rdquo; includes:</p> + <blockquote> <p>One day we won&rsquo;t hate one another, no young boy will march to war and I will clean up my Emacs config. But that day isn&rsquo;t today.</p> </blockquote> <ul> <li>Me, <span class="timestamp-wrapper"><span class="timestamp">&lt;2021-05-27 Thu 17:35&gt; </span></span> in commit 93a0573. Adapted from <a href="https://www.youtube.com/watch?v=pIdBinlW40E">The Dark Element - &ldquo;The Pallbearer Walks Alone&rdquo;</a>. T_T</li> </ul> <h2 id="introduction">Introduction</h2> <p>My configuration of <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a>, an awesome <del>text editor</del> piece of software that can do almost anything.</p> <p>At the moment of writing this, that &ldquo;almost anything&rdquo; includes:</p> Guix diff --git a/configs/mail/index.html b/configs/mail/index.html index 7c0c63b..5a92f82 100644 --- a/configs/mail/index.html +++ b/configs/mail/index.html @@ -180,7 +180,7 @@
      remoteuser = <<mail-username()>> remotepass = <<mail-password()>> remoteport = 993 -cert_fingerprint = 416b1f7f18d68a65f5e75bb1af5d65ea5e20739e +cert_fingerprint = 20bbfdcb617e4695c47a90af96e40d72a57adee4

    Notmuch

    @@ -460,7 +460,7 @@ Remove TAG from emails which are outside the matching PATHport 465 tls on tls_starttls off -tls_fingerprint 69:E9:61:A0:DE:8B:AD:F2:C0:90:2F:55:F9:D6:80:7F:0B:AB:7E:1B:FD:56:C0:EE:35:ED:E2:EB:DD:80:AD:C3 +tls_fingerprint AD:1D:38:93:43:18:F2:DF:0C:62:80:81:55:74:B0:FB:A7:2B:FF:BD:FC:60:05:02:89:AB:F3:C2:33:57:E1:96 from pvkorytov@etu.ru user pvkorytov passwordeval "pass show Job/Digital/Email/pvkorytov@etu.ru | head -n 1" diff --git a/index.html b/index.html index 21bf135..eaac2f6 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,6 @@ - + diff --git a/index.xml b/index.xml index 972d2f5..cf1c5a8 100644 --- a/index.xml +++ b/index.xml @@ -1331,7 +1331,8 @@ Customize the formatting of these records through <code>org-clock-agg-elem } </style> <blockquote> -<p>Poof I made my free-time disappear</p></blockquote> +<p>Poof I made my free-time disappear</p> +</blockquote> <p class="quote-title">- <a href="https://elken.dev">Ellis Kenyő</a>, on being called an "elisp mage" <p>Little did I know on the fateful day of <strong><span class="timestamp-wrapper"><span class="timestamp">[2020-10-09 Fri]</span></span></strong>, when I had installed <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a>. I wasn&rsquo;t thinking about the <a href="https://www.gnu.org/philosophy/philosophy.html">ethical aspects</a> of free software, the <a href="https://www.webofstories.com/play/marvin.minsky/44">aesthetics of Lisp</a>, or these other things with which an occasional layperson might explain how an almost <a href="https://www.jwz.org/doc/emacs-timeline.html">half a century old</a> program can still be in <a href="https://emacsconf.org/2022/talks/survey/">active use</a>.</p> <p>In fact, when considering using software X for anything, the most important question to me was: can X provide a better user experience? For Emacs, the answer to most of these questions turned out to be yes.</p> diff --git a/posts/2023-04-13-emacs/index.html b/posts/2023-04-13-emacs/index.html index 979dd14..f4fd16f 100644 --- a/posts/2023-04-13-emacs/index.html +++ b/posts/2023-04-13-emacs/index.html @@ -84,7 +84,8 @@ }
    -

    Poof I made my free-time disappear

    +

    Poof I made my free-time disappear

    +

    - Ellis Kenyő, on being called an "elisp mage"

    Little did I know on the fateful day of [2020-10-09 Fri], when I had installed GNU Emacs. I wasn’t thinking about the ethical aspects of free software, the aesthetics of Lisp, or these other things with which an occasional layperson might explain how an almost half a century old program can still be in active use.

    In fact, when considering using software X for anything, the most important question to me was: can X provide a better user experience? For Emacs, the answer to most of these questions turned out to be yes.

    diff --git a/posts/index.xml b/posts/index.xml index 990cf18..74c7abe 100644 --- a/posts/index.xml +++ b/posts/index.xml @@ -838,7 +838,8 @@ } </style> <blockquote> -<p>Poof I made my free-time disappear</p></blockquote> +<p>Poof I made my free-time disappear</p> +</blockquote> <p class="quote-title">- <a href="https://elken.dev">Ellis Kenyő</a>, on being called an "elisp mage" <p>Little did I know on the fateful day of <strong><span class="timestamp-wrapper"><span class="timestamp">[2020-10-09 Fri]</span></span></strong>, when I had installed <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a>. I wasn&rsquo;t thinking about the <a href="https://www.gnu.org/philosophy/philosophy.html">ethical aspects</a> of free software, the <a href="https://www.webofstories.com/play/marvin.minsky/44">aesthetics of Lisp</a>, or these other things with which an occasional layperson might explain how an almost <a href="https://www.jwz.org/doc/emacs-timeline.html">half a century old</a> program can still be in <a href="https://emacsconf.org/2022/talks/survey/">active use</a>.</p> <p>In fact, when considering using software X for anything, the most important question to me was: can X provide a better user experience? For Emacs, the answer to most of these questions turned out to be yes.</p> diff --git a/sass/researcher.min.css b/sass/researcher.min.css index 5f7cd41..b5e3123 100644 --- a/sass/researcher.min.css +++ b/sass/researcher.min.css @@ -1 +1 @@ -@font-face{font-family:inconsolata lgc;font-style:normal;font-weight:400;src:local(""),url(fonts/inconsolatalgc-scaled-down.woff2)format("woff2")}#content a,.nav-link{color:#dc3545;text-decoration:none}#content a *,.nav-link *{color:#dc3545}#content a:hover,.nav-link:hover{color:#dc3545;text-decoration:underline}#footer a,.navbar-brand{color:#222;text-decoration:none}#footer a *,.navbar-brand *{color:#222}#footer a:hover,.navbar-brand:hover{color:#222;text-decoration:underline}#content table td,#content table th{border:1px solid #ccc;padding:6px 12px;text-align:left}*{color:#222;font-family:inconsolata,inconsolata lgc;line-height:1.2}.text-ru{font-family:inconsolata lgc,inconsolata}.root{display:flex;flex-direction:column}.table-of-contents{order:0}.table-of-contents ul{padding-left:1rem !important}.table-of-contents ul>li{margin-left:.3em !important}.table-of-contents a.active{font-weight:700}.table-of-contents a:hover{cursor:pointer}@media(max-width:578px){.table-of-contents{align-self:center}}.container{max-width:750px;order:1}#title-large-screen{display:none}#title-small-screen{margin-left:15px !important}@media(max-width:578px){#title-small-screen{align-self:center}}@media(max-width:1125px){.root{margin-right:auto;margin-left:auto;width:100%;max-width:750px}.table-of-contents{padding-left:15px;padding-right:15px}}@media(min-width:1275px){.root{margin-left:calc((100vw - 750px)/2)}#actual-content{margin:0}}@media(min-width:1125px){.root{flex-direction:row}.table-of-contents{width:350px;order:2;position:sticky;top:0;padding:1em;align-self:start;scrollbar-width:thin}.table-of-contents .table-of-contents-text{overflow-x:hidden;overflow-y:auto;max-height:calc(100vh - 155px)}.table-of-contents .hidden{display:none}#title-small-screen{display:none}#title-large-screen{display:block}}.navbar-brand{font-size:2rem}#content p{margin-bottom:.6rem}#content h1,#content h2,#content h3,#content h4,#content h5,#content h6{font-size:medium;font-weight:700;margin:1rem 0 .6rem}#content h1{font-size:1.8rem}#content h2{font-size:1.6rem}#content h3{font-size:1.4rem}#content h4{font-size:1.2rem}#content img{display:block;margin:1rem auto;max-width:100%}#content a>img{margin:1rem 4px 1rem 0 !important}#content .avatar>img{border-radius:50%;float:right;margin:-8px 0 0 16px;height:90px;width:90px}#content .webbuttons{display:flex;flex-direction:row;gap:5px}#content .webbuttons>figure{margin:0}#content ol{counter-reset:list;list-style:none;padding-left:2rem}#content ol>li{display:table-row}#content ol>li:before{content:"[" counter(list,decimal)"] ";counter-increment:list;display:table-cell;text-align:right;padding-right:.5em}#content .container>ol,#content .footnotes>ol{padding-left:0}#content ul{list-style:inside;padding-left:2rem}#content ul>li{list-style-position:outside;margin-left:1em}#content .container>ul,#content .footnotes>ul{padding-left:0}#content table{margin:1rem auto;width:100%}#content table th{font-weight:700}#content table tr:nth-child(2n){background-color:#f8f8f8}#content .table-no-header th{font-weight:400}#content .table-no-header table{margin:0 0 .5rem}#content blockquote{border-left:4px solid;font-style:italic;margin:1rem 0;padding:8px}#content code{color:#222;background-color:#f8f8f8;border:1px solid #ccc;border-radius:10%;padding:0 4px;font-family:monospace !important}#content code span{font-family:monospace}#content pre code{all:unset;font-size:95%}#content .highlight{margin:1rem auto;border:1px solid #ccc}#content .highlight>pre{padding:8px;margin-bottom:0}#content .abstract{margin-top:12px;margin-bottom:12px;padding-left:72px;padding-right:72px}#content .abstract p:first-of-type::before{content:"Abstract: ";font-weight:700}#content span.underline{text-decoration:underline} \ No newline at end of file +@font-face{font-family:inconsolata lgc;font-style:normal;font-weight:400;src:local(""),url(fonts/inconsolatalgc-scaled-down.woff2)format("woff2")}#content a,.nav-link{color:#dc3545;text-decoration:none}#content a *,.nav-link *{color:#dc3545}#content a:hover,.nav-link:hover{color:#dc3545;text-decoration:underline}#footer a,.navbar-brand{color:#222;text-decoration:none}#footer a *,.navbar-brand *{color:#222}#footer a:hover,.navbar-brand:hover{color:#222;text-decoration:underline}#content table td,#content table th{border:1px solid #ccc;padding:6px 12px;text-align:left}*{color:#222;font-family:inconsolata,inconsolata lgc;line-height:1.2}.text-ru{font-family:inconsolata lgc,inconsolata}.root{display:flex;flex-direction:column}.table-of-contents{order:0}.table-of-contents ul{padding-left:1rem!important}.table-of-contents ul>li{margin-left:.3em!important}.table-of-contents a.active{font-weight:700}.table-of-contents a:hover{cursor:pointer}@media(max-width:578px){.table-of-contents{align-self:center}}.container{max-width:750px;order:1}#title-large-screen{display:none}#title-small-screen{margin-left:15px!important}@media(max-width:578px){#title-small-screen{align-self:center}}@media(max-width:1125px){.root{margin-right:auto;margin-left:auto;width:100%;max-width:750px}.table-of-contents{padding-left:15px;padding-right:15px}}@media(min-width:1275px){.root{margin-left:calc((100vw - 750px)/2)}#actual-content{margin:0}}@media(min-width:1125px){.root{flex-direction:row}.table-of-contents{width:350px;order:2;position:sticky;top:0;padding:1em;align-self:start;scrollbar-width:thin}.table-of-contents .table-of-contents-text{overflow-x:hidden;overflow-y:auto;max-height:calc(100vh - 155px)}.table-of-contents .hidden{display:none}#title-small-screen{display:none}#title-large-screen{display:block}}.navbar-brand{font-size:2rem}#content p{margin-bottom:.6rem}#content h1,#content h2,#content h3,#content h4,#content h5,#content h6{font-size:medium;font-weight:700;margin:1rem 0 .6rem}#content h1{font-size:1.8rem}#content h2{font-size:1.6rem}#content h3{font-size:1.4rem}#content h4{font-size:1.2rem}#content img{display:block;margin:1rem auto;max-width:100%}#content a>img{margin:1rem 4px 1rem 0!important}#content .avatar>img{border-radius:50%;float:right;margin:-8px 0 0 16px;height:90px;width:90px}#content .webbuttons{display:flex;flex-direction:row;gap:5px}#content .webbuttons>figure{margin:0}#content ol{counter-reset:list;list-style:none;padding-left:2rem}#content ol>li{display:table-row}#content ol>li:before{content:"[" counter(list,decimal)"] ";counter-increment:list;display:table-cell;text-align:right;padding-right:.5em}#content .container>ol,#content .footnotes>ol{padding-left:0}#content ul{list-style:inside;padding-left:2rem}#content ul>li{list-style-position:outside;margin-left:1em}#content .container>ul,#content .footnotes>ul{padding-left:0}#content table{margin:1rem auto;width:100%}#content table th{font-weight:700}#content table tr:nth-child(2n){background-color:#f8f8f8}#content .table-no-header th{font-weight:400}#content .table-no-header table{margin:0 0 .5rem}#content blockquote{border-left:4px solid;font-style:italic;margin:1rem 0;padding:8px}#content code{color:#222;background-color:#f8f8f8;border:1px solid #ccc;border-radius:10%;padding:0 4px;font-family:monospace!important}#content code span{font-family:monospace}#content pre code{all:unset;font-size:95%}#content .highlight{margin:1rem auto;border:1px solid #ccc}#content .highlight>pre{padding:8px;margin-bottom:0}#content .abstract{margin-top:12px;margin-bottom:12px;padding-left:72px;padding-right:72px}#content .abstract p:first-of-type::before{content:"Abstract: ";font-weight:700}#content span.underline{text-decoration:underline} \ No newline at end of file diff --git a/stats/all.png b/stats/all.png index a106326..2e9ed75 100644 Binary files a/stats/all.png and b/stats/all.png differ diff --git a/stats/emacs-vim.png b/stats/emacs-vim.png index ea7fc98..499ae8d 100644 Binary files a/stats/emacs-vim.png and b/stats/emacs-vim.png differ diff --git a/stats/literate-config.png b/stats/literate-config.png index f525312..a8fd725 100644 Binary files a/stats/literate-config.png and b/stats/literate-config.png differ diff --git a/tags/emacs/index.xml b/tags/emacs/index.xml index 5cf09c0..0f21130 100644 --- a/tags/emacs/index.xml +++ b/tags/emacs/index.xml @@ -20,7 +20,7 @@ https://sqrtminusone.xyz/posts/2023-04-13-emacs/ Thu, 13 Apr 2023 00:00:00 +0000 https://sqrtminusone.xyz/posts/2023-04-13-emacs/ - <style> .quote-title { margin-left: 24px; } </style> <blockquote> <p>Poof I made my free-time disappear</p></blockquote> <p class="quote-title">- <a href="https://elken.dev">Ellis Kenyő</a>, on being called an "elisp mage" <p>Little did I know on the fateful day of <strong><span class="timestamp-wrapper"><span class="timestamp">[2020-10-09 Fri]</span></span></strong>, when I had installed <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a>. I wasn&rsquo;t thinking about the <a href="https://www.gnu.org/philosophy/philosophy.html">ethical aspects</a> of free software, the <a href="https://www.webofstories.com/play/marvin.minsky/44">aesthetics of Lisp</a>, or these other things with which an occasional layperson might explain how an almost <a href="https://www.jwz.org/doc/emacs-timeline.html">half a century old</a> program can still be in <a href="https://emacsconf.org/2022/talks/survey/">active use</a>.</p> + <style> .quote-title { margin-left: 24px; } </style> <blockquote> <p>Poof I made my free-time disappear</p> </blockquote> <p class="quote-title">- <a href="https://elken.dev">Ellis Kenyő</a>, on being called an "elisp mage" <p>Little did I know on the fateful day of <strong><span class="timestamp-wrapper"><span class="timestamp">[2020-10-09 Fri]</span></span></strong>, when I had installed <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a>. I wasn&rsquo;t thinking about the <a href="https://www.gnu.org/philosophy/philosophy.html">ethical aspects</a> of free software, the <a href="https://www.webofstories.com/play/marvin.minsky/44">aesthetics of Lisp</a>, or these other things with which an occasional layperson might explain how an almost <a href="https://www.jwz.org/doc/emacs-timeline.html">half a century old</a> program can still be in <a href="https://emacsconf.org/2022/talks/survey/">active use</a>.</p> <p>In fact, when considering using software X for anything, the most important question to me was: can X provide a better user experience? For Emacs, the answer to most of these questions turned out to be yes.</p> Running Gource with Emacs