;;; scpaste.el --- Paste to the web via scp.

;; Copyright © 2008-2023 Phil Hagelberg and contributors

;; Author: Phil Hagelberg
;; URL: https://git.sr.ht/~technomancy/scpaste
;; Version: 0.7.0
;; Created: 2008-04-02
;; Keywords: convenience hypermedia
;; EmacsWiki: SCPaste
;; Package-Requires: ((htmlize "1.39"))

;; This file is NOT part of GNU Emacs.

;;; Pasted Files

;; * <https://paste.guixotic.coop/7b79cjib42fx85pdx0ihpc2rsk0srr-ffmpeg-6.1.2.drv.html>
;; * <https://paste.guixotic.coop/829rda40m1p11vsv2ixrqspk54nz7y-luanti-whitelist-1.2.7.drv.html>
;; * <https://paste.guixotic.coop/build-demos-gtk-demo.diff.html>
;; * <https://paste.guixotic.coop/conditional.node.diff.html>
;; * <https://paste.guixotic.coop/config.log_guix-build-gtick-0.5.5-17530-19051.drv-0_.html>
;; * <https://paste.guixotic.coop/config.log-powerpc64le-16263-16282.html>
;; * <https://paste.guixotic.coop/configure-19374-20691.ac.html>
;; * <https://paste.guixotic.coop/_CPU-Profiler-Report_2025-10-17_10_53_02_.html>
;; * <https://paste.guixotic.coop/_CPU-Profiler-Report_2025-10-17_11_04_27_.html>
;; * <https://paste.guixotic.coop/dap73kpyfvajhnn9fdis2mbla8fdfw-gtk-4.20.3.drv.html>
;; * <https://paste.guixotic.coop/debian-ipv6-hetzner.html>
;; * <https://paste.guixotic.coop/_Diff_.html>
;; * <https://paste.guixotic.coop/drongo.scm.html>
;; * <https://paste.guixotic.coop/dwz.log.html>
;; * <https://paste.guixotic.coop/emerge-1-903.scm.html>
;; * <https://paste.guixotic.coop/exec_linux-1530-1724.go.html>
;; * <https://paste.guixotic.coop/flyd27zdsmy40a0jmpl2z4yg4n82mm-python-matplotlib-3.10.8-941716-942649.drv.html>
;; * <https://paste.guixotic.coop/forgejo-9961-10309.scm_tests_.html>
;; * <https://paste.guixotic.coop/fsf40.org.html>
;; * <https://paste.guixotic.coop/games-2316-3577.scm_tests_.html>
;; * <https://paste.guixotic.coop/gdb-pie.html>
;; * <https://paste.guixotic.coop/_Geiser_Guile_REPL_3_-1115-1682.html>
;; * <https://paste.guixotic.coop/_Geiser_Guile_REPL_guix_-600691-600841.html>
;; * <https://paste.guixotic.coop/_Geiser_Guile_REPL_guix-master_-6392-6537.html>
;; * <https://paste.guixotic.coop/_Geiser_Guile_REPL_guix-master_-77669-78096.html>
;; * <https://paste.guixotic.coop/_Geiser_Guile_REPL_guix-spare_-4354-5141.html>
;; * <https://paste.guixotic.coop/_Geiser_Guile_REPL_guix-spare_-67368-68205.html>
;; * <https://paste.guixotic.coop/_Geiser_Guile_REPL_guix-spare_-760042-763816.html>
;; * <https://paste.guixotic.coop/_Geiser_Guile_REPL_guix-spare_-8352-8775.html>
;; * <https://paste.guixotic.coop/_Geiser_Guile_REPL_guix-spare_-929908-930152.html>
;; * <https://paste.guixotic.coop/gjs-meson-test-testlog.txt.html>
;; * <https://paste.guixotic.coop/gnome-251134-253807.scm.html>
;; * <https://paste.guixotic.coop/gnome-session-test-failure-machine-id.txt.html>
;; * <https://paste.guixotic.coop/gnu-build-system-26624-27412.scm_guix-master_.html>
;; * <https://paste.guixotic.coop/gnu-ftp-workaround-for-guix-install.sh.html>
;; * <https://paste.guixotic.coop/gnu-packages.scm.html>
;; * <https://paste.guixotic.coop/gnus-msg.el-49750-50888.gz.html>
;; * <https://paste.guixotic.coop/gnu-store.mount.html>
;; * <https://paste.guixotic.coop/gradle.scm_guix_.html>
;; * <https://paste.guixotic.coop/gradle.scm_tests_.html>
;; * <https://paste.guixotic.coop/gremlin.scm_guix_tests_-5556-5977.html>
;; * <https://paste.guixotic.coop/gtk.diffoscope.html>
;; * <https://paste.guixotic.coop/gtk-v2.diffoscope.html>
;; * <https://paste.guixotic.coop/guix-daemon-fails-starting.html>
;; * <https://paste.guixotic.coop/guix-daemon.service.html>
;; * <https://paste.guixotic.coop/guix-install.sh_etc_.html>
;; * <https://paste.guixotic.coop/guix-install.sh-fails-on-hetzner-rescue.html>
;; * <https://paste.guixotic.coop/guix-install.sh.html>
;; * <https://paste.guixotic.coop/h4zhxqic804sy99j46vhyg4y9iiy4c-gcc-cross-boot0-14.3.0-11688063-11692190.drv.html>
;; * <https://paste.guixotic.coop/hetzner-30639-32167.scm_gnu_.html>
;; * <https://paste.guixotic.coop/hetzner-30893-31578.scm.html>
;; * <https://paste.guixotic.coop/hetzner-31551-32139.scm.html>
;; * <https://paste.guixotic.coop/hetzner-31606-31926.scm_gnu_.html>
;; * <https://paste.guixotic.coop/hetzner-images.html>
;; * <https://paste.guixotic.coop/icecat-nok-34622-35161.strace.html>
;; * <https://paste.guixotic.coop/index.html>
;; * <https://paste.guixotic.coop/io.scm_guix_.html>
;; * <https://paste.guixotic.coop/java-65630-65823.scm_guix-master_.html>
;; * <https://paste.guixotic.coop/java-65630-65824.scm_guix-master_.html>
;; * <https://paste.guixotic.coop/ld-wrapper.scm.html>
;; * <https://paste.guixotic.coop/Libera-10652-10925.Chat.html>
;; * <https://paste.guixotic.coop/Libera-1389-1642.Chat.html>
;; * <https://paste.guixotic.coop/Libera-24559-24963.Chat.html>
;; * <https://paste.guixotic.coop/Libera-25672-29269.Chat.html>
;; * <https://paste.guixotic.coop/Libera-30261-30402.Chat.html>
;; * <https://paste.guixotic.coop/libinput-minimal-child.strace.html>
;; * <https://paste.guixotic.coop/lmvr9pplb98q6pmiwhlr9axjl86hpa-gnome-shell-49.4.drv.html>
;; * <https://paste.guixotic.coop/luanti-paths.patch.html>
;; * <https://paste.guixotic.coop/magit-diff_guix.html>
;; * <https://paste.guixotic.coop/magit-diff_guix-spare.html>
;; * <https://paste.guixotic.coop/magit-diff_nar-herder-1-1761.html>
;; * <https://paste.guixotic.coop/magit_guix-383-1339.html>
;; * <https://paste.guixotic.coop/magit_guix-398-1436.html>
;; * <https://paste.guixotic.coop/magit_guix-7993-10829.html>
;; * <https://paste.guixotic.coop/magit_guix-master-727-1383.html>
;; * <https://paste.guixotic.coop/magit-revision_guix-spare-383-2088.html>
;; * <https://paste.guixotic.coop/magit-revision_guix-spare-455-1252.html>
;; * <https://paste.guixotic.coop/magit-revision_guix-spare-653-1367.html>
;; * <https://paste.guixotic.coop/main-288-698.scm.html>
;; * <https://paste.guixotic.coop/Makefile.html>
;; * <https://paste.guixotic.coop/_Man_5_githooks_-559-904.html>
;; * <https://paste.guixotic.coop/_Memory-Profiler-Report_2025-10-17_10_46_12_.html>
;; * <https://paste.guixotic.coop/mmap-munmap-ETXTBSY.html>
;; * <https://paste.guixotic.coop/nar-herder-21067-21710.in.html>
;; * <https://paste.guixotic.coop/new-safe-clone.html>
;; * <https://paste.guixotic.coop/nhyynyr4myhq7slmhiszdhhyz2gl5p-grub-ieee1275-2.12.drv.html>
;; * <https://paste.guixotic.coop/nok.txt.html>
;; * <https://paste.guixotic.coop/non-monadic-code-in-mbegin.html>
;; * <https://paste.guixotic.coop/_Occur_-1-9548.html>
;; * <https://paste.guixotic.coop/_Occur_.html>
;; * <https://paste.guixotic.coop/org-babel-scheme-test-columns-are-0-based.html>
;; * <https://paste.guixotic.coop/ovh-4797-5457.scm.html>
;; * <https://paste.guixotic.coop/pre-push_hooks_-1283-1414.html>
;; * <https://paste.guixotic.coop/python-xyz-438822-439142.scm_guix-spare_.html>
;; * <https://paste.guixotic.coop/qt-72165-73941.scm.html>
;; * <https://paste.guixotic.coop/raw-2819-2963.eml.html>
;; * <https://paste.guixotic.coop/run-gdb.html>
;; * <https://paste.guixotic.coop/s3-2351-3397.scm_storage_.html>
;; * <https://paste.guixotic.coop/_scratch_-10884-12437.html>
;; * <https://paste.guixotic.coop/_scratch_-147-1043.html>
;; * <https://paste.guixotic.coop/_scratch_-148-1256.html>
;; * <https://paste.guixotic.coop/_scratch_-148-3069.html>
;; * <https://paste.guixotic.coop/_scratch_-148-3124.html>
;; * <https://paste.guixotic.coop/_scratch_-148-3247.html>
;; * <https://paste.guixotic.coop/_scratch_-148-381.html>
;; * <https://paste.guixotic.coop/_scratch_-190-5468.html>
;; * <https://paste.guixotic.coop/_scratch_-208-620.html>
;; * <https://paste.guixotic.coop/_scratch_-211-559.html>
;; * <https://paste.guixotic.coop/_scratch_-31393-32250.html>
;; * <https://paste.guixotic.coop/_scratch_-3195-3344.html>
;; * <https://paste.guixotic.coop/_scratch_-4152-4503.html>
;; * <https://paste.guixotic.coop/_scratch_-4596-5080.html>
;; * <https://paste.guixotic.coop/_scratch_-5083-5838.html>
;; * <https://paste.guixotic.coop/_scratch_-5470-6449.html>
;; * <https://paste.guixotic.coop/_scratch_-5840-7134.html>
;; * <https://paste.guixotic.coop/_scratch_-645-2137.html>
;; * <https://paste.guixotic.coop/_scratch_-7082-8166.html>
;; * <https://paste.guixotic.coop/_scratch_-7744-8177.html>
;; * <https://paste.guixotic.coop/_scratch_-8168-9074.html>
;; * <https://paste.guixotic.coop/_scratch_-9119-10027.html>
;; * <https://paste.guixotic.coop/_shell_-12142-14025.html>
;; * <https://paste.guixotic.coop/_shell_-12522311-12528577.html>
;; * <https://paste.guixotic.coop/_shell_-13804-14164.html>
;; * <https://paste.guixotic.coop/_shell_-16386888-16387126.html>
;; * <https://paste.guixotic.coop/Shell-16.gir.html>
;; * <https://paste.guixotic.coop/_shell_-173-18025.html>
;; * <https://paste.guixotic.coop/Shell-17.gir.html>
;; * <https://paste.guixotic.coop/_shell_-19419407-19421067.html>
;; * <https://paste.guixotic.coop/_shell_-2078036-2078956.html>
;; * <https://paste.guixotic.coop/_shell_2_-1418457-1418951.html>
;; * <https://paste.guixotic.coop/_shell_2_-192385-195306.html>
;; * <https://paste.guixotic.coop/_shell_-219483-221474.html>
;; * <https://paste.guixotic.coop/_shell_-2356596-2361014.html>
;; * <https://paste.guixotic.coop/_shell_-249536-252533.html>
;; * <https://paste.guixotic.coop/_shell_2_-4995695-4998429.html>
;; * <https://paste.guixotic.coop/_shell_-2594880-2626110.html>
;; * <https://paste.guixotic.coop/_shell_2_-616026-616865.html>
;; * <https://paste.guixotic.coop/_shell_-2632952-2664182.html>
;; * <https://paste.guixotic.coop/_shell_2_-740235-741836.html>
;; * <https://paste.guixotic.coop/_shell_2_-7660-8241.html>
;; * <https://paste.guixotic.coop/_shell_-2846680-2865842.html>
;; * <https://paste.guixotic.coop/_shell_-2914283-2914501.html>
;; * <https://paste.guixotic.coop/_shell_-303560-303841.html>
;; * <https://paste.guixotic.coop/_shell_-304775-306702.html>
;; * <https://paste.guixotic.coop/_shell_-304845-305219.html>
;; * <https://paste.guixotic.coop/_shell_-31640912-31647212.html>
;; * <https://paste.guixotic.coop/_shell_3_-29527443-29542000.html>
;; * <https://paste.guixotic.coop/_shell_3_-3833-6765.html>
;; * <https://paste.guixotic.coop/_shell_3_-777-1916.html>
;; * <https://paste.guixotic.coop/_shell_4_-74658-75841.html>
;; * <https://paste.guixotic.coop/_shell_4_-76025-76742.html>
;; * <https://paste.guixotic.coop/_shell_-5222475-5224747.html>
;; * <https://paste.guixotic.coop/_shell_-750985-751144.html>
;; * <https://paste.guixotic.coop/_shell_-7645691-7645969.html>
;; * <https://paste.guixotic.coop/_shell_.html>
;; * <https://paste.guixotic.coop/sparrow.scm.html>
;; * <https://paste.guixotic.coop/storage-18177-32120.scm.html>
;; * <https://paste.guixotic.coop/syscalls-36105-37166.log.html>
;; * <https://paste.guixotic.coop/syscalls-36105-37701.log_tests_.html>
;; * <https://paste.guixotic.coop/syscalls-41800-42051.scm_build_.html>
;; * <https://paste.guixotic.coop/syscalls.scm_guix_tests_-25073-26126.html>
;; * <https://paste.guixotic.coop/terra-10213-10406.scm.html>
;; * <https://paste.guixotic.coop/terra-14835-15406.scm.html>
;; * <https://paste.guixotic.coop/testlog.txt.html>
;; * <https://paste.guixotic.coop/tests-8498-8891.scm.html>
;; * <https://paste.guixotic.coop/test-suite-24019-28258.log_guix-master_.html>
;; * <https://paste.guixotic.coop/ubuntu24.04-.logs.html>
;; * <https://paste.guixotic.coop/_unsent_mail_to_bug-gnu-emacs@gnu-332-125967.org_.html>
;; * <https://paste.guixotic.coop/unshare-einval-test.html>
;; * <https://paste.guixotic.coop/without-thread-context.html>
;; * <https://paste.guixotic.coop/xbss231sv6k0m25rqzxnw6pc74ldy7-gtk-4.22.1.drv.html>
;; * <https://paste.guixotic.coop/y1jfsd73sl8g3m14a59wqbbx8j3g7b-gtk-4.22.1-11846587-11848130.drv.html>
;; * <https://paste.guixotic.coop/y1jfsd73sl8g3m14a59wqbbx8j3g7b-gtk-4.22.1.drv.html>

;;; Commentary:

;; This will place an HTML copy of a buffer on the web on a server
;; that the user has shell access on.

;; It's similar in purpose to services such as https://gist.github.com
;; or https://pastebin.com, but it's much simpler since it assumes the user
;; has an account on a publicly-accessible HTTP server. It uses `scp'
;; as its transport and uses Emacs' font-lock as its syntax
;; highlighter instead of relying on a third-party syntax highlighter
;; for which individual language support must be added one-by-one.

;;; Install

;; Requires htmlize; available at
;; https://github.com/hniksic/emacs-htmlize.  If htmlize is not
;; installed, by default it will fall back to Emacs's own htmlfontify.

;; Open the file and run `package-install-from-buffer', or put it on your
;; `load-path' and add these to your config:

;; (autoload 'scpaste "scpaste" nil t)
;; (autoload 'scpaste-region "scpaste" nil t)

;; Set `scpaste-http-destination' and `scpaste-scp-destination' to
;; appropriate values, and add this to your Emacs config:

;; (setq scpaste-http-destination "https://p.hagelb.org"
;;       scpaste-scp-destination "p.hagelb.org:p.hagelb.org")

;; If you have a different keyfile, you can set that, too:
;; (setq scpaste-scp-pubkey "~/.ssh/my_keyfile.pub")

;; If you use a non-standard ssh port, you can specify it by setting
;; `scpaste-scp-port'.

;; If you need to use alternative scp and ssh programs, you can set
;; `scpaste-scp' and `scpaste-ssh'. For example, scpaste works with the Putty
;; suite on Windows if you set these to pscp and plink, respectively.

;; Optionally you can set the displayed name for the footer and where
;; it should link to:

;; (setq scpaste-user-name "Technomancy"
;;       scpaste-user-address "https://technomancy.us/")

;; You can set `scpaste-async' to non-nil to run the upload in the background.

;;; Usage

;; M-x scpaste, enter a name, and press return. The name will be
;; incorporated into the URL by escaping it and adding it to the end
;; of `scpaste-http-destination'. The URL for the pasted file will be
;; pushed onto the kill ring.

;; You can autogenerate a splash page that gets uploaded as index.html
;; in `scpaste-http-destination' by invoking M-x scpaste-index. This
;; will upload an explanation as well as a listing of existing
;; pastes. If a paste's filename includes "private" it will be skipped.

;; You probably want to set up SSH keys for your destination to avoid
;; having to enter your password once for each paste. Also be sure the
;; key of the host referenced in `scpaste-scp-destination' is in your
;; known hosts file--scpaste will not prompt you to add it but will
;; simply hang and need you to hit C-g to cancel it.

;;; 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, 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:

(require 'url)
(require 'htmlize nil t)

(defvar scpaste-html-converter
  (if (featurep 'htmlize)
      'htmlize-buffer
    'htmlfontify-buffer)
  "Name of the function to use to generate the HTML output.
By default, it will try to use `htmlize-buffer' from htmlize, and
will fall back to `htmlfontify-buffer' from Emacs's `htmlfontify'
if htmlize is not available.")

(defvar scpaste-scp-port
  nil)

(defvar scpaste-scp
  "scp"
  "The scp program to use.")

(defvar scpaste-ssh
  "ssh"
  "The ssh program to use when running remote shell commands.")

(defvar scpaste-http-destination
  "https://p.hagelb.org"
  "Publicly-accessible (via HTTP) location for pasted files.")

(defvar scpaste-scp-destination
  "p.hagelb.org:p.hagelb.org"
  "SSH-accessible directory corresponding to `scpaste-http-destination'.
You must have write access to this directory via `scp'.")

(defvar scpaste-scp-pubkey
  nil
  "Identity file for the server.
Corresponds to ssh’s `-i` option Example: \"~/.ssh/id.pub\".
It's better to set this in ~/.ssh/config than to use this setting.")

(defvar scpaste-user-name
  nil
  "Name displayed under the paste.")

(defvar scpaste-user-address
  nil
  "Link to the user’s homebase (can be a mailto:).")

(defvar scpaste-make-name-function
  'scpaste-make-name-from-buffer-name
  "The function used to generate file names, unless the user provides one.")

(defvar scpaste-el-location (replace-regexp-in-string "\.elc$" ".el"
                                                      (or load-file-name
                                                          (buffer-file-name))))

(defvar scpaste-async (bound-and-true-p exwm-state)
  "Upload pastes asynchronously when non-nil. Enabled by default in exwm.")

(defun scpaste-footer ()
  "HTML message to place at the bottom of each file."
  (concat "<p style='font-size: 8pt; font-family: monospace; "
          (mapconcat (lambda (c) (concat c "-select: none"))
                     '("-moz-user" "-webkit-user" "-ms-user" "user") "; ")
          "'>Generated by "
          (let ((user (or scpaste-user-name user-full-name)))
            (if scpaste-user-address
                (concat "<a href='" scpaste-user-address "'>" user "</a>")
              user))
          " using <a href='https://p.hagelb.org'>scpaste</a> at %s. "
          (cadr (current-time-zone)) ". (<a href='%s'>original</a>)</p>"))

(defun scpaste-read-name (&optional suffix)
  "Read the paste name from the minibuffer.

Defaults to the return value of `scpaste-make-name-function'
with SUFFIX as argument."
  (let* ((default (funcall scpaste-make-name-function suffix))
         (input (read-from-minibuffer (format "Name: (defaults to %s) "
                                              default))))
    (if (equal "" input) default input)))

(defun scpaste-make-name-from-buffer-name (&optional suffix)
  "Make a name from buffer name and extension.

If non-nil, SUFFIX is inserted between name and extension."
  (concat (file-name-sans-extension (buffer-name))
          suffix
          (file-name-extension (buffer-name) t)))

(defun scpaste-make-name-from-timestamp (&optional _)
  "Make a name from current timestamp and current buffer's extension."
  (concat (format-time-string "%s") (file-name-extension (buffer-name) t)))

(defun scpaste-exit-handler (exit-code full-url tmp-file tmp-hfile error-buffer)
  (delete-file tmp-file)
  (delete-file tmp-hfile)
  (if (= exit-code 0)
      (message "Pasted to %s (on kill ring)" full-url)
    (pop-to-buffer error-buffer)
    (help-mode-setup)))

(defun scpaste-upload (command tmp-file tmp-hfile full-url)
  (let* ((error-buffer "*scp-error*")
         (exit-code (shell-command (mapconcat 'identity command " ")
                                   nil error-buffer)))
    (kill-new full-url)
    (scpaste-exit-handler exit-code full-url tmp-file tmp-hfile error-buffer)))

(defun scpaste-sentinel (tmp-file tmp-hfile full-url process _change)
  (when (eq 'exit (process-status process))
    (scpaste-exit-handler (process-exit-status process) full-url
                          tmp-file tmp-hfile (process-buffer process))))

(defun scpaste-upload-async (command tmp-file tmp-hfile full-url)
  (kill-new full-url)
  (set-process-sentinel (apply 'start-process "scpaste" "*scpaste*" command)
                        (apply-partially 'scpaste-sentinel
                                         tmp-file tmp-hfile full-url)))

;;;###autoload
(defun scpaste (original-name)
  "Paste the current buffer via `scp' to `scpaste-http-destination'.
If ORIGINAL-NAME is an empty string, then the buffer name is used
for the file name."
  (interactive (list (scpaste-read-name)))
  (let* ((b (generate-new-buffer (generate-new-buffer-name "scpaste")))
         (pre-hl-line (and (featurep 'hl-line) hl-line-mode
                           (progn (hl-line-mode -1) t)))
         (hb (funcall scpaste-html-converter))
         (name (replace-regexp-in-string "[/\\%*:|\"<>  ]+" "_"
                                         original-name))
         (full-url (concat scpaste-http-destination
                           "/" (url-hexify-string name) ".html"))
         (tmp-file (concat temporary-file-directory name))
         (tmp-hfile (concat temporary-file-directory name ".html")))
    (when pre-hl-line
      (hl-line-mode 1))
    ;; Save the files (while adding a footer to html file)
    (save-excursion
      (copy-to-buffer b (point-min) (point-max))
      (switch-to-buffer b)
      (write-file tmp-file)
      (kill-buffer b)
      (switch-to-buffer hb)
      (goto-char (point-min))
      (search-forward "</body>\n</html>")
      (insert (format (scpaste-footer)
                      (current-time-string)
                      (substring full-url 0 -5)))
      (write-file tmp-hfile)
      (kill-buffer hb))

    (let* ((identity (and scpaste-scp-pubkey (list "-i" scpaste-scp-pubkey)))
           (port (and scpaste-scp-port (list "-P" scpaste-scp-port)))
           (command `(,scpaste-scp "-q" ,@identity ,@port ,tmp-file ,tmp-hfile
                                   ,(concat scpaste-scp-destination "/")))
           (select-enable-primary t))
      (if scpaste-async
          (scpaste-upload-async command tmp-file tmp-hfile full-url)
        (scpaste-upload command tmp-file tmp-hfile full-url)))))

;;;###autoload
(defun scpaste-region (name)
  "Paste the current region via `scpaste'.
NAME is used for the file name."
  (interactive (list (scpaste-read-name (format "-%s-%s" (region-beginning)
                                                (region-end)))))
  (let ((buffer-name (buffer-name))
        (beg-line (line-number-at-pos (region-beginning)))
        (end-line (line-number-at-pos (region-end)))
        (region-contents (buffer-substring (mark) (point))))
    (with-temp-buffer
      (rename-buffer (format "%s:%s"
                             buffer-name
                             (if (eq beg-line end-line)
                                 beg-line
                               (format "%s-%s" beg-line end-line))))
      (insert region-contents)
      (scpaste name))))

;;;###autoload
(defun scpaste-index ()
  "Generate an index of all existing pastes on server on the splash page."
  (interactive)
  (let* ((dest-parts (split-string scpaste-scp-destination ":"))
         (files (shell-command-to-string (concat scpaste-ssh " "
                                                 (car dest-parts) " ls "
                                                 (cadr dest-parts))))
         (file-list (split-string files "\n")))
    (save-excursion
      (with-temp-buffer
        (insert-file-contents scpaste-el-location)
        (goto-char (point-min))
        (search-forward ";;; Commentary")
        (forward-line -1)
        (insert "\n;;; Pasted Files\n\n")
        (dolist (file file-list)
          (when (and (string-match "\\.html$" file)
                     (not (string-match "private" file)))
            (insert (concat ";; * <" scpaste-http-destination "/" file ">\n"))))
        (emacs-lisp-mode)
        (if (fboundp 'font-lock-ensure)
            (progn (font-lock-mode nil)
                   (font-lock-ensure)
                   (jit-lock-mode t))
          (with-no-warnings ; fallback for Emacs 24
            (font-lock-fontify-buffer)))
        (rename-buffer "SCPaste")
        (write-file (concat temporary-file-directory "scpaste-index"))
        (scpaste "index")))))

(provide 'scpaste)
;;; scpaste.el ends here

Generated by apteryx using scpaste at Tue May 12 18:08:29 2026. JST. (original)