A good while ago I made peace with the fact that the natural thing for some Elm modules is to grow quite large. Many folk have recommended putting sign posts like the below as navigational aids. Indeed, a well-labeled file is much like a directory of smaller files. Just a different way of organizing data.
-- PARSER
-- ERROR HANDLER
What I wanted to say here is that there is one additional small step which can be helpful: add a table of contents. Here is one for a project I am working on at the moment:
--| Table Contents
--| PARSELOOP
--| Recovery Data and Handlers
--| EXPRESSION PARSER
--| Errors
--| Text
--| Math
--| Macro
--| OptArg
--| Arg
--| Environment
--| SOURCE MAP
--| HELPERS
--| Loop
--| Many
--| Many2
Of course, it wouldnât do to compile this table by hand, so we contrive a shell script to do the work:
# File: tc-list.sh
grep '^\-\- ' $1 | sed 's/--/--|/'
Then we can say sh tc-list.sh src/Parser/Parser.elm to get our table of contents. If you wish, it can be pasted into your document. Because each line begins with --| followed by a space instead of -- followed by a space, the table of contents will not be listed twice when you run the script.
Velociraptor
I like to use velociraptor to run scripts. It is light-weight, unlike npm. Velociraptor is configured using a scripts.yaml file, like this:
# File: scripts.yaml
scripts:
make: elm make app/Main.elm --output=app/public/Main.js
look: open -a /Applications/Firefox.app app/public/index.html
cloc: cloc --by-file src/ # list lines of code per file
yes: git log --after=`date -v-1d +%F` --oneline # yesterday: show commits in the last 24 hrs
yess: git log --after=`date -v-1d +%F` # the same, but more verbose
tc: sh scripts/tc-list.sh $1 # make table of contents
I do something similar to this, but I use explicit folds in Vim, which makes it look very similar to your table of contents when I open the file. You define a fold like this:
Sorry for potentially derailing the thread, but I think the following is relevant to the topic title. (Also sorry for sounding Vim-snobbish. Iâm trying to write this from the perspective of learning about othersâ text editor usage patterns instead.)
It feels to me like âsign postsâ are useful to folks if they search for things via scrolling through the file linearly.
I am used to navigating files via /<search_term> and * in Vim (âsearch for occurence of this stringâ and âsearch for occurence of string under cursorâ) â in your browser, you might emulate this via F3<search_term> and double-click + Ctrl-C + F3 + Ctrl-V; in IDEs I imagine folks have Ctrl+click to navigate to a definition/usage.
Those two navigating primitives (/ and *) have largely removed my need to scroll through a file. That makes it roughly the same perception-wise to me to work with small files and large files (our largest Elm file has 6362 lines). It also makes it irrelevant to me whether a definition is above one that uses it, or below it (which I remember being a pain point to some colleagues who navigated via scrolling).
I wonder, does the scrolling navigation style have some kind of advantage compared to the âjump to stringâ approach? Or is it just the way thatâs most accessible to people âout of the boxâ, so thatâs how folks do it?
EDIT: I realized what I write might be only relevant to âworking with your own known codebaseâ. Perhaps if I was forced to work with othersâ large modules, Iâd like to scroll through them too
I sometimes scroll to the top, select the exposed name and then âCMD+Dâ to select the next instance which a lot of the times is the definition. A lot of the time I use the find feature.
Sublime Text also has an overview of the file and I can quickly scroll to some places by the general shape and color. For example, the update is quite easy to spot due to the Msg being one block of purple.
+1 for searching code rather than scrolling, however I think there are other advantages to being able to mark up sections. One thing I like is to be able to narrow my view to only what Iâm focusing on at the moment.
Visual Studio used to have this feature for VB.net code, where you could mark up âRegionsâ (as well as namespaces) in a file and navigate/fold/focus them. This was considered an anti-pattern by the community because, you guessed it, it encouraged large files, however it was certainly better than just using comments to organize a class.
I use emacs, and we have a feature called ânarrowâ which allows you to only display part of a file - itâs especially great in org-mode where you can focus completely on one section of a document at a time. In emacs itâs rather easy to cobble together something to narrow/widen or fold based on an arbitrary pattern. However I think that having a community standard method of marking up âSectionsâ of code would be nice, and of course allow this to happen across files and editors.
Iâve gotten used to /^name : and /type TypeName and /type alias TypeName = for finding the definitions (also /case msg of for locating the update function ). If youâre diligent about writing type annotations for your top level definitions, this works nearly all the time.
There was a thread I came across in my Twitter feed about Navigate your code like it's 2021 - Austin Z. Henley. Seems like an interesting tool, but what really caught my eye in the Twitter thread itself was a discussion around does it matter if youâre viewing things vertically or horizontally? This came up when someone responded talking about the PL theyâre building where your app exists entirely in 1 tall file. This in turn reminded me that Iâd love to use the Outline panel in VSCode but donât because then I canât see my files which I also often want to see when navigating code. Additionally it feels very dense. Itâd be interesting, if possible, to combine the Outline view with @jxxcarlsonâs table of contents approach.