The idea is I select some text and press g y and emacs or vim will provide me with a command to go to that section of that file.

example usage of results

1
emacshelp +/"Major modes specialize Emacs for editing or interacting with particular" "(elisp) Major Modes"
1
ewwlinks +/"\* When ~~ is pressed, the Expect interpreter runs interactively.\"" "https://wiki.tcl-lang.org/page/interact"
1
man +/"For example, here are some things Expect can do:" "expect(1)"

emacs functions

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
(defun get-path (&optional soft)
       (interactive)
       ;; (xc-m (s/rp (buffer-file-name)))
       (or (and (eq major-mode 'Info-mode)
                (if soft
                    (concat "(" (basename Info-current-file) ") " Info-current-node)
                  (concat Info-current-file ".info")))
           (buffer-file-name)
           (buffer-file-path)
           (progn (save-temp-if-no-file)
                  (e/chomp (full-path)))))

(defun buffer-file-path ()
  (if (major-mode-enabled 'eww-mode)
      ;; (sh/ptw/xurls (or (eww-current-url)
      ;;                   eww-followed-link))
      (or (eww-current-url)
          eww-followed-link)
    (s/rp (or (buffer-file-name)
              (and (string-match-p "~" (buffer-name))
                   (concat (s/chomp (b vc get-top-level)) "/" (sed "s/\\.~.*//" (buffer-name))))
              (concat (s/chomp (b vc get-top-level)) "/" (buffer-name))))))
(defalias 'full-path 'buffer-file-path)

(defun get-vim-link (&optional editor)
  (interactive)
  (if (not editor)
      (setq editor "v"))
  (defvar uri)
  (defvar vimcmd)
  (setq uri (mnm (get-path t)))

  (setq vimcmd
        (cond ((major-mode-enabled 'eww-mode) "ewwlinks")
              ((major-mode-enabled 'Info-mode) "emacshelp")
              (t editor)))

  (if (selected)
      ;; (my/copy (concat "vim +/\"" (bs (selection) "/\"$*[]") "\" " (q (get-current-url))))
      ;; (my/copy (se 'show (concat "vim +/\"" (escape "`/\"$*[]" (selection)) "\" " (q (bp github-url-to-raw (get-current-url))))))
      (let ((cmd (concat vimcmd " +/" (vim-escape (e/chomp (bp head -n 1 (selection)))) " " (q uri))))
        (my/copy cmd)
        (message cmd)
        (deselect))))

vim functions and binding

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
fun! GetCopySearchFileProgram()
     if &ft=='help'
        return "vimhelp"
     elseif &ft=='man'
        return "man"
     else
        return "vim"
     endif
endf

fun! CopySearchFile(sel)
    let result=GetCopySearchFileProgram() . ' +/"'.escape(escape(a:sel, '\\'),'`/"$*[]\\').'" "'.GetCopySearchFilePath().'"'
    " silent! call system('xc -m', 'vim +/"'.escape(a:sel, '`/"$*[]').'" "'.expand('%:p').'"')
    silent! call system('xc -m', result)
    " silent! call system('xc -m', 'vim +/"'.escape(a:sel,'`"$*').'" "'.expand('%:p').'"')

    if v:shell_error == 0
        echom "Copied: " . result
    endif
endf

" line
fun! CopySearchFile(sel)
    let result=GetCopySearchFileProgram() . ' +/"'.escape(escape(a:sel, '\\'),'`/"$*[]\\').'" "'.GetCopySearchFilePath().'"'
    " silent! call system('xc -m', 'vim +/"'.escape(a:sel, '`/"$*[]').'" "'.expand('%:p').'"')
    silent! call system('xc -m', result)
    " silent! call system('xc -m', 'vim +/"'.escape(a:sel,'`"$*').'" "'.expand('%:p').'"')

    if v:shell_error == 0
        echom "Copied: " . result
    endif
endf
xmap gy

demonstrations

emacs info

1
emacshelp +/"before-change-functions" "(elisp) Position Parse"

asciinema recording

eww browser

1
ewwlinks +/"dos> convert a.tif a.jpg" "https://wiki.tcl-lang.org/page/exec+path+problems"
1
ewwlinks +/"if { \$prod1 > \$prod2 } {" "https://wiki.tcl-lang.org/page/Convex+hull"

Interesting. The braces are interpreted by PCRE. Not sure if that’s worth fixing at this point.

asciinema recording

man pages

1
man +/"package customre;" "perlre(1)"
1
man +/"UNIX 98 pseudoterminals" "pty(7)"

Because vim is running inside emacs in this one, I needed to create the vim bindings above.

vim help

1
vimhelp +/"Use CTRL-T or CTRL-O to jump back." "*helphelp.txt*"
1
vimhelp +/"1.20	29-May-2007" "*camelcasemotion.txt*"

asciinema recording

regular files

1
vim +/"call pathogen#infect()" "$VIMCONFIG/vimrc"
1
v +/"\*\* =emacshelp=" "$HOME/blog/posts/getting-permalinks-for-substrings-in-man-pages-urls-and-other-files.org"

asciinema recording

emacshelp

This script relies on tcl/expect to decorate my emacs wrapper with a parameter to search inside the file once emacs has opened.

Create the ems script

This script will give any emacs command a cli parameter +/"pattern" and automatically send the C-s <pattern> C-m.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/bash
export TTY

# This wraps a command with a pattern parameter =+/= that assumes the
# underlying command is emacs-based

( hs "$(basename "$0")" "$@" "#" "<==" "$(ps -o comm= $PPID)" 0</dev/null ) &>/dev/null

# Example
# ems +/"when done" sp $HOME/scripts/ems

while [ $# -gt 0 ]; do opt="$1"; case "$opt" in
    +/*) { # pattern
        pattern="$(p "$opt" | mcut -d+/ -f2 | s chomp)"

        shift
    }
    ;;

    *) break;
esac; done

if test -n "$pattern"; then
    x \
    -cd "$(pwd)" \
    -sh "$(cmd "$@")" \
    -e "When done with this frame" \
    -c s \
    -s "$pattern" \
    -c m \
    -i
else
    "$@"
fi

The emacshelp command

Without ems, the pattern would not be interpretted.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash
export TTY

( hs "$(basename "$0")" "$@" "#" "<==" "$(ps -o comm= $PPID)" 0</dev/null ) &>/dev/null

last_arg="${@: -1}"
funcname="$last_arg"
set -- "${@:1:$(($#-1))}" # shift last arg

ems "$@" orspe -e "(emacshelp $(aqf "$funcname"))"