~parasrah/filelist.kak

0ae741fc816e2059254fee886675bd1451b9a10b — parasrah 11 months ago 18b8430 main
rc: update filelist-add command to support multiple arguments

While it does come at a slight performance cost, this functionality is
important to support better integration with remote usage
1 files changed, 221 insertions(+), 217 deletions(-)

M rc/filelist.kak
M rc/filelist.kak => rc/filelist.kak +221 -217
@@ 2,221 2,225 @@
# FIXME: lack of TCO breaks recursion for executions

provide-module filelist %§
    declare-option -docstring '
        The command used to populate the filelist

        Example: find ''%s'' -type f -name ''%%s''
        Example: fd -t file -- ''%%s'' ''%s''
        Example: fd -t file -x realpath --relative-base="$PWD" "{}" \; -- ''%%s'' ''%s''
    ' str filelist_cmd 'find ''%s'' -type f -name ''%%s'''
    declare-option -docstring '
        Default pattern for ''filelist_cmd''

        Example (for glob, such as with find): ''*''
        Example (for regex, such as with fd): ''.''
    ' str filelist_default_pattern '*'

    declare-option -hidden int filelist_current_line 0
    declare-option -hidden str filelist_cwd ''

    define-command filelist-set -params 0..2 -file-completion -docstring "
        filelist-set [path] [pattern]

        Populate the filelist with the files at [path] that match [pattern].

        Default: [path] = $CWD
        Default: [pattern] = %%opt{filelist_default_pattern}
        Example: filelist-set autoload/ %opt{filelist_default_pattern}
        Example: filelist-set autoload/
    " %{ evaluate-commands %sh{
        dir="${1:-./}"
        pattern="${2:-$kak_opt_filelist_default_pattern}"

        output=$(mktemp -d "${TMPDIR:-/tmp}"/kak-filelist.XXXXXXXX)/fifo
        mkfifo ${output}

        cmd="$(printf "$kak_opt_filelist_cmd" "$dir")"
        cmd="$(printf "$cmd" "$pattern")"
        ( eval "$cmd" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null


        printf '%s\n' "evaluate-commands -try-client '$kak_opt_toolsclient' %{
               edit! -fifo ${output} *filelist*
               set-option buffer filetype filelist
               set-option buffer filelist_current_line 0
               hook -always -once buffer BufCloseFifo .* %{ nop %sh{ rm -r $(dirname ${output}) } }
        }"
    } }

    define-command filelist-add -params 1 -file-completion -docstring '
        filelist-add <path>

        Add a raw value to the filelist

        Example: filelist-add autoload/filelist.kak/LICENSE
    ' %{
        evaluate-commands -try-client "%opt{toolsclient}" -save-regs 'f' %{
            open-filelist-buffer
        set-register f "%arg{1}"
            execute-keys 'ge"fPo<esc>'
        }
    }

    define-command open-filelist-buffer -docstring 'open filelist buffer' %{
        try %{
            buffer *filelist*
        } catch %{
            evaluate-commands %sh{
                output=$(mktemp -d "${TMPDIR:-/tmp}"/kak-filelist.XXXXXXXX)/fifo
                mkfifo ${output}
                ( printf '%s' > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null

                printf %s\\n "evaluate-commands -try-client '$kak_opt_toolsclient' %{
                       edit! -fifo ${output} *filelist*
                       set-option buffer filetype filelist
                       set-option buffer filelist_current_line 0
                       hook -always -once buffer BufCloseFifo .* %{ nop %sh{ rm -r $(dirname ${output}) } }
                }"
            }
        }
    }

    define-command filelist-execute-keys -params 1.. -docstring 'execute a series of keys on each file in the filelist' %{
        open-filelist-buffer
        execute-keys gg
        filelist-exec-line %arg{@}
    }

    define-command -hidden filelist-exec-line -params 1.. %{
        try %{
            try %{
                execute-keys 'xs(?:[✗✓] )+<ret>d'
            }
            try %{
                execute-keys 'giGl'
                evaluate-commands -try-client %opt{jumpclient} -verbatim -- edit -existing %reg{.}
                execute-keys -- "%arg{@}"
                open-filelist-buffer
                execute-keys -draft 'I✓ <esc>'
            } catch %{
                open-filelist-buffer
                execute-keys -draft 'I✗ <esc>'
            }
            execute-keys 'gl?^[^\n]+$<ret>;x'
            filelist-exec-line %arg{@}
        }
    }

    alias global filelist-exec filelist-execute-keys

    define-command filelist-next -docstring 'Go to next file from filelist' %{
        evaluate-commands -try-client %opt{jumpclient} %{
            buffer '*filelist*'
            execute-keys "ge,%opt{filelist_current_line}g<a-l>/^(?!#)[^\n]+$<ret>"
            filelist-jump
        }
        try %{
            evaluate-commands -client %opt{toolsclient} %{
                buffer '*filelist*'
                execute-keys gg %opt{filelist_current_line}g
            }
        }
    }

    define-command filelist-previous -docstring 'Go to previous file from filelist' %{
        evaluate-commands -try-client %opt{jumpclient} %{
            buffer '*filelist*'
            execute-keys "ge,%opt{filelist_current_line}g<a-h><a-/>^(?!#)[^\n]+$<ret>"
            filelist-jump
        }
        try %{
            evaluate-commands -client %opt{toolsclient} %{
                buffer '*filelist*'
                execute-keys "gg,%opt{filelist_current_line}g"
            }
        }
    }

    define-command filelist-enable-persistence -docstring 'enable filelist persistence' %{
        set-option global filelist_cwd %sh{ printf "$PWD" }
        filelist-load

        hook -group filelist-persist-option global WinSetOption filetype=filelist %{
            hook -group filelist-persist-impl window NormalIdle .* %{
                filelist-persist
            }

            hook -once -always window WinSetOption filetype=.* %{
                remove-hooks window filelist-persist-impl
            }
        }
    }

    define-command filelist-disable-persistence -docstring 'disable filelist persistence' %{
        evaluate-commands -draft %{
            open-filelist-buffer
            remove-hooks global filelist-persist-option
            remove-hooks window filelist-persist-idle
        }
    }

    define-command -hidden filelist-load %{ evaluate-commands %sh{
        if test -f "$kak_opt_filelist_cwd/.filelist.kak"; then
            dir="${1:-./}"
            pattern="${2:-$kak_opt_filelist_default_pattern}"

            output=$(mktemp -d "${TMPDIR:-/tmp}"/kak-filelist.XXXXXXXX)/fifo
            mkfifo ${output}

            ( eval "cat '$kak_opt_filelist_cwd/.filelist.kak'" | sed -z '$ s/\n$//' > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null

            printf '%s\n' "evaluate-commands -try-client '$kak_opt_toolsclient' %{
                   edit! -fifo ${output} *filelist*
                   set-option buffer filetype filelist
                   set-option buffer filelist_current_line 0
                   hook -always -once buffer BufCloseFifo .* %{ nop %sh{ rm -r $(dirname ${output}) } }
            }"
        else
            printf 'nop\n'
        fi
    } }

    define-command -hidden filelist-persist %{
        evaluate-commands -draft %{
            open-filelist-buffer
            execute-keys '%'
            nop %sh{
                printf '%s' "$kak_reg_dot" > "$kak_opt_filelist_cwd/.filelist.kak"
            }
        }
    }
            
    define-command -hidden filelist-jump %{
        evaluate-commands %{
            try %{
                execute-keys 'xs^([✗✓] )?([^\n]+):(\d+)<ret>'
                set-option buffer filelist_current_line %val{cursor_line}
                evaluate-commands -try-client %opt{jumpclient} -verbatim -- edit -existing %reg{2} %reg{3}
            } catch %{
                execute-keys 'xs^([✗✓] )?([^\n]+)<ret>'
                set-option buffer filelist_current_line %val{cursor_line}
                evaluate-commands -try-client %opt{jumpclient} -verbatim -- edit -existing %reg{2}
                try %{ focus %opt{jumpclient} }
            }
        }
    }

    hook -group filelist-highlight global WinSetOption filetype=filelist %{
        add-highlighter window/filelist regions
        add-highlighter window/filelist/comment region '#' '$' fill comment
        add-highlighter window/filelist/code default-region group
        add-highlighter window/filelist/code/ regex '^(?!#)(✗ )?(✓ )?(.*?/?)([^/]*)$' 1:red 2:green 3:cyan
        add-highlighter window/filelist/code/ line %{%opt{filelist_current_line}} default+b
    }

    hook global WinSetOption filetype=filelist %{
        map window normal <ret> ': filelist-jump<ret>' -docstring 'goto buffer'

        hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/filelist }
    }
	declare-option -docstring '
		The command used to populate the filelist

		Example: find ''%s'' -type f -name ''%%s''
		Example: fd -t file -- ''%%s'' ''%s''
		Example: fd -t file -x realpath --relative-base="$PWD" "{}" \; -- ''%%s'' ''%s''
	' str filelist_cmd 'find ''%s'' -type f -name ''%%s'''
	declare-option -docstring '
		Default pattern for ''filelist_cmd''

		Example (for glob, such as with find): ''*''
		Example (for regex, such as with fd): ''.''
	' str filelist_default_pattern '*'

	declare-option -hidden int filelist_current_line 0
	declare-option -hidden str filelist_cwd ''

	define-command filelist-set -params 0..2 -file-completion -docstring "
		filelist-set [path] [pattern]

		Populate the filelist with the files at [path] that match [pattern].

		Default: [path] = $CWD
		Default: [pattern] = %%opt{filelist_default_pattern}
		Example: filelist-set autoload/ %opt{filelist_default_pattern}
		Example: filelist-set autoload/
	" %{ evaluate-commands %sh{
		dir="${1:-./}"
		pattern="${2:-$kak_opt_filelist_default_pattern}"

		output=$(mktemp -d "${TMPDIR:-/tmp}"/kak-filelist.XXXXXXXX)/fifo
		mkfifo ${output}

		cmd="$(printf "$kak_opt_filelist_cmd" "$dir")"
		cmd="$(printf "$cmd" "$pattern")"
		( eval "$cmd" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null


		printf '%s\n' "evaluate-commands -try-client '$kak_opt_toolsclient' %{
			edit! -fifo ${output} *filelist*
			set-option buffer filetype filelist
			set-option buffer filelist_current_line 0
			hook -always -once buffer BufCloseFifo .* %{ nop %sh{ rm -r $(dirname ${output}) } }
		}"
	} }

	define-command filelist-add -params 1.. -file-completion -docstring '
		filelist-add <path ...>

		Add a raw value (or values) to the filelist

		Example: filelist-add autoload/filelist.kak/LICENSE
		Example: filelist-add autoload/filelist.kak/LICENSE autoload/filelist.kak/rc/filelist.kak
	' %{ evaluate-commands -try-client "%opt{toolsclient}" -save-regs 'f' %sh{
			println() { printf '%s\n' "$*"; }

			println open-filelist-buffer

			for i in $(seq $#); do
				println set-register f "%arg{${i}}"
				println execute-keys 'ge"fPo<esc>'
			done
	} }

	define-command open-filelist-buffer -docstring 'open filelist buffer' %{
		try %{
			buffer *filelist*
		} catch %{
			evaluate-commands %sh{
				output=$(mktemp -d "${TMPDIR:-/tmp}"/kak-filelist.XXXXXXXX)/fifo
				mkfifo ${output}
				( printf '%s' > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null

				printf %s\\n "evaluate-commands -try-client '$kak_opt_toolsclient' %{
					edit! -fifo ${output} *filelist*
					set-option buffer filetype filelist
					set-option buffer filelist_current_line 0
					hook -always -once buffer BufCloseFifo .* %{ nop %sh{ rm -r $(dirname ${output}) } }
				}"
			}
		}
	}

	define-command filelist-execute-keys -params 1.. -docstring 'execute a series of keys on each file in the filelist' %{
		open-filelist-buffer
		execute-keys gg
		filelist-exec-line %arg{@}
	}

	define-command -hidden filelist-exec-line -params 1.. %{
		try %{
			try %{
				execute-keys 'xs(?:[✗✓] )+<ret>d'
			}
			try %{
				execute-keys 'giGl'
				evaluate-commands -try-client %opt{jumpclient} -verbatim -- edit -existing %reg{.}
				execute-keys -- "%arg{@}"
				open-filelist-buffer
				execute-keys -draft 'I✓ <esc>'
			} catch %{
				open-filelist-buffer
				execute-keys -draft 'I✗ <esc>'
			}
			execute-keys 'gl?^[^\n]+$<ret>;x'
			filelist-exec-line %arg{@}
		}
	}

	alias global filelist-exec filelist-execute-keys

	define-command filelist-next -docstring 'Go to next file from filelist' %{
		evaluate-commands -try-client %opt{jumpclient} %{
			buffer '*filelist*'
			execute-keys "ge,%opt{filelist_current_line}g<a-l>/^(?!#)[^\n]+$<ret>"
			filelist-jump
		}
		try %{
			evaluate-commands -client %opt{toolsclient} %{
				buffer '*filelist*'
				execute-keys gg %opt{filelist_current_line}g
			}
		}
	}

	define-command filelist-previous -docstring 'Go to previous file from filelist' %{
		evaluate-commands -try-client %opt{jumpclient} %{
			buffer '*filelist*'
			execute-keys "ge,%opt{filelist_current_line}g<a-h><a-/>^(?!#)[^\n]+$<ret>"
			filelist-jump
		}
		try %{
			evaluate-commands -client %opt{toolsclient} %{
				buffer '*filelist*'
				execute-keys "gg,%opt{filelist_current_line}g"
			}
		}
	}

	define-command filelist-enable-persistence -docstring 'enable filelist persistence' %{
		set-option global filelist_cwd %sh{ printf "$PWD" }
		filelist-load

		hook -group filelist-persist-option global WinSetOption filetype=filelist %{
			hook -group filelist-persist-impl window NormalIdle .* %{
				filelist-persist
			}

			hook -once -always window WinSetOption filetype=.* %{
				remove-hooks window filelist-persist-impl
			}
		}
	}

	define-command filelist-disable-persistence -docstring 'disable filelist persistence' %{
		evaluate-commands -draft %{
			open-filelist-buffer
			remove-hooks global filelist-persist-option
			remove-hooks window filelist-persist-idle
		}
	}

	define-command -hidden filelist-load %{ evaluate-commands %sh{
		if test -f "$kak_opt_filelist_cwd/.filelist.kak"; then
			dir="${1:-./}"
			pattern="${2:-$kak_opt_filelist_default_pattern}"

			output=$(mktemp -d "${TMPDIR:-/tmp}"/kak-filelist.XXXXXXXX)/fifo
			mkfifo ${output}

			( eval "cat '$kak_opt_filelist_cwd/.filelist.kak'" | sed -z '$ s/\n$//' > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null

			printf '%s\n' "evaluate-commands -try-client '$kak_opt_toolsclient' %{
				edit! -fifo ${output} *filelist*
				set-option buffer filetype filelist
				set-option buffer filelist_current_line 0
				hook -always -once buffer BufCloseFifo .* %{ nop %sh{ rm -r $(dirname ${output}) } }
			}"
		else
			printf 'nop\n'
		fi
	} }

	define-command -hidden filelist-persist %{
		evaluate-commands -draft %{
			open-filelist-buffer
			execute-keys '%'
			nop %sh{
				printf '%s' "$kak_reg_dot" > "$kak_opt_filelist_cwd/.filelist.kak"
			}
		}
	}

	define-command -hidden filelist-jump %{
		evaluate-commands %{
			try %{
				execute-keys 'xs^([✗✓] )?([^\n]+):(\d+)<ret>'
				set-option buffer filelist_current_line %val{cursor_line}
				evaluate-commands -try-client %opt{jumpclient} -verbatim -- edit -existing %reg{2} %reg{3}
			} catch %{
				execute-keys 'xs^([✗✓] )?([^\n]+)<ret>'
				set-option buffer filelist_current_line %val{cursor_line}
				evaluate-commands -try-client %opt{jumpclient} -verbatim -- edit -existing %reg{2}
				try %{ focus %opt{jumpclient} }
			}
		}
	}

	hook -group filelist-highlight global WinSetOption filetype=filelist %{
		add-highlighter window/filelist regions
		add-highlighter window/filelist/comment region '#' '$' fill comment
		add-highlighter window/filelist/code default-region group
		add-highlighter window/filelist/code/ regex '^(?!#)(✗ )?(✓ )?(.*?/?)([^/]*)$' 1:red 2:green 3:cyan
		add-highlighter window/filelist/code/ line %{%opt{filelist_current_line}} default+b
	}

	hook global WinSetOption filetype=filelist %{
		map window normal <ret> ': filelist-jump<ret>' -docstring 'goto buffer'

		hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/filelist }
	}
§