# BufPreWrite hook dependent on buffer content

**URL:** <https://discuss.kakoune.com/t/bufprewrite-hook-dependent-on-buffer-content/1598>\
**Category:** Help\
**Tags:** hook, grep\
**Created:** [February 20, 2021, 8:52am UTC](https://discuss.kakoune.com/t/bufprewrite-hook-dependent-on-buffer-content/1598 "2021-02-20T08:52:51Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![basbebe](https://discuss.kakoune.com/letter_avatar_proxy/v4/letter/b/8edcca/32.png) [@basbebe](https://discuss.kakoune.com/u/basbebe)\
**Post date:** [February 20, 2021, 8:52am UTC](https://discuss.kakoune.com/t/bufprewrite-hook-dependent-on-buffer-content/1598/1 "2021-02-20T08:52:51Z")

</div>

Hi!

## The Problem

I want markdown files to get autoformatted on safe.  
For that, I want to use pandoc. Since I have markdown files with pandoc’s [YAML markdown header](https://pandoc.org/MANUAL.html#extension-yaml_metadata_block) and latex content, I need to consider that.  
Since the workaround needed for this creates redundant newlines in the beginning of the file (see [github isse](https://github.com/jgm/pandoc/issues/6901)), I want to adress this by either deleting theses newlines or by changing the `formatcmd` depending on file content.

#### Why not use `prettier` for formatting?

I would like to use `--reference-links` with pandoc, which creates references for all the links in the document at the bottom of the file.

## The Question

Depending on which way I choose, I want to do one of the following:

- (a) delete three newlines in the beginning of the file **or** after the YAML header
- (b) check the file content for a specific line within the YAML header

The problem is that either way, I’m not sure how to approach this since the YAML header starts with `---` but ends with either `---` or `...`.  
Also, it normally is at the beginning of the file but it doesn’t have to by definition.

So the only way I can come up with for matching this is some sort of complicated PCRE regex, wich wouldn’t be very portable at all.

Maybe soneone else has another idea?

---

<div class="post-metadata">

**Author:** ![duncan](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/duncan/32/95_2.png) [@duncan](https://discuss.kakoune.com/u/duncan)\
**Post date:** [February 23, 2021, 2:48am UTC](https://discuss.kakoune.com/t/bufprewrite-hook-dependent-on-buffer-content/1598/2 "2021-02-23T02:48:15Z")

</div>

Hi basbebe,  
It’s not everything but it may get you started. The top one I got from @dmerejkowsky. The other one I just winged it. Have fun. Bye 👋

```auto
# on every `:write` a hook like this can be done for every file type.
hook global BufWritePost .* %{
  nop %sh{ pandoc --flags "${kak_hook_param}" }
}
----
# or on a specific file type you can run something like `pandoc --flags`
hook global WinSetOption filetype=latex %{
  hook window BufWritePost .* %{ sh%{ pdflatex -halt-on-error -file-line-error -output-format=pdf -synctex=1 [...] } }
}

```

* * *

Hey basbebe, forgot I had this. You could swap it out for pandoc or yaml parser…

```auto
hook global WinSetOption filetype=kotlin %{
    # <https://discuss.kakoune.com/t/what-is-the-right-way-to-do-format-on-write/922/2>
    set-option window lintcmd 'ktlint --relative --verbose --editorconfig="$HOME/.editorconfig"'
    set-option window formatcmd 'ktlint --format--relative'
}

```

Bye buddy 👋

* * *

> [@basbebe](#):
>
> since the YAML header starts with `---` but ends with either `---` or `...`.

Might actually have a solution for you basbebe that I came across today. Source adapted:  
nficano 2019, _permissions_, dotfiles/bin/, viewed 05 March 2021, [dotfiles/bin/permissions at master · nficano/dotfiles · GitHub](https://github.com/nficano/dotfiles/blob/master/bin/permissions)

```shell
#!/bin/sh
#/ Shows the permissions of a file or directory in octal form.
#/
#/ USAGE:
#/ permissions /path/to/file/or/dir
#/
#/ EXAMPLES:
#/ permissions /usr/bin # drwxr-xr-x 755 /usr/bin

usage () {
  grep '^#/' < "$0" | cut -c4-
}

```

As the line begin is always known then the problem is only the line end. We can look for simple alternation pattern and pipe the result as above. Also consider the `sed` utility, a play ground can be found here [https://sed.js.org/](https://sed.js.org/).

`grep '^---.*(---|....)' | utility`

Unix utilities are not one off my strengths, so it’s an idea not proof of concept.

If that was no help to you at all, see you tomorrow. Bye 👋.

---

<div class="post-metadata">

**Author:** ![basbebe](https://discuss.kakoune.com/letter_avatar_proxy/v4/letter/b/8edcca/32.png) [@basbebe](https://discuss.kakoune.com/u/basbebe)\
**Post date:** [March 14, 2021, 7:03am UTC](https://discuss.kakoune.com/t/bufprewrite-hook-dependent-on-buffer-content/1598/3 "2021-03-14T07:03:46Z")

</div>

Hi duncan,

thanks for getting into this!

The last grep rule might go in the right direction.  
I will have to somehow select everything _except_ the YAML header and consider the case when it’s not at the beginning of the file.

I was kind of hoping there was another way of doing this in Kakoune (like how syntax highlighting and other highlighters select parts) but I guess this is the right approach.

---

<div class="post-metadata">

**Author:** ![duncan](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/duncan/32/95_2.png) [@duncan](https://discuss.kakoune.com/u/duncan)\
**Post date:** [March 16, 2021, 12:41pm UTC](https://discuss.kakoune.com/t/bufprewrite-hook-dependent-on-buffer-content/1598/4 "2021-03-16T12:41:26Z")

</div>

Hey basbebe, just had this thought that we haven’t considered for the yaml file. Output to temp and do your thing, then save it, the way you like it:

```auto
# ref: https://github.com/mawww/config/blob/master/kakrc#L136
define-command -params .. fifo %{ evaluate-commands %sh{
   output=$(mktemp -d "${TMPDIR:-/tmp}"/kak-fifo.XXXXXXXX)/fifo
   mkfifo ${output}
   ( eval "$@" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null

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

```

Copy and paste the bellow example into kakoune and give it a run manually to see the keys in action.

`---`  
Then on the `*fifo*` buffer do this:

```auto
# multi line output from begin and all lines inclusive of ending. 
execute-keys %s^---.*(^---|^...)$<ret>

# to delete all the enclosed
execute-keys d

# Or if on the one line match it, grab it, 
execute-keys %s^---.*(---|...)$<ret>

# and everything above it. Then delete current selection.
# <a-;>Gkdd <-- an extra d key maybe needed to remove top blank line.
execute-keys <a-;>Gkd

# either evaluate-commands or execute-keys for this one, I'm not sure which.
execute-keys :write filename.yaml

```

`...`

`:doc execeval`

_‘execute-keys runs keys as if they were pressed, whereas evaluate-commands evaluates its given parameters as if they were entered in the command prompt’._

Am I getting any better? All the best. Bye 👋
