Navigating Large Elm Modules

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.


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
--| Recovery Data and Handlers
--| Errors
--| Text
--| Math
--| Macro
--| OptArg
--| Arg
--| Environment
--| 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:
grep '^\-\- ' $1 | sed 's/--/--|/'

Then we can say 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.


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


  make: elm make  app/Main.elm --output=app/public/Main.js

  look: open -a /Applications/ 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/ $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:

-- {{{ MODEL

type alias Model = Int

-- }}}

So when I open a file, it looks like this:

I’ve been doing this since I started using Elm and I think that’s why having longer files has never really bothered me.


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 :upside_down_face:


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. :slight_smile:

1 Like

+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 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.

1 Like

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 :smiley: ). If you’re diligent about writing type annotations for your top level definitions, this works nearly all the time.

1 Like

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.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.