Note Taking Manual
Table of Contents
1 TODO Clean up and Replace previous Method
2 TODO Clear off Workload of attempts
3 Introduction
The important features are:
- Writing Material
- Finding Material
- Reading Material
- Mobile
- Desktop
- Sharing Material
3.1 Org-Mode
and Markdown
While org-mode
is full featured and powerful, there are a
few reasons I don't like it for the backbone of a note taking system:
3.1.1 Problems with org-mode
- Emacs with
org-mode
is just far too unstable, I've spent hours, well no weeks, literally 9-5 weeks trying to get it stable, you blink and it fails to export, or inline create math or whatever, whereas markdown just works, lacking in features, but, it just works. - Emacs takes an enormous amount of configuration
- my
~/.emacs.d/init.el
is already at like 500 lines and I'm using a starter kit (Spacemacs)- With Emacs 28, this is now in
~/.config/emacs/init.el
where it should be but I don't really look forward to moving it.
- With Emacs 28, this is now in
- my
- Emacs can get really slow
- This is probably on my end, but again, a pain in the ass
- No mobile editors (see 2.1 below)
- I don't like beorg, it sucks for long notes, doesn't support
inline math and it doesn't work well with
git
, using Dropbox is nothing but a headache when it comes to syncing.- I've heard good things about it's support for the
agenda but I don't use
org-mode
like that, I use thetodo
features to track a specific project in an index but I use ToDoist because it's just simpler to use.
- I've heard good things about it's support for the
agenda but I don't use
- I don't like beorg, it sucks for long notes, doesn't support
inline math and it doesn't work well with
- It only works with emacs
- The Vim Rendition is half-way there
- markdown works in both and
emacs
doesn't scroll with the mouse which is a shame on the laptop. - You'll miss fzf,
helm-locate
andhelm-ag
don't even come close.
- No live preview for math sucks
- Math inline preview will break if there is a bug above
- this is a dealbreaker honestly, it's ridiculous
- Exported Math depends on previous math, whereas markdown is compartmentalised
yasnippets
doesn't hold a candle to using UltiSnips to write LaTeX in vim. andcompany-mode
isn't much better than Deoplete, but i'll admit YCM is a buggy mess that fails when you blink- bugs in
init.el
can break HTML export
3.1.2 Strengths to org-mode
Although it does have some features that justify using it:
- inline LaTeX preview is really great
- if youre willing to compile ghostscript v50 from
source if you're not on Arch-Linux
- oh and you can tollerate opening your
init.el
to inclrease the font size as opposed to usingC-x C-+ C--
- oh and you can tollerate opening your
- if youre willing to compile ghostscript v50 from
source if you're not on Arch-Linux
- It really is more readable as raw text than Markdown
- This means if you use WorkingCopy on iOS you
can practically edit and work with your
org
set-up- If you're using
org-wiki
you can even follow the HTML File through all the links which is great, because I think the tags and agenda suck for navigating notes/notebooks.1 - Alternatively you could use
python3 -m http.server 8351 --bind 192.168.0.134
to look on the ipad, but this is annoying because you have to grap your ipv4 before doing that if you're out of the house unlike iamcco's preview which does it automatically.
- If you're using
- This means if you use WorkingCopy on iOS you
can practically edit and work with your
- Foldable Code Boxes out of the box
- with MD you have to use
set foldmethod=manual
and a text-object plugin.
- with MD you have to use
- Once it is set up creating links with
SPC a o l
feels amazing - Inline code is amazing with outshine mode
- I cannot get outshine to play with R though so I don't know
- Literate Programming with it is amazing, so many of my
bash
scripts start asorg-mode
usingorg-edit-special
and then I just pull the bash out [fn:9] and use =SPC m e e t u
to give myself a manual/help dialog for it, it feels like magic!! - Managing long documents with emacs is a lot easier, because the folding feels very natural and the syntax highlighting is brilliant.
citeproc-org
makes your HTML documents look just like they would with BibTeXorg-mode
supports the minted package out of the box (minted looks better than listing and actually supports most languages likevimscript
andelisp
org-mode
interprets LaTeX properly and then passes it to mathjax, markdown is so confusing because you wrap everything in$
even if you wouldn't in LaTeX and I think that's ridiculous.- you never need to leave
emacs
- I map
C-c
e=/=v
to vim emacs so it shouldn't matter.
- I map
3.1.3 Use Case
Basically the choice of format will depend on the note type,
- A long document like a manual will go into
org-mode
- because the interlinking is brilliant and the inbuild HTML export
- A short note will go into
md
because- fzf works in vim works with
md
- more apps support it (MWeb/iaWriter)
- More programs have support for smaller document notes:
- live preview of math is excellent
- Two features, missing by
org-mode
2 but available forMD
which are crucial to filtering through small notes (and available in Evernote) are:- Something I call fuzzy-search-with-live-preview which is
provided only by Notable
- although
fzf --preview
comes pretty close- This is implemented in vim with
notational-fzf
, which is amazing
- This is implemented in vim with
- although
- Recursively Filtering through tags
- Something I call fuzzy-search-with-live-preview which is
provided only by Notable
- fzf works in vim works with
3.1.4 Using pandoc
Thankfully pandoc
means you shouldn't really too much
about this stuff though, you can literally paste org-mode
out of the clipboard into Markdown and vice-versa if you
map a bash script to a keybinding 3
input=$(xclip -o -selection clipboard) alias xclip='xclip -selection clipboard' # To Org xclip -o | pandoc -s -f markdown -t org | xclip # Back to Markdown xclip -o | pandoc -s -t markdown -f org | xclip
Actually with pipes you can do all sort of cool things, like this is an example of how to pull a website into markdown:
curl https://orgmode.org/manual/Markdown-Export.html#Markdown-Export | pandoc -f HTML -t gfm | xclip -selection clipboard
and reference it using beautifulsoup
:
arglink=$(xclip -o -selection clipboard) title=$(wget -qO- $arglink | perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si' | recode html..) outputlink="[$title]($arglink)" echo $outputlink | xclip -selection clipboard
- Problems with links
Links may become a pain in the ass to maintain, so what i do is copy the file name to the clipboard and use fzf with this bash script to make a relative link to a file:
#!/bin/bash # Don't forget to adjust the permissions with: #chmod +x ~/somecrazyfolder/script1 ## Program ### Description # This will use fzf to find filenames that might correspond to a path from a broken link in the clipboard. # so let's say that ~[](~/broken/path/to/rsico.png)~ is a broken link, I can use ~yi(~ to copy that to the clipboard in vim and run the following bash scipt to return the correct link: # Requires: # * gnu coreutils (specifically realpath) # * fzf # * xclip ### Code brokenPath=$(xclip -o -selection clipboard) #find ~/Dropbox/ -name $(echo $(basename $brokenPath)) | fzf | xclip -selection clipboard NewFile=$(find ~/Dropbox/ -name $(echo $(basename $brokenPath)) | fzf) echo $NewFile | xclip -selection clipboard echo " Put the path of the source file in the clipboard and Press any Key to Continue " # this will just continue after a key stroke read -d'' -s -n1 echo " Using: " sourceFile=$(xclip -o -selection clipboard) echo " SOURCE_FILE.......$sourceFile NEW_ATTACHMENT....$NewFile " sourcePath=$(dirname $sourceFile) relativePath=$(realpath --relative-to=$sourcePath $NewFile) relPathWithDot="./"$relativePath echo $relPathWithDot | xclip -selection clipboard echo " Success! Relative path is in clipboard " exit 0 ## vim:fdm=expr:fdl=0 ## vim:fde=getline(v\:lnum)=~'^##'?'>'.(matchend(getline(v\:lnum),'##*')-2)\:'='
4 Sharing Material
4.1 Markdown
- HackMD is an option
- MkDocs and GitHub
4.2 Org-Mode
- put the HTML on Github
4.3 HTML and iOS
- Shortcuts
- iCloud is quicker
- Dropbox allows mathjax
- WorkingCopy (best)
- phenomenal, uses mathml for math in
MD
- uses MathJax to view Math in HTML
- phenomenal, uses mathml for math in
5 Writing Material
5.1 Diagrams
5.1.1 Apple Pencil
5.1.2 TiKz
Tikz is awesome but this is actually a bit of work to implement:
See Previous work on
- write in LaTeX
- export using a luascript
- grab the svg
- be aware that getting an svg in LaTeX is a real pain, so you can go from TeX to HTML with the lua script but not really back, its madness.
- Or you could go from
svg
topng
but then you lose scaling so the whole thing sucks - You could also use LaTeX and just export to HTML with Mathjax
This is probably the way to go tbh.
- You can open the HTML from notable :shrug:
5.1.3 InkScape
6 Finding Material
6.1 Tags
Tags revolve around:
- Entering the same tag
- Browsing through tags
6.1.1 Yaml Tags
These are basically Notebooks, they make more sense than folders
because you can change them using vim
and sed
which scales
better over many files and is easier to maintain than manually maintaining
symlinks
across directories.
These are supported by:
Notable
VsCode
And they work really well for there rigid strucutre
- Inserting
YAML
Tags ATTACH
In order to insert a
YAML
tag into a note withvim
you can useFZF
to read a text file and make suggestions from a text file with those entries:imap <expr> <C-c><C-y> fzf#vim#complete('cat ~/Notes/MD/notes/00tags.csv')
In order to get that text file you can use an R that leverages
RMarkdown
to pull theyaml
out:noteFiles <- c(dir(pattern="*.Rmd"), dir(pattern="*.md"), dir(pattern="*.txt"), dir(pattern="*.markdown")) tagVector <- c() # Run the following code over the entire folder for (i in noteFiles){ yamlExtract <- yaml_front_matter(input = i ) MDTags <- (yamlExtract$tags) tagVector <- c(MDTags, tagVector) # Generate Symlinks for (tagDirPath in MDTags) { actDirPath <- paste0("./aaaamytest/", tagDirPath) dir.create(path = actDirPath, recursive = TRUE) linkPath=paste0( actDirPath, "/", i) print(i) print(linkPath) createLink(link = linkPath, target = i) } }
Then you can just regenerate the tags as needed with
$ Rscript makeTags.R
and insert them withC-c C-y
.This can be seen in this gif:
- Browsing Yaml Tags
In order to browse
YAML
tags just search for the verbatim structure withripgrep
, in this contextYAML
tags are only used to set up notebook directories, so they will always be nested with/
characters, hence the number of false positives will be small enough to justify this simplicity:cat 00tags.csv | rg '[a-zA-Z0-9]+/[a-zA-Z0-9/]+' | fzf | xargs rg -l > /tmp/kdkdjaksd; cat /tmp/kdkdjaksd # I couldn't get a pipe to work so I had to save to /tmp
- Folder Structure
You can Also browse through the YAML tags like a folder structure, the above RScript at 6.1.1.1 uses a nested
for
loop to create a directory structure with symlinks for the corresponding notes.
- Folder Structure
6.1.2 #Tags
So the advantage to inline tags is that they are:
- Really simple to implement and use
- for example using
YAML
basically requires a parser because:- if you're working with something rigid like
YAML
you need to support it properly or the system will fall apart, butYAML
can use:python
-style lists- mappings
- New line sequences
- Even if
YAML
used just one syntax, it would not be easy to implement in regex because look around features don't like to work with wild cards, moreover doing something like\-\-\-\n[\w\W]*tags:\s
cannot be efficient.
- if you're working with something rigid like
- for example using
- Can appear anywhere in your document
- If you use iamcco's preview, the scroll can be locked to once you jump to the tag it will be in the preview as well.
- Because they are easy to implement they can be concurrently filtered
I've elected to use #tags
rather than @
4 becuase
it's more common and is implemented by iaWriter
, meaning
I can use smart folders on the iPad
, :tag:
was another
option I rejected 5.
In order to reduce false positives it's important to have a really clear definition of a tag, I've chosen to do \s#TAGNAME\s
, this should work well, I just need to be mindful to include spaces around the tags.
- Listing already Created tags
This is where
#tags
really shine, because they are easy to parse and becauseripgrep
andfzf
are both lightning fast all the notes can be searched and all the tags listed on the fly like so:imap <expr> <C-c><C-t> fzf#vim#complete('rg --pcre2 "\s#[a-zA-Z-@]+\s" -o --no-filename $HOME/Notes/MD/notes -t md \| sort -u')
Then simply presing
C-c C-t
invim
will allow you to enter the matching tag. - Filtering by the desired tag
This is where
#tags
are amazing, because they are so simple, they can be recursively filtered for, first create a temporary file to store any notes that have tags in them6, then useripgrep
withlook-around
to extract the tag name:First find all the tags and offer the user
# Make a temp file to store results if necessary if test -f 00TagMatchList; then echo "subsequent search"; else # List in order of modification Date, top newest ls -t *.md > 00TagMatchList; fi tagval=$(cat 00TagMatchList | xargs -d '\n' rg --pcre2 --no-pcre2-unicode --no-filename '(?<=[\n\s]#)[a-zA-z]+(?=[\s\n$])' -o | sort -u | fzf)
After the tags have been identified and passed to the user, save the
tagval
as a temp file and search through all the notes listed in the file for any matches:if [[ ! -z $tagval ]]; then echo ' wait for fzf to finish otherwise ripgrep has nothing with which to filter ' exit 1 else cat 00TagMatchList | xargs rg ":$tagval:|\s#$tagval\s" -l > 00TagMatchList; fi bat 00TagMatchList
Now you can re run those last two commands (which I've written into a
bash
script astagFilter.sh
here, over and over again until the number of listed tags is down to a reasonable number7 .Once you're satisfied that the results are sufficiently filtered you can dump them as symlinks into a direcory like so:
mkdir 00TagMatch rm 00TagMatch/* ln -s $(realpath $(cat 00TagMatchList)) ./00TagMatch; rm 00TagMatchList
Then you can go through that directory using
fzf
and--preview
with 8:rg --files-with-matches --no-messages "$1" | fzf --preview "highlight -O ansi -l {} 2> /dev/null | rg --colors 'match:bg:yellow' --ignore-case --pretty --context 10 '$1' || rg --ignore-case --pretty --context 10 '$1' {}"
Or you you could preview the files in ranger using
glow
by appending the following to your scope.sh:9... md|markdown) glow -s dark "${FILE_PATH}" && { dump | trim; exit 5; } ;; ...
- Integrating with TMSU
Alternatively you can leverage TMSU to make all the symlinks, both is probably the way to go because that way you're not tied to TMSU (plus the mounting is a little buggy) but you can still leverage it
# Piping is still better than a loop because ripgrep acts on everything # Unfoutunately you cannot pipe directley into tmsu cd ~/Notes/MD/notes rg --pcre2 '(?<=\s#)[a-zA-Z]+(?=\s)' *.md -o \ | sed s+:+\ + | sed s/^/tmsu\ tag\ / | bash
TMSU wouldn't work so well with nested
yaml
TAGS because TMSU doesn't have any notion of nested tags, instead it would be easier to create symlinks directly from R usingR.utils::createLink()
- Browsing through the Symlinks
Then you can mount the TMSU Virtual File System wherever you like and there is an easy to browse through tags.
What works really well though is to open nvim in the directory with:
# any other way causes a crash # also confusingly =|= is to vim as =;= is to bash nvim -c 'set noautochdir | cd 00tmsutags/ | pwd'#+end_src
and then search through the files using
:Files
from FZF (mapped toC-p
/SPC f f
) and/or NerdTree, and use iamcco's preview in Firefox with Tree Style Tab to stay organised. If you'd rather work frombash
you can usefzf
with the--preview
option from before.Or you could use vim with and a preview app like iamcco's.
Or you could preview all the markdown in a rendered state by using MarkText / or Typora, or Zettlr, Abricotine, Typora, MarkdownViewer Chrome Plugin10 , MkDocs or Docsify, are other options that work in some way.
Another good option for navigating the 'tags are now folders' structure is to use VSCode and/or atom, both are well suited to navigating through a dense structure.
Dillinger is also really cool, but, I don't know what I'd use it for, could I get it on the ipad by hosting my own server maybe?
- Renaming Tags
Just use a careful application of
sed
if this is necessary:sed -i s+#OldTag+#NewTag+g
- Renaming Files
Somewhat integral to the Tag Filtering operation above is reasonable file names, if it's necessary to fix the file name just use
chdir "%p"; ! mv "%" newname.md
.This will break links, but if a note is already linked from elsewhere you'd make a new note and/or delete the old one.
- Searching Tag Under Cursor
In order to search for the word under the cursor you could just
:Rg
byFZF
,:NV
bynotational-fzf-vim
offers a seamless preview as well so I'll just use that.Add the following to
.vimrc
and you'll be able to search for a tag under the cursor withSPC f g
and if you forget keyboard shortcutsSPC Tab
will list them."let mapleader="\<Space>" map <Space> <Leader> :set iskeyword+=# nmap <Space>fg :NV <C-r><C-w> <CR> nmap <leader><tab> <plug>(fzf-maps-n)
7 Viewing Material
7.1 Vim-Plugin
7.2 Firefox
while Previewing MD in the browser, in order to keep your sanity, you're going to want to use this Tree add on to keep yourself organised.
7.3 Chrome Browser Extension
Firefox will not allow local MD files to be rendered with
an add on as a security policy, instead you can
Firefox doesn't allow markdown files to be rendered inside
the browser if they are local ( nor does it make it easy if
you do it with a simple python3 -m http.server 8089 --bind 192.168.0.137
)
you'd be better off just doing it in chrome with This extension
7.4 WYSIWYG Editor
7.5 Notable
8 Appendix
8.1 Emacs Speaks Statistics
Emacs is amazing for literate programming, but it's a nightmare to work with,
it has it's place but Nvim-R
is definitely best in class for literate
programming using R-Markdown, but there are cases where using R in
org-mode
is really handy, for example, to make a bar chart of all the words in
this manual:
## Load Tidy Verse library(tidyverse) ## Scan Through the Manual words <- tolower(scan("./manual.org", what = "", na.strings = c("|",":")) ) ## Use Grep to pull out org #+ Blocks words <- words[-grep(pattern = "#.*", x = words)] ## Sort the words by frequency and cut the results topwords <- sort(table(words[nchar(words) > 3]), decreasing = TRUE)[1:9] topwords <- as_tibble(topwords, .name_repair = "universal") names(topwords) <- c("Word", "Frequency") print(topwords)
Word | Frequency |
---|---|
with | 54 |
this | 44 |
using | 29 |
tags | 24 |
because | 21 |
just | 21 |
like | 21 |
will | 21 |
that | 20 |
## Make Plot WordFreqPlot <- ggplot(topwords, aes(y = Frequency, x = Word, fill = -Frequency)) + geom_col() + theme_minimal() # Export the Plot into the working directory plotname <- "WordCount" png(filename=paste0(plotname, ".png")) print(WordFreqPlot) dev.off() # Print the =org-mode= link syntax print(paste0( "\n", "Output:", "\n", "[[./", plotname, ".png", "]]"))
x |
---|
Output: |
8.1.1 Using ESS with org-babel
- Output types
- Results Type
Notice that this block when executed with
C-c
will give the STDOUTrnorm(9)
[1] 0.6382742 0.8345823 1.7164897 -1.6547841 0.3749552 -0.3740537 -0.1397769 [8] 1.7248219 -0.6240926
Where as this block will give the expected results:
rnorm(9)
-0.291413700921148 -0.842118271320166 0.607393290039903 -1.45235488571945 0.76756412055268 -0.781050222761955 -0.00871441944811291 2.55762250149617 0.035717298920082 - Format Type
You can also change the output to better integrate with org by using
:format raw
or:format org
:rnorm(9)
-0.77482993685678 0.0965881713078849 -0.14713783099907 0.872082762958436 0.430324516204023 1.09693115216299 -1.08671165152439 0.0577277935967486 1.99238195515524
- Results Type
- Working with Graphics
Switching back to
:results value
so we don't get crap from the graphic export:library(tidyverse) rnorm(9) %>% hist()
We can see that this gives us a popup, which we don't really want, instead, let's deal with an inline image, previously I was able to acheive this by using
:results output graphics
, that's since stopped working, it would probably better to just bypass the brokenorg-babel
bullshit and deal with it all from R, it's not as nice but theres not much I can do about that.library("ggplot2") # Using SVG is also an option, but LaTeX sucks. svg(filename="pipe.svg") # Give the filename of the plot and a Description plotname="chocolatemouselamp" description= "Just a test to get =org-babel= plots" # Export the Plot into the working directory png(filename=paste0(plotname, ".png")) print(qplot(mpg, wt, data = mtcars)) dev.off() # Print the =org-mode= link syntax print(paste0( "\n", "Output:", "\n", "[[./", plotname, ".png", "]]"))
Output:
Footnotes:
Yes I've been patient, no it doesn't work for me.
Atleast easily in a fashion I could make work
This is used by Notes.vim
A variable would be quicker than a file because it's stored in memory, I did a file when I was playing in the terminal using for
loops rather than pipes
and it just made it's way into the script I'm using, there is a TODO next to it but the whole script needs to be rewritten anyway.
This is why using descriptive file names is important, with all notes in one directory it will be necessary to have unique file names, but using a sample of 1000 words and never repeating a word and not using the same 3 words in two files there will be \(\binom{1000}{3} > 10^6\) different combinations, so there is no need to use a UUID.
I got this idea from the Github Wiki
ranger
crashes all the time though, there's some bug with the way the
directories are mounted and vim, for example vim can only change into that
directory after being loaded, so vim -c 'cd 00tmsutags'
is fine but
vim 00tmsutags
is not fine.
You might want to start a python server for this with python3 -m https.server 8392