├── .gitignore
├── LICENSE
├── README.md
├── config.toml
├── content
├── about.md
├── book
│ └── _index.md
├── concurrency
│ ├── _index.md
│ ├── example
│ │ ├── _index.md
│ │ └── tla
│ │ │ ├── await_macro.tla
│ │ │ ├── if_macro.tla
│ │ │ ├── init.tla
│ │ │ ├── limit_process.tla
│ │ │ ├── with_delay.tla
│ │ │ └── with_reserves.tla
│ ├── invariants.md
│ ├── labels.md
│ ├── procedures-and-macros.md
│ └── processes
│ │ ├── _index.md
│ │ └── tla
│ │ ├── fail1.tla
│ │ ├── fail2.tla
│ │ ├── in.tla
│ │ ├── pass1.tla
│ │ └── processes.tla
├── introduction
│ ├── _index.md
│ ├── about-this-guide.md
│ └── example
│ │ ├── _index.md
│ │ ├── img
│ │ ├── Error Stack.png
│ │ ├── basic_transfer.png
│ │ ├── if_screenshot.png
│ │ ├── intro_toolbox.png
│ │ ├── make_spec.png
│ │ ├── model.png
│ │ ├── model_assert_fail.png
│ │ ├── model_moneyinvariant1.png
│ │ ├── model_moneyinvariant2.png
│ │ ├── model_moneyinvariant_fail.png
│ │ ├── multiprocess_fail.png
│ │ └── translated.png
│ │ └── tla
│ │ ├── 3.tla
│ │ ├── 4.tla
│ │ ├── 5.tla
│ │ ├── 6.tla
│ │ ├── 7.tla
│ │ ├── 8.tla
│ │ ├── assertion.tla
│ │ └── init.tla
├── models
│ ├── _index.md
│ ├── constants
│ │ ├── _index.md
│ │ ├── img
│ │ │ ├── edit.png
│ │ │ ├── show.png
│ │ │ └── solution.png
│ │ └── tla
│ │ │ ├── constants.tla
│ │ │ ├── hanoi.tla
│ │ │ └── sensical.tla
│ ├── example
│ │ ├── _index.md
│ │ ├── img
│ │ │ └── failure.png
│ │ └── tla
│ │ │ ├── market.tla
│ │ │ ├── market2.tla
│ │ │ └── trade.tla
│ └── model-values
│ │ ├── _index.md
│ │ └── img
│ │ └── null.png
├── pluscal
│ ├── _index.md
│ ├── a-simple-spec.md
│ ├── behaviors
│ │ ├── _index.md
│ │ └── tla
│ │ │ ├── gates.tla
│ │ │ └── gates2.tla
│ └── toolbox
│ │ ├── _index.md
│ │ └── img
│ │ ├── error_trace.png
│ │ ├── invariant.png
│ │ ├── model_overview.png
│ │ └── model_run.png
├── reference
│ ├── _index.md
│ ├── expressions.md
│ ├── structure
│ │ ├── _index.md
│ │ └── tla
│ │ │ └── structure.tla
│ └── types.md
├── techniques
│ ├── _index.md
│ ├── cond-steps.md
│ ├── history.md
│ ├── img
│ │ ├── depth-first.png
│ │ └── state-constraint.png
│ ├── infinite-loops.md
│ ├── merging-functions.md
│ ├── model-values.md
│ └── performance.md
├── temporal-logic
│ ├── _index.md
│ ├── operators
│ │ ├── _index.md
│ │ └── livelock.png
│ ├── termination
│ │ ├── _index.md
│ │ ├── img
│ │ │ ├── stuttering.png
│ │ │ └── termination.png
│ │ └── tla
│ │ │ ├── fairness.tla
│ │ │ └── finish.tla
│ └── usage
│ │ └── _index.md
└── tla
│ ├── _index.md
│ ├── expressions.md
│ ├── functions.md
│ ├── logic.md
│ ├── operators.md
│ ├── sets.md
│ └── tuples
│ ├── _index.md
│ ├── img
│ └── solution.png
│ └── tla
│ └── hanoi.tla
├── layouts
├── index.html
├── partials
│ ├── custom-footer.html
│ ├── footer.html
│ ├── logo.html
│ ├── menu-footer.html
│ └── script.html
└── shortcodes
│ ├── ans.html
│ ├── code.html
│ └── q.html
├── staging-content
├── example-specs
│ └── _index.md
└── patterns
│ └── messages.md
├── static
├── css
│ ├── bootstrap.css
│ ├── hugo-theme.css
│ └── theme.css
└── js
│ └── bootstrap.min.js
└── themes
└── hugo-theme-learn
├── .commit
├── LICENSE.md
├── README.md
├── archetypes
├── chapter.md
└── default.md
├── exampleSite
├── LICENSE.md
├── config.toml
├── content
│ ├── _index.en.md
│ ├── _index.fr.md
│ ├── basics
│ │ ├── _index.en.md
│ │ ├── _index.fr.md
│ │ ├── configuration
│ │ │ ├── _index.en.md
│ │ │ └── _index.fr.md
│ │ ├── installation
│ │ │ ├── _index.en.md
│ │ │ ├── _index.fr.md
│ │ │ └── images
│ │ │ │ └── chapter.png
│ │ ├── requirements
│ │ │ ├── _index.en.md
│ │ │ ├── _index.fr.md
│ │ │ └── images
│ │ │ │ └── magic.gif
│ │ └── style-customization
│ │ │ ├── _index.en.md
│ │ │ ├── _index.fr.md
│ │ │ └── images
│ │ │ ├── blue-variant.png
│ │ │ ├── green-variant.png
│ │ │ └── red-variant.png
│ ├── cont
│ │ ├── _index.en.md
│ │ ├── _index.fr.md
│ │ ├── archetypes.en.md
│ │ ├── archetypes.fr.md
│ │ ├── i18n
│ │ │ ├── _index.en.md
│ │ │ ├── _index.fr.md
│ │ │ └── images
│ │ │ │ └── i18n-menu.gif
│ │ ├── markdown.en.md
│ │ ├── markdown.fr.md
│ │ ├── menushortcuts.en.md
│ │ ├── menushortcuts.fr.md
│ │ └── pages
│ │ │ ├── _index.en.md
│ │ │ ├── _index.fr.md
│ │ │ └── images
│ │ │ ├── frontmatter-icon.png
│ │ │ ├── pages-chapter.png
│ │ │ └── pages-default.png
│ ├── credits.en.md
│ ├── credits.fr.md
│ ├── shortcodes
│ │ ├── _index.en.md
│ │ ├── _index.fr.md
│ │ ├── attachments.en.files
│ │ │ ├── BachGavotteShort.mp3
│ │ │ ├── Carroll_AliceAuPaysDesMerveilles.pdf
│ │ │ ├── adivorciarsetoca00cape.pdf
│ │ │ ├── hugo.png
│ │ │ └── movieselectricsheep-flock-244-32500-2.mp4
│ │ ├── attachments.en.md
│ │ ├── attachments.fr.files
│ │ │ ├── BachGavotteShort.mp3
│ │ │ ├── Carroll_AliceAuPaysDesMerveilles.pdf
│ │ │ ├── adivorciarsetoca00cape.pdf
│ │ │ ├── hugo.png
│ │ │ └── movieselectricsheep-flock-244-32500-2.mp4
│ │ ├── attachments.fr.md
│ │ ├── button.en.md
│ │ ├── button.fr.md
│ │ ├── children
│ │ │ ├── _index.en.md
│ │ │ ├── _index.fr.md
│ │ │ ├── children-1
│ │ │ │ ├── _index.en.md
│ │ │ │ ├── _index.fr.md
│ │ │ │ └── children-1-1
│ │ │ │ │ ├── _index.en.md
│ │ │ │ │ ├── _index.fr.md
│ │ │ │ │ └── children-1-1-1
│ │ │ │ │ ├── _index.en.md
│ │ │ │ │ ├── _index.fr.md
│ │ │ │ │ └── children-1-1-1-1
│ │ │ │ │ ├── _index.en.md
│ │ │ │ │ ├── _index.fr.md
│ │ │ │ │ └── children-1-1-1-1-1
│ │ │ │ │ ├── _index.en.md
│ │ │ │ │ └── _index.fr.md
│ │ │ ├── children-2
│ │ │ │ ├── _index.en.md
│ │ │ │ ├── _index.fr.md
│ │ │ │ ├── test3.en.md
│ │ │ │ └── test3.fr.md
│ │ │ ├── children-3
│ │ │ │ ├── _index.en.md
│ │ │ │ └── _index.fr.md
│ │ │ ├── children-4
│ │ │ │ ├── _index.en.md
│ │ │ │ └── _index.fr.md
│ │ │ ├── test.en.md
│ │ │ └── test.fr.md
│ │ ├── expand.en.md
│ │ ├── expand.fr.md
│ │ ├── mermaid.en.md
│ │ ├── mermaid.fr.md
│ │ ├── notice.en.md
│ │ ├── notice.fr.md
│ │ ├── siteparam.en.md
│ │ └── siteparam.fr.md
│ ├── showcase.en.md
│ └── showcase.fr.md
├── layouts
│ ├── partials
│ │ ├── custom-footer.html
│ │ ├── logo.html
│ │ └── menu-footer.html
│ └── shortcodes
│ │ └── ghcontributors.html
└── static
│ ├── css
│ └── theme-mine.css
│ ├── fonts
│ ├── monogramos-webfont.eot
│ ├── monogramos-webfont.svg
│ ├── monogramos-webfont.ttf
│ ├── monogramos-webfont.woff
│ └── monogramos-webfont.woff2
│ └── images
│ └── showcase
│ └── tat.png
├── i18n
├── en.toml
└── fr.toml
├── images
├── screenshot.png
└── tn.png
├── layouts
├── 404.html
├── _default
│ ├── list.html
│ └── single.html
├── index.html
├── index.json
├── partials
│ ├── custom-footer.html
│ ├── custom-header.html
│ ├── favicon.html
│ ├── footer.html
│ ├── header.html
│ ├── logo.html
│ ├── menu-footer.html
│ ├── menu.html
│ ├── meta.html
│ ├── search.html
│ └── toc.html
└── shortcodes
│ ├── attachments.html
│ ├── button.html
│ ├── children.html
│ ├── expand.html
│ ├── mermaid.html
│ ├── notice.html
│ ├── ref.html
│ ├── relref.html
│ └── siteparam.html
├── static
├── css
│ ├── auto-complete.css
│ ├── featherlight.min.css
│ ├── font-awesome.min.css
│ ├── hugo-theme.css
│ ├── hybrid.css
│ ├── nucleus.css
│ ├── perfect-scrollbar.min.css
│ ├── theme-blue.css
│ ├── theme-green.css
│ ├── theme-red.css
│ └── theme.css
├── fonts
│ ├── FontAwesome.otf
│ ├── Inconsolata.eot
│ ├── Inconsolata.svg
│ ├── Inconsolata.ttf
│ ├── Inconsolata.woff
│ ├── Novecentosanswide-Normal-webfont.eot
│ ├── Novecentosanswide-Normal-webfont.svg
│ ├── Novecentosanswide-Normal-webfont.ttf
│ ├── Novecentosanswide-Normal-webfont.woff
│ ├── Novecentosanswide-Normal-webfont.woff2
│ ├── Novecentosanswide-UltraLight-webfont.eot
│ ├── Novecentosanswide-UltraLight-webfont.svg
│ ├── Novecentosanswide-UltraLight-webfont.ttf
│ ├── Novecentosanswide-UltraLight-webfont.woff
│ ├── Novecentosanswide-UltraLight-webfont.woff2
│ ├── Work_Sans_200.eot
│ ├── Work_Sans_200.svg
│ ├── Work_Sans_200.ttf
│ ├── Work_Sans_200.woff
│ ├── Work_Sans_200.woff2
│ ├── Work_Sans_300.eot
│ ├── Work_Sans_300.svg
│ ├── Work_Sans_300.ttf
│ ├── Work_Sans_300.woff
│ ├── Work_Sans_300.woff2
│ ├── Work_Sans_500.eot
│ ├── Work_Sans_500.svg
│ ├── Work_Sans_500.ttf
│ ├── Work_Sans_500.woff
│ ├── Work_Sans_500.woff2
│ ├── fontawesome-webfont.eot
│ ├── fontawesome-webfont.svg
│ ├── fontawesome-webfont.ttf
│ ├── fontawesome-webfont.woff
│ └── fontawesome-webfont.woff2
├── images
│ ├── clippy.svg
│ ├── favicon.png
│ └── gopher-404.jpg
├── js
│ ├── auto-complete.js
│ ├── clipboard.min.js
│ ├── featherlight.min.js
│ ├── highlight.pack.js
│ ├── html5shiv-printshiv.min.js
│ ├── hugo-learn.js
│ ├── jquery-2.x.min.js
│ ├── jquery.sticky-kit.min.js
│ ├── learn.js
│ ├── lunr.min.js
│ ├── modernizr.custom.71422.js
│ ├── perfect-scrollbar.jquery.min.js
│ ├── perfect-scrollbar.min.js
│ └── search.js
└── mermaid
│ ├── mermaid.css
│ ├── mermaid.dark.css
│ ├── mermaid.forest.css
│ └── mermaid.js
├── theme.toml
└── wercker.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | public/
2 | *~
3 | .DS_Store
4 | .htpasswd
5 | .vscode
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **THIS HAS BEEN REPLACED BY https://github.com/hwayne/learntla-v2/**
2 |
3 | This is the source code used to build the site [Learn TLA+](http://www.learntla.com). The guide is aimed at beginners to formal method who want to use it for simple (but useful!) specifications. "Keep the server from exploding", not "Keep the spaceship from exploding".
4 |
5 | ### Setup
6 |
7 | 1. Clone repo
8 | 2. Get [Hugo](https://gohugo.io/)
9 | 3. Run with `hugo server` (on port 1313)
10 | 4. Either set up my [sad depressing Pygments plugin](https://github.com/hwayne/tla-pygments) or set `PygmentsCodeFences` to false in `config.toml`
11 |
--------------------------------------------------------------------------------
/config.toml:
--------------------------------------------------------------------------------
1 | languageCode = "en-us"
2 | baseurl = "http://learntla.com"
3 | title = "Learn TLA+"
4 | theme = "hugo-theme-learn"
5 | googleAnalytics = "UA-90708265-1"
6 | pygmentsUseClassic = true
7 | PygmentsCodeFences = true
8 |
9 | [Params]
10 | Author = "Hillel Wayne"
11 | disableSearch = true
12 | disableInlineCopyToClipBoard = true
13 | disableAssetsBusting = true
14 |
--------------------------------------------------------------------------------
/content/about.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "About"
3 | +++
4 |
5 | This is an introductory guide for TLA+ (Temporal Logic of Actions), a specification language used for writing code blueprints.
6 |
7 | ### About the Author
8 |
9 | I have a personal site at [hillelwayne.com](http://hillelwayne.com) I never update and a [Twitter account](https://twitter.com/Hillelogram) I never use.
10 |
--------------------------------------------------------------------------------
/content/book/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Book"
3 | weight = 800
4 | +++
5 |
6 |
7 | I am delighted to announce that my book, [Practical TLA+](https://www.apress.com/us/book/9781484238288), is now available!
8 |
9 | _Practical TLA+_ is the spiritual sequel to _Learn TLA+_. It's designed for the same audience, people who are unfamiliar with formal methods but could benefit from using it at work. Part two is where the book really shines: it's all about _using_ TLA+. It covers all sorts of different approaches, techniques, and pitfalls to writing specs. Everything from fleshing out abstract specs to modeling adversarial agents to why you always want a `TypeInvariant`.
10 |
11 | The book is also designed to be _accessible_. My technical editor and I went through the book together, line by line, making sure every explanation was clear and every step was explained. On average, we spent a half hour on each page. I honestly believe this is the best introduction to TLA+ available.
12 |
13 | Of course, you're already at a free, beginner-focused resource for TLA+, one I'm still incredibly proud of. I think it's worth talking about how the two resources relate to each other.
14 |
15 | ### FAQ
16 |
17 | **What makes this different from _Learn TLA+_?**
18 |
19 | _Practical TLA+_ is much more comprehensive. It covers the same material with greater depth, properly explains temporal logic, and actually talks about the module system. More importantly, it focuses much more on how to _use_ TLA+. The second half of the book is packed with applications, techniques, and large scale examples. To give a sense of scale, the last two proper chapters are each about a single spec. Those two chapters combined are about as long as _the entirety_ of _Learn TLA+_.
20 |
21 | Most importantly, I wrote _Learn TLA+_ as I was, well, _learning_ TLA+. I wrote _Practical TLA+_ with two more years of experience with writing specs, teaching people, and communicating the ideas. I think it shows in the quality of the text.
22 |
23 | On the other hand, _Learn TLA+_ is free and has exercises in it. Tradeoffs!
24 |
25 | **What's happening to _Learn TLA+_?**
26 |
27 | _Learn TLA+_ will always be freely available online. In fact, I'm planning two more big updates to it. The first will clean up any confusing parts and correct any technical errors. I'm about halfway through that and hope to have it finished relatively soon. The second will be adding the option to switch between P-syntax (the current style) and C-syntax. That's a little further out.
28 |
29 | Past that I plan to let _Learn TLA+_ stand on its own. I will still be reviewing pull requests, of course, if people want to [contribute fixes or additions](https://github.com/hwayne/learntla). Ultimately I see it being a shared project of the community. I wrote it because I believe free, online documentation is critical to the success of any project, and _Learn TLA+_ will stay that way.
30 |
31 | **If I've already read _Learn TLA+_, how should I read _Practical TLA+_?**
32 |
33 | Read the introduction so you know how to set up the PT module. Chapter 1 uses the same introductory example here and can be skipped. Chapters 2, 3, and 5 cover similar ground as the website, but more carefully and with more detail. Skim these if you feel comfortable with the basics. Chapter 4 is new material: in addition to constants and model values, it also has using multiple modules in a project and parameterization. Chapter 6 is a much better treatment of temporal logic than the site currently has.
34 |
35 | Chapters 7-12 are entirely new material.
36 |
--------------------------------------------------------------------------------
/content/concurrency/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Concurrency"
3 | weight = 400
4 | +++
5 |
6 | This chapter will cover _concurrent systems_: ones where multiple processes, sharing a global state, run simultaneously. As a simple example of a concurrent system, you have one model and three different kinds of jobs that can affect the state of that model, all running in an asynchronous worker pool. How do you guarantee that just the right ordering of run jobs doesn’t cause data to somehow break?
7 |
8 | Reasoning about concurrent systems gets intractable quickly, which is why we get a model checker to reason about it for us.
9 |
--------------------------------------------------------------------------------
/content/concurrency/example/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Example: Rate Limiting"
3 | weight = 7
4 | +++
5 |
6 | ## The Problem
7 |
8 | As part of your project, you need to call a third party API. There are two types of calls you need to make:
9 |
10 | 1. A GET for a collection of objects. Each call will return some results and, potentially, a pagination token.
11 | 1. A GET for a single object, followed by, if necessary, a PUT to update it.
12 |
13 | There is a known rate limit of N calls per unit of time on this API, and you do not want to exceed this. The first type may make an arbitrary number of calls, but it's less critical and you are comfortable waiting between calls. For the second, it will make either 1 or 2 calls; however, being higher priority, you want to _immediately_ update the object if necessary. With these constraints in mind, how do you guarantee you never exceed the rate limit?
14 |
15 | ### Initial Design
16 |
17 | We start with the minimum possible case.
18 |
19 | {{% code init %}}
20 |
21 | Since most of the business logic is irrelevant to our use case, we simply leave it out. `get_collection` makes an arbitrary number of calls, represented by the `either goto`. Every time TLC reaches that branch point it will explore both branches, so we know this can be an arbitrary number of calls. Similarly, the `get_put` makes either one or two calls in a transaction. Finally, every time the `made_calls` changes we check that we haven't gone over the maximum.
22 |
23 | If we run this, we'll get an error: the assert fails pretty trivially. We can fix this by adding a check in the macro, so that we only make a call if we have enough rate left. One fix is this:
24 |
25 | {{% code if_macro %}}
26 |
27 | Which makes the call fail silently if it would take us past the limit.
28 |
29 | ### Deadlocks
30 |
31 | Our solution works, but misses the business case: we don't want to not make the calls, we want to _wait_ on them until the rate limit refreshes. We can simulate that with an _await_:
32 |
33 | {{% code await_macro %}}
34 |
35 | If we run this, though, we get a deadlock. That's because all of our processes are waiting for the limit to refresh, which we never actually coded. Here's one way of doing this:
36 |
37 | {{% code limit_process %}}
38 |
39 | If we add that, the spec passes as normal.
40 |
41 | ### Asynchronous Workers
42 |
43 | Let's add a complication: all of the processes are running on different workers, so they don't automatically know the number of calls made. In order to avoid going past the limit, we need to share that information, which takes time. One way we can do this is by having each process query a central cache that only move forward if there's enough calls remaining. One representation would be
44 |
45 | {{% code with_delay %}}
46 |
47 | When we run this, we see it fails, as between the get and the request another process can make a call. If we want to resolve this we need some form of locking or priority. This will work, but it also explodes the diameter. Every process needs to wait on every other process, even when there's plenty of calls to go around. We should instead look for a more optimized way of handling this issue.
48 |
49 | ### Semaphores
50 |
51 | One solution we can use is to reserve calls: when a process checks that there are calls remaining, it reserves N calls that are considered made in our cache but not in the API endpoint. Then, once we make the appropriate calls, we return the necessary reserves.
52 |
53 | {{% code with_reserves %}}
54 |
--------------------------------------------------------------------------------
/content/concurrency/example/tla/await_macro.tla:
--------------------------------------------------------------------------------
1 | macro make_calls(n)
2 | begin
3 | await made_calls <= max_calls - n;
4 | made_calls := made_calls + n;
5 | assert made_calls <= max_calls;
6 | end macro;
7 |
--------------------------------------------------------------------------------
/content/concurrency/example/tla/if_macro.tla:
--------------------------------------------------------------------------------
1 | macro make_calls(n)
2 | begin
3 | if made_calls <= max_calls - n then
4 | made_calls := made_calls + n;
5 | assert made_calls <= max_calls;
6 | end if;
7 | end macro;
8 |
--------------------------------------------------------------------------------
/content/concurrency/example/tla/init.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE api ----
2 | EXTENDS Integers, TLC
3 | (* --algorithm api
4 | variables made_calls = 0, max_calls \in 5..10;
5 |
6 | macro make_calls(n)
7 | begin
8 | made_calls := made_calls + n;
9 | assert made_calls <= max_calls;
10 | end macro;
11 |
12 | process get_collection = 0
13 | begin
14 | Request:
15 | make_calls(1);
16 | either goto Request
17 | or skip
18 | end either;
19 | end process;
20 |
21 | process get_put \in 1..3
22 | begin
23 | Call:
24 | with c \in {1, 2} do
25 | make_calls(c)
26 | end with;
27 | end process;
28 |
29 | end algorithm; *)
30 | ====
31 |
--------------------------------------------------------------------------------
/content/concurrency/example/tla/limit_process.tla:
--------------------------------------------------------------------------------
1 | process reset_limit = -1
2 | begin
3 | Reset:
4 | while TRUE do
5 | made_calls := 0;
6 | end while
7 | end process
8 |
--------------------------------------------------------------------------------
/content/concurrency/example/tla/with_delay.tla:
--------------------------------------------------------------------------------
1 | EXTENDS Integers, TLC
2 | (* --algorithm api
3 | variables made_calls = 0, max_calls \in 5..10;
4 |
5 | macro make_calls(n)
6 | begin
7 | made_calls := made_calls + n;
8 | assert made_calls <= max_calls;
9 | end macro;
10 |
11 | process reset_limit = -1
12 | begin
13 | Reset:
14 | while TRUE do
15 | made_calls := 0;
16 | end while
17 | end process
18 |
19 |
20 | process get_collection = 0
21 | begin
22 | GCGetCalls:
23 | await made_calls <= max_calls - 1;
24 | Request:
25 | make_calls(1);
26 | either goto GCGetCalls
27 | or skip
28 | end either;
29 | end process;
30 |
31 | process get_put \in 1..3
32 | begin
33 | GPGetCalls:
34 | await made_calls <= max_calls - 2;
35 | Call:
36 | with c \in {1, 2} do
37 | make_calls(c)
38 | end with;
39 | end process;
40 |
41 | end algorithm; *)
42 |
--------------------------------------------------------------------------------
/content/concurrency/example/tla/with_reserves.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE api ----
2 | EXTENDS Integers, TLC
3 | (* --algorithm api
4 | variables made_calls = 0, max_calls \in 5..10, reserved_calls = 0;
5 |
6 |
7 | macro make_calls(n) begin
8 | made_calls := made_calls + n;
9 | assert made_calls <= max_calls;
10 | end macro;
11 |
12 |
13 | macro reserve(n) begin
14 | await made_calls + reserved_calls + n <= max_calls;
15 | reserved_calls := reserved_calls + n;
16 | end macro
17 |
18 | process reset_limit = -1
19 | begin
20 | Reset:
21 | while TRUE do
22 | made_calls := 0;
23 | end while
24 | end process
25 |
26 | process get_collection = 0
27 | begin
28 | GCGetCalls:
29 | reserve(1);
30 | Request:
31 | make_calls(1);
32 | reserved_calls := reserved_calls - 1;
33 | either goto GCGetCalls
34 | or skip
35 | end either;
36 | end process;
37 |
38 | process get_put \in 1..3
39 | begin
40 | GPGetCalls:
41 | reserve(2);
42 | Call:
43 | with c \in {1, 2} do
44 | make_calls(c)
45 | end with;
46 | reserved_calls := reserved_calls - 2;
47 | end process;
48 |
49 | end algorithm; *)
50 |
--------------------------------------------------------------------------------
/content/concurrency/invariants.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Concurrent Invariants"
3 | weight = 4
4 | +++
5 |
6 | Sometimes, we want to enforce invariants _between_ processes. For example, only one thread may have a lock at the same time, or the total values across all processes must be less than a certain threshold. Here's one example:
7 |
8 | ``` tla
9 | process foo \in 1..2
10 | variable x \in 1..2
11 | begin
12 | Skip:
13 | skip
14 | end process
15 | ```
16 |
17 | How do we assert the variant "the sum of x between the two processes is not 4?" With a single process algorithm, we could write `x /= 4`. But to do the same with multiple processes, we have to let the PlusCal abstraction leak.
18 |
19 | When we translate an algorithm, TLA+ will create all of the corresponding variables. When we have multiple processes, TLA+ will instead create a function with a domain on the process identifiers and the range the actual values of x per process. So instead of having for example `x \in 1..2`, we instead have `x == [ProcSet -> 1..2]`. So in this case, the appropriate invariant is `x[1] + x[2] /= 4`.
20 |
--------------------------------------------------------------------------------
/content/concurrency/labels.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Labels"
3 | weight = 3
4 | +++
5 |
6 | ### Valid Labels
7 |
8 | Since labels represent steps, single moments of time, there are some rules on how you have to place them.
9 |
10 | - The first line in a process has to have a label. That includes the first `begin` if it's a single-process algorithm.
11 |
12 | ```
13 | begin
14 | Foo:
15 | skip;
16 | ```
17 |
18 | - A label must come before a `while` statement.
19 |
20 | ```
21 | Foo:
22 | while FALSE do
23 | skip;
24 | end while;
25 | ```
26 |
27 | - A label must come right after a `call`, `return`, or `goto`.
28 |
29 | ```
30 | A:
31 | skip;
32 | B:
33 | goto A;
34 | Foo: \* this one is necessary even if it's never reached
35 | skip;
36 | ```
37 |
38 | - If you have a control statement, such as `if` or `either`, and one possible branch has a label in it, then the whole control structure must be followed with a label.
39 |
40 | ```
41 | either
42 | A:
43 | skip;
44 | or
45 | skip;
46 | end either;
47 | Foo: \* Necessary because of the A label
48 | ```
49 |
50 | - You cannot put labels in a `with` statement.
51 |
52 | ```
53 | with x \in {1, 2} do
54 | Foo: \* INVALID
55 | skip
56 | end with;
57 | ```
58 |
59 | - You cannot assign to any given variable more than once in a label.
60 |
61 | ```
62 | Foo:
63 | x := 1;
64 | q := 2; \* VALID
65 |
66 | Bar:
67 | x := 1;
68 | x := 2; \* INVALID
69 | ```
70 |
71 | Sometimes this can cause issues: for example, switching two variables, or assigning to different records of the same structure. In these cases you can use `||` to chain assignments: `x := y || y := x;`.
72 |
73 | ### Optimization
74 |
75 | Every label specifies a branch point in your system: any process with an available label can run as the next step. For N processes with M sequential labels the total number of behaviors is `(MN)!/M!^N`, not counting initial states or nondeterministic labels (`either` or `with`). The more labels you have, the more exact your concurrency testing. The fewer labels you have, the faster your model will run. As always, there are tradeoffs.
--------------------------------------------------------------------------------
/content/concurrency/processes/tla/fail1.tla:
--------------------------------------------------------------------------------
1 | variables x = 0;
2 | process one = 1
3 | begin
4 | A:
5 | x := x - 1;
6 | B:
7 | x := x * 3;
8 | end process
9 |
10 | process two = 2
11 | begin
12 | C:
13 | x := x + 1;
14 | D:
15 | assert x /= 0;
16 | end process
17 |
--------------------------------------------------------------------------------
/content/concurrency/processes/tla/fail2.tla:
--------------------------------------------------------------------------------
1 | (* --algorithm foo
2 | variables x = 0;
3 | process cycle \in 1..3
4 | begin
5 | A:
6 | x := x + 1;
7 | B:
8 | x := 0;
9 | C:
10 | assert x /= 2;
11 | end process
12 | end algorithm; *)
13 |
--------------------------------------------------------------------------------
/content/concurrency/processes/tla/in.tla:
--------------------------------------------------------------------------------
1 | process p \in 1..3
2 | variable x \in 1..4
3 | begin
4 | A:
5 | skip
6 | end process;
7 |
--------------------------------------------------------------------------------
/content/concurrency/processes/tla/pass1.tla:
--------------------------------------------------------------------------------
1 | process one = 1
2 | begin
3 | A:
4 | x := x - 1;
5 | B:
6 | x := x * 3;
7 | end process
8 |
9 | process two = 2
10 | begin
11 | C:
12 | await x < -1;
13 | x := x + 1;
14 | D:
15 | assert x /= 0;
16 | end process
17 |
--------------------------------------------------------------------------------
/content/concurrency/processes/tla/processes.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE module_name ----
2 | \* TLA+ code
3 |
4 | (* --algorithm algorithm_name
5 | variables global_variables
6 |
7 | process p_name = foo
8 | variables local_variables
9 | begin
10 | \* pluscal code
11 | end process
12 |
13 | process p_group \in bar \* set
14 | variables local_variables
15 | begin
16 | \* pluscal code
17 | end process
18 |
19 | end algorithm; *)
20 | ====
21 |
--------------------------------------------------------------------------------
/content/introduction/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Introduction"
3 | weight = 1
4 | +++
5 |
6 | {{% notice note %}}
7 | I now have a [book available](/book)! You can check it out [here](https://www.apress.com/us/book/9781484238288) and read more about it [here](/book).
8 | {{% /notice %}}
9 | ### What is TLA+?
10 |
11 | TLA+ is a _formal specification language_. It's a tool to design systems and algorithms, then programmatically verify that those systems don't have critical bugs. It's the software equivalent of a blueprint.
12 |
13 | ### Why should I use it?
14 |
15 | Here's a simple TLA+ specification, representing people trading unique items. Can you find the bug?
16 |
17 | ```tla
18 | People == {"alice", "bob"}
19 | Items == {"ore", "sheep", "brick"}
20 | (* --algorithm trade
21 | variable owner_of \in [Items -> People]
22 |
23 | process giveitem \in 1..3 \* up to three possible trades made
24 | variables item \in Items,
25 | owner = owner_of[item],
26 | to \in People,
27 | origin_of_trade \in People
28 | begin Give:
29 | if origin_of_trade = owner then
30 | owner_of[item] := to;
31 | end if;
32 | end process;
33 | end algorithm; *)
34 | ```
35 |
36 | Since we check that the owner of an item is the one trading it away, we should be safe against scams, right? But if we run the model checker, we find that's not true: Alice could trade an item to _herself_ and, before that process finishes running, resolve a parallel trade giving that same item to Bob. Then the first trade resolves and Alice gets the item back. Our algorithm fails for race conditions, and we know this because TLA+ explored every possible state and timeline.
37 |
38 | There's a few different ways of fixing this. But does our fix work for more than two people? In TLA+, checking that is as simple as `People == {"alice", "bob", "eve"}`. Does it work if we can trade multiple items at once? `variable items \in SUBSET Items`. What about if there's multiple sheep, ore, and bricks? `amount_owned = [People \X Items -> 0..5]`. What if three people are all trading 1 ore and 1 sheep with each of the other players while Eve also trades Alice 0 brick? If it's in the possible state space, TLA+ will check it.
39 |
40 | ### Is it hard to use?
41 |
42 | Formal methods have a reputation for being difficult to the point where they're only worth it for critical systems. This means that all of the guides are written under the assumption that the reader is working on a critical system, where they have to know TLA+ inside and out to make absolutely sure that their system won't accidentally _kill people_.
43 |
44 | If a dangerous bug to you is "somebody dies", then yes, formal methods are hard. If a dangerous bug to you is "nobody dies but our customers get really mad and we have to spend two weeks tracking down and fixing the bug", then the small subset of TLA+ you'll need is actually pretty easy to learn. Just find a beginner-friendly guide and you're all set.
45 |
46 | ### Where's a beginner-friendly guide?
47 |
48 | Hello! This guide covers the basics of TLA+ in an easy, hands-on way. If you want to start from the beginning, you can learn more about what we'll cover [here](about-this-guide). If you want to dive in right away, why not try a [whirlwind tour](example)?
49 |
50 | Either way, welcome to TLA+!
51 |
--------------------------------------------------------------------------------
/content/introduction/about-this-guide.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "About This Guide"
3 | weight = 3
4 | +++
5 |
6 | This guide focuses on the bare minimum required to get you up and running as fast as possible as well as some intermediate techniques to improve your models. This approach will ignore or skim over the vast majority of TLA+ in order to make that small chunk easier to learn. This doesn't mean the other parts boring, difficult, or useless. Far from it. But they're outside the scope of this guide.
7 |
8 | I'm assuming you have the following background:
9 |
10 | * __You're an experienced programmer.__ This is not an introduction to programming, and TLA+ is not a user-friendly tool.
11 | * __You're familiar with testing.__ If you haven't used unit tests before, that'll be a lot more useful than learning this.
12 | * __You know some math.__ TLA+ borrows heavily from mathematical structures and syntax. If you've heard of de Morgan's laws, know what a set is, and can understand what `(P => Q) => (~Q => ~P)` means, you're fine. Otherwise, this should still be accessible but might be a little less intuitive.
13 |
14 | __You need to download the [TLA+ Toolbox](https://github.com/tlaplus/tlaplus/releases/latest).__ You should also have access to the following resources:
15 |
16 | * [The PlusCal Manual](https://lamport.azurewebsites.net/tla/p-manual.pdf): PlusCal is the algorithmic interface to TLA+. We'll be covering everything about it in this guide, but it's nice to have a complete grammar reference. We will be using the p-version of the manual.
17 | * [The TLA+ Cheat Sheet](http://lamport.azurewebsites.net/tla/summary-standalone.pdf): Exactly what it sounds like. Includes syntax for things out of this guide's scope.
18 | * [Specifying Systems](https://research.microsoft.com/en-us/um/people/lamport/tla/book.html): _Specifying Systems_ was written by Leslie Lamport, the inventor of TLA+, and remains the most comprehensive book on the subject. It's a lot more advanced than this guide is, but you should know it exists.
19 |
20 | {{% notice info %}}
21 | As of version 1.5.4 the TLA+ Toolbox bundles all of these files under "help".
22 | {{% /notice %}}
23 |
--------------------------------------------------------------------------------
/content/introduction/example/img/Error Stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/Error Stack.png
--------------------------------------------------------------------------------
/content/introduction/example/img/basic_transfer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/basic_transfer.png
--------------------------------------------------------------------------------
/content/introduction/example/img/if_screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/if_screenshot.png
--------------------------------------------------------------------------------
/content/introduction/example/img/intro_toolbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/intro_toolbox.png
--------------------------------------------------------------------------------
/content/introduction/example/img/make_spec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/make_spec.png
--------------------------------------------------------------------------------
/content/introduction/example/img/model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/model.png
--------------------------------------------------------------------------------
/content/introduction/example/img/model_assert_fail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/model_assert_fail.png
--------------------------------------------------------------------------------
/content/introduction/example/img/model_moneyinvariant1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/model_moneyinvariant1.png
--------------------------------------------------------------------------------
/content/introduction/example/img/model_moneyinvariant2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/model_moneyinvariant2.png
--------------------------------------------------------------------------------
/content/introduction/example/img/model_moneyinvariant_fail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/model_moneyinvariant_fail.png
--------------------------------------------------------------------------------
/content/introduction/example/img/multiprocess_fail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/multiprocess_fail.png
--------------------------------------------------------------------------------
/content/introduction/example/img/translated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/translated.png
--------------------------------------------------------------------------------
/content/introduction/example/tla/3.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE transfer ----
2 | EXTENDS Naturals, TLC
3 |
4 | (* --algorithm transfer
5 | variables alice_account = 10, bob_account = 10, money \in 1..20;
6 |
7 | begin
8 | A: alice_account := alice_account - money;
9 | B: bob_account := bob_account + money;
10 | C: assert alice_account >= 0;
11 | end algorithm *)
12 | =====
13 |
--------------------------------------------------------------------------------
/content/introduction/example/tla/4.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE transfer ----
2 | EXTENDS Naturals, TLC
3 |
4 | (* --algorithm transfer
5 | variables alice_account = 10, bob_account = 10, money \in 1..20;
6 |
7 | begin
8 | Transfer:
9 | if alice_account >= money then
10 | A: alice_account := alice_account - money;
11 | B: bob_account := bob_account + money;
12 | end if;
13 | C: assert alice_account >= 0;
14 | end algorithm *)
15 | =====
16 |
--------------------------------------------------------------------------------
/content/introduction/example/tla/5.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE Transfer ----
2 | EXTENDS Naturals, TLC
3 |
4 | (* --algorithm transfer
5 | variables alice_account = 10, bob_account = 10, money \in 1..20;
6 |
7 | begin
8 | Transfer:
9 | if alice_account >= money then
10 | A: alice_account := alice_account - money;
11 | B: bob_account := bob_account + money;
12 | end if;
13 | C: assert alice_account >= 0;
14 |
15 | end algorithm *)
16 |
17 | \* BEGIN TRANSLATION
18 | \* Removed for clarity...
19 | \* END TRANSLATION
20 |
21 | MoneyNotNegative == money >= 0
22 |
23 | ====
24 |
25 |
--------------------------------------------------------------------------------
/content/introduction/example/tla/6.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE Transfer ----
2 | EXTENDS Naturals, TLC
3 |
4 | (* --algorithm transfer
5 | variables alice_account = 10, bob_account = 10, money \in 1..20,
6 | account_total = alice_account + bob_account;
7 |
8 | begin
9 | Transfer:
10 | if alice_account >= money then
11 | A: alice_account := alice_account - money;
12 | B: bob_account := bob_account + money;
13 | end if;
14 | C: assert alice_account >= 0;
15 |
16 | end algorithm *)
17 |
18 | MoneyNotNegative == money >= 0
19 | MoneyInvariant == alice_account + bob_account = account_total
20 |
21 | ====
22 |
23 |
--------------------------------------------------------------------------------
/content/introduction/example/tla/7.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE Transfer ----
2 | EXTENDS Naturals, TLC
3 |
4 | (* --algorithm transfer
5 | variables alice_account = 10, bob_account = 10, money \in 1..20,
6 | account_total = alice_account + bob_account;
7 |
8 | begin
9 | Transfer:
10 | if alice_account >= money then
11 | A: alice_account := alice_account - money;
12 | bob_account := bob_account + money; \* Both now part of A
13 | end if;
14 | C: assert alice_account >= 0;
15 |
16 | end algorithm *)
17 |
18 | MoneyNotNegative == money >= 0
19 | MoneyInvariant == alice_account + bob_account = account_total
20 |
21 | ====
22 |
23 |
--------------------------------------------------------------------------------
/content/introduction/example/tla/8.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE Transfer ----
2 | EXTENDS Naturals, TLC
3 |
4 | (* --algorithm transfer
5 | variables alice_account = 10, bob_account = 10,
6 | account_total = alice_account + bob_account;
7 |
8 | process Transfer \in 1..2
9 | variable money \in 1..20;
10 | begin
11 | Transfer:
12 | if alice_account >= money then
13 | A: alice_account := alice_account - money;
14 | bob_account := bob_account + money;
15 | end if;
16 | C: assert alice_account >= 0;
17 | end process
18 |
19 | end algorithm *)
20 |
21 | MoneyNotNegative == money >= 0
22 | MoneyInvariant == alice_account + bob_account = account_total
23 |
24 | ====
25 |
26 |
--------------------------------------------------------------------------------
/content/introduction/example/tla/assertion.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE transfer ----
2 | EXTENDS Naturals, TLC
3 |
4 | (* --algorithm transfer
5 | variables alice_account = 10, bob_account = 10, money = 5;
6 |
7 | begin
8 | A: alice_account := alice_account - money;
9 | B: bob_account := bob_account + money;
10 | C: assert alice_account >= 0;
11 | end algorithm *)
12 | =====
13 |
14 |
--------------------------------------------------------------------------------
/content/introduction/example/tla/init.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE transfer ----
2 | EXTENDS Naturals, TLC
3 |
4 | (* --algorithm transfer
5 | variables alice_account = 10, bob_account = 10, money = 5;
6 |
7 | begin
8 | A: alice_account := alice_account - money;
9 | B: bob_account := bob_account + money;
10 |
11 | end algorithm *)
12 | ====
13 |
--------------------------------------------------------------------------------
/content/models/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Models"
3 | weight = 300
4 | +++
5 |
6 | In the past few chapters, we covered how to write complex specifications. However, our models have always been fairly crude: drop an operator or expression into Invariants and check that it's satisfied. This is useful, but as you can probably guess by now, there's also a lot more we can do with them. This chapter will cover some of the tools TLC provides to manage larger and more complex models.
7 |
--------------------------------------------------------------------------------
/content/models/constants/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Constants"
3 | weight = 5
4 | +++
5 |
6 | Let's go back to our old [Hanoi solver](/tla/tuples/#example). As a refresher, this is the code we started with.
7 |
8 | {{% code hanoi %}}
9 |
10 | It works, but what if we wanted to change one of the parameters (more towers, more disks in a tower), we'd have to directly edit the code. It would be better to make a generic spec and test different parameters in the models instead. To do this, we introduce _constants_.
11 |
12 | {{% code constants %}}
13 |
14 | This is the same as the old code, except that we now define the tower in terms of constants. Instead of the spec assigning the constant a value, the model does instead.
15 |
16 | 
17 |
18 | When we click edit we can assign a specific value to each constant.
19 |
20 | 
21 |
22 |
23 | ### Assumptions
24 |
25 | What if we also wanted to vary the solution? For example, we all know that it's possible to move the entire tower over. But is it possible to reach `<<<<1, 2>>, <<>>, <<3, 4>>>>`? By moving the solution to a constant, we can vary that in the model, too:
26 |
27 | ``` tla
28 | CONSTANT SOLUTION
29 | \* ...
30 | assert tower /= SOLUTION
31 | ```
32 |
33 | And now we can put the new solution in an ordinary assignment:
34 |
35 | 
36 |
37 | One problem: this solution is nonsensical. It has four numbers when `TSIZE` is 3. In these cases, TLA+ can't find a solution because the solution isn't even defined! One way to catch this kind of error is with an `ASSUME` statement:
38 |
39 | {{% code sensical %}}
40 |
41 | TLC will check that our assignments don't break any of the `ASSUME` expressions, so we can use `ASSUME` to make sure nobody makes a bad model. Of course, it can only check what we remember to check: for example, a solution with two "5"s can still slip through. As always, with programming, be paranoid.
42 |
--------------------------------------------------------------------------------
/content/models/constants/img/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/models/constants/img/edit.png
--------------------------------------------------------------------------------
/content/models/constants/img/show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/models/constants/img/show.png
--------------------------------------------------------------------------------
/content/models/constants/img/solution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/models/constants/img/solution.png
--------------------------------------------------------------------------------
/content/models/constants/tla/constants.tla:
--------------------------------------------------------------------------------
1 | CONSTANTS TSIZE, TSPACES
2 |
3 | FullTower[n \in 1..TSIZE] == n \* <<1, 2, 3, ...>>
4 | Board[n \in 1..TSPACES] == IF n = 1 THEN FullTower ELSE <<>>
5 |
6 | (* --algorithm hanoi
7 | variables tower = Board;
8 |
9 | define
10 | D == DOMAIN tower
11 | end define;
12 |
13 | begin
14 | while TRUE do
15 | assert tower[TSPACES] /= FullTower;
16 | \* rest is the same
17 |
--------------------------------------------------------------------------------
/content/models/constants/tla/hanoi.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE hanoi ----
2 | EXTENDS TLC, Sequences, Integers
3 |
4 | (* --algorithm hanoi
5 | variables tower = <<<<1, 2, 3>>, <<>>, <<>>>>,
6 |
7 | define
8 | D == DOMAIN tower
9 | end define;
10 |
11 | begin
12 | while TRUE do
13 | assert tower[3] /= <<1, 2, 3>>;
14 | with from \in {x \in D : tower[x] /= <<>>},
15 | to \in {
16 | y \in D :
17 | \/ tower[y] = <<>>
18 | \/ Head(tower[from]) < Head(tower[y])
19 | }
20 | do
21 | tower[from] := Tail(tower[from]) ||
22 | tower[to] := <
> \o tower[to];
23 | end with;
24 | end while;
25 | end algorithm; *)
26 | ====
27 |
28 |
--------------------------------------------------------------------------------
/content/models/constants/tla/sensical.tla:
--------------------------------------------------------------------------------
1 | IsSensical(state) == /\ Len(state) = TSPACES \* Correct spaces
2 | /\ \A tower \in DOMAIN state: \* Numbers do not exceed TSIZE
3 | \A disc \in DOMAIN state[tower]:
4 | state[tower][disc] \in 1..TSIZE
5 | /\ \A n \in 1..TSIZE : \* All numbers appear
6 | \E tower \in DOMAIN state:
7 | \E disc \in DOMAIN state[tower]:
8 | n = state[tower][disc]
9 | \* ...
10 |
11 | ASSUME IsSensical(SOLUTION)
12 |
--------------------------------------------------------------------------------
/content/models/example/img/failure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/models/example/img/failure.png
--------------------------------------------------------------------------------
/content/models/example/tla/market.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE market ----
2 | EXTENDS Integers
3 | CONSTANTS Items, MaxPrice, Vendors, MaxActions
4 |
5 | I == Items
6 | V == Vendors
7 | P == 1..MaxPrice
8 |
9 | ValidMarkets == [V \X I -> [buy : P, sell : P]]
10 |
11 | (* --algorithm market
12 | variables market \in ValidMarkets,
13 | backpack = {}, \* items we have
14 | actions = 0,
15 | profit = 0;
16 |
17 | begin
18 | Act:
19 | while actions < MaxActions do
20 | either
21 | Buy:
22 | with v \in V, i \in Items \ backpack do
23 | profit := profit - market[<>].sell;
24 | backpack := backpack \union {i};
25 | end with;
26 | or
27 | Sell:
28 | with v \in V, i \in backpack do
29 | profit := profit + market[<>].buy;
30 | backpack := backpack \ {i};
31 | end with;
32 | end either;
33 | Loop:
34 | actions := actions + 1;
35 | end while;
36 | end algorithm; *)
37 |
38 | \* Translation
39 |
40 | NoArbitrage == profit <= 0
41 | ====
42 |
--------------------------------------------------------------------------------
/content/models/example/tla/market2.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE market ----
2 | EXTENDS Integers
3 | CONSTANTS Items, MaxPrice, Vendors, MaxActions
4 |
5 | I == Items
6 | V == Vendors
7 | P == 1..MaxPrice
8 |
9 | ValidMarkets == LET Markets == [V \X I -> [buy : P, sell : P]]
10 | IN {m \in Markets :
11 | \A item \in I, vendors \in V \X V:
12 | m[<>].buy <= m[<>].sell
13 | }
14 |
15 | (* --algorithm market
16 | variables market \in ValidMarkets,
17 | backpack = {}, \* items we have
18 | actions = 0,
19 | profit = 0;
20 |
21 | begin
22 | Act:
23 | while actions < MaxActions do
24 | either
25 | Buy:
26 | with v \in V, i \in Items \ backpack do
27 | profit := profit - market[<>].sell;
28 | backpack := backpack \union {i};
29 | end with;
30 | or
31 | Sell:
32 | with v \in V, i \in backpack do
33 | profit := profit + market[<>].buy;
34 | backpack := backpack \ {i};
35 | end with;
36 | end either;
37 | Loop:
38 | actions := actions + 1;
39 | end while;
40 | end algorithm; *)
41 |
42 | \* Translation
43 |
44 | NoArbitrage == profit <= 0
45 | ====
46 |
--------------------------------------------------------------------------------
/content/models/example/tla/trade.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE market ----
2 | EXTENDS Integers, FiniteSets
3 | CONSTANTS Items, MaxPrice, Vendors, MaxActions
4 |
5 | I == Items
6 | V == Vendors
7 | P == 1..MaxPrice
8 |
9 | ValidMarkets == LET Markets == [V \X I -> [buy : P, sell : P]]
10 | IN {m \in Markets :
11 | \A item \in I, vendors \in V \X V:
12 | m[<>].buy <= m[<>].sell
13 | }
14 |
15 | ValidTrades == [{ i \in SUBSET I : Cardinality(i) > 1} -> I]
16 |
17 | (* --algorithm market
18 | variables market \in ValidMarkets,
19 | trades \in ValidTrades,
20 | backpack = {}, \* items we have
21 | actions = 0,
22 | profit = 0;
23 |
24 | begin
25 | Act:
26 | while actions < MaxActions do
27 | either
28 | Buy:
29 | with v \in V, i \in Items \ backpack do
30 | profit := profit - market[<>].sell;
31 | backpack := backpack \union {i};
32 | end with;
33 | or
34 | Sell:
35 | with v \in V, i \in backpack do
36 | profit := profit + market[<>].buy;
37 | backpack := backpack \ {i};
38 | end with;
39 | or
40 | Trade:
41 | with items \in (SUBSET backpack) \intersect (DOMAIN trades) do
42 | backpack := (backpack \ items) \union {trades[items]};
43 | end with;
44 | end either;
45 | Loop:
46 | actions := actions + 1;
47 | end while;
48 | end algorithm; *)
49 |
50 | \* Translation
51 |
52 | NoArbitrage == profit <= 0
53 | ====
54 |
--------------------------------------------------------------------------------
/content/models/model-values/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Model Values"
3 | weight = 10
4 | +++
5 |
6 | Up until now we've used three basic types of values: strings ("a"), numbers, and booleans. While these work, it doesn't scale very well. For example, if your spec has both students and teachers, you may want to enforce that no students are teaching other students. If you represent every student and teacher with a number, enforcing this quickly becomes painful.
7 |
8 | To resolve this, we have a fourth basic type: the model value. The only way to use it is to define a constant and then assign it such a value in the model overview. A constant with a "model value" is only equal to itself.
9 |
10 | ```
11 | CONSTANT NULL
12 | ```
13 |
14 | 
15 |
16 | We can also define a set of model values:
17 |
18 | ```
19 | \* Imagine this is a screenshot
20 | Apps <- [ model value ] {facebook, twitter, espark}
21 | Users <- [ model value ] {user1, user2}
22 | ```
23 |
24 | Once we define a set of model values, we can then use the elements of the set as part of other constants:
25 |
26 | ```
27 | \* This too
28 | StartingApp == facebook
29 | ```
30 |
31 | Emphasis on "other __constants__"; model values can't be referred to in your TLA+ spec itself. They're exclusively a model checker property.
32 |
33 | ### Symmetry Sets
34 |
35 | Imagine an extremely simple setup as follows:
36 |
37 | ``` tla
38 | CONSTANT Foos
39 | \* ...
40 | variables x \in Foos, y \in Foos;
41 | \* ...
42 | ```
43 |
44 | If Foos is the model set `{f1, f2, f3}`, that's nine possible starting states. To a rough approximation, your program will take nine times as long to finish as it would if `Foos` just had one element. That's comprehensive, but not always necessary.
45 |
46 | _Symmetry sets_ are one possible optimization you can make here. It tells TLC to ignore any states that are just permutations of model values of an existing state. `<> = <> = <> ...`, and `<> = <> = <>`. In this case, there are only two initial states: `x = y` and `x /= y`.
47 |
48 | In most cases, this is a safe optimization: all you care about are the similiarities and differences of values, not the exact values themselves. There are some cases where this can cause problems, though. If you ever use a model value in an ordinary assignment, it's possible to miss states that could violate safety invariants. And as we'll see later, combining temporal properties and symmetry sets is almost always a bad idea.
49 |
--------------------------------------------------------------------------------
/content/models/model-values/img/null.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/models/model-values/img/null.png
--------------------------------------------------------------------------------
/content/pluscal/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "PlusCal"
3 | weight = 100
4 | +++
5 |
6 | PlusCal is a tool for working with TLA+: it adds a pseudocode-like interface to the specs, making them easier for programmers to understand. While not every interesting spec can be written with PlusCal, quite a few can, and it's a great entry point into modelling. All of the specs we'll write over the course of this guide will run with PlusCal at the core.
7 |
--------------------------------------------------------------------------------
/content/pluscal/behaviors/tla/gates.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE flags ----
2 | EXTENDS TLC, Integers
3 | (* --algorithm flags
4 | variables f1 \in BOOLEAN, f2 \in BOOLEAN, f3 \in BOOLEAN
5 | begin
6 | while TRUE do
7 | with f \in {1, 2, 3} do
8 | if f = 1 then
9 | either
10 | f1 := TRUE;
11 | or
12 | f1 := FALSE;
13 | end either;
14 | elsif f = 2 then
15 | either
16 | f2 := TRUE;
17 | or
18 | f2 := FALSE;
19 | end either;
20 | else
21 | either
22 | f3 := TRUE;
23 | or
24 | f3 := FALSE;
25 | end either;
26 | end if;
27 | end with;
28 | end while;
29 | end algorithm; *)
30 |
31 | ====
32 |
--------------------------------------------------------------------------------
/content/pluscal/behaviors/tla/gates2.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE flags ----
2 | EXTENDS TLC, Integers
3 | (* --algorithm flags
4 | variables flags \in [1..3 -> BOOLEAN], next = TRUE;
5 | begin
6 | while next do
7 | with f \in DOMAIN flags, n \in BOOLEAN do
8 | flags[f] := ~flags[f];
9 | next := n;
10 | end with;
11 | end while;
12 | end algorithm; *)
13 |
14 | ====
15 |
16 |
--------------------------------------------------------------------------------
/content/pluscal/toolbox/img/error_trace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/pluscal/toolbox/img/error_trace.png
--------------------------------------------------------------------------------
/content/pluscal/toolbox/img/invariant.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/pluscal/toolbox/img/invariant.png
--------------------------------------------------------------------------------
/content/pluscal/toolbox/img/model_overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/pluscal/toolbox/img/model_overview.png
--------------------------------------------------------------------------------
/content/pluscal/toolbox/img/model_run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/pluscal/toolbox/img/model_run.png
--------------------------------------------------------------------------------
/content/reference/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Appendix"
3 | weight = 700
4 | reference = true
5 | +++
6 |
7 | General reference materials, such as cheat sheets etc
8 |
--------------------------------------------------------------------------------
/content/reference/expressions.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Expressions"
3 | weight = 0
4 | +++
5 |
6 | ### Operators
7 |
8 | ```tla
9 | Add(a,b) == a + b
10 |
11 | Apply(Op(_,_), a) == Op(a, 3)
12 | Apply(Add, 5) = 8
13 |
14 | RECURSIVE IsOdd(_)
15 |
16 | IsOdd(n) == CASE n = 1 -> TRUE
17 | [] n = 0 -> FALSE
18 | [] OTHER -> ~IsOdd(n-1)
19 |
20 | IsOdd(3) = TRUE
21 | ```
22 |
23 | ### Expressions
24 |
25 | ```tla
26 | AddOrMult(a, b, add) == IF add
27 | THEN a + b
28 | ELSE a * b
29 | AddOrMult(4, 6, TRUE) = AddOrMult(2, 5, FALSE)
30 |
31 | SubtractSquares(a, b) ==
32 | LET sum == a + b
33 | diff == a - b
34 | IN sum * diff
35 | SubtractSquares(6, 4) = 20
36 |
37 | Bool(bool) ==
38 | LET op1 == LET op2 == LET op3 ==
39 | IF bool
40 | THEN TRUE ELSE
41 | FALSE IN
42 | op3 IN op2
43 | IN op1
44 | Bool(TRUE) = TRUE
45 | Bool(FALSE) = FALSE
46 | ```
47 |
48 | ### Logic
49 |
50 | ```tla
51 | (\E x \in {1, 2, 3} : x > 2) = TRUE
52 | (CHOOSE x \in {1, 2, 3} : x > 2) = 3
53 | (CHOOSE x \in {1, 2, 3} : x <= 2) = \* 1 or 2, deterministic, always the same
54 |
55 | (\A x \in {1, 2, 3} : x > 4) = FALSE
56 | (CHOOSE x \in {1, 2, 3} : x > 4) = \* error
57 |
58 | EvenSquare(n) ==
59 | /\ n % 2 = 0
60 | /\ \E x \in 1..n : x*x = n
61 |
62 | EvenSquareOrOdd(n) ==
63 | \/ /\ n % 2 = 0
64 | /\ \E x \in 1..n : x*x = n
65 | \/ n % 2 = 1
66 |
67 | EvenSquareOrOddNonsquare(n) ==
68 | (\E x \in 1..n : x*x = n) <=> (n % 2 = 0)
69 | ```
--------------------------------------------------------------------------------
/content/reference/structure/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Structure of a Spec"
3 | weight = 2
4 | +++
5 |
6 | {{% code structure %}}
7 |
--------------------------------------------------------------------------------
/content/reference/structure/tla/structure.tla:
--------------------------------------------------------------------------------
1 | pluscal options
2 | ---- MODULE name_of_file ----
3 | (* import statements *)
4 | EXTENDS , , ...
5 |
6 | (*
7 | Constants are values that are dependent on the particular model.
8 | All constants must be specified for the model to run.
9 | *)
10 | CONSTANTS , , ... \* CONSTANT also works
11 | ASSUME \* Optional. If Expression is false, model cannot run.
12 | ASSUME \* ASSUME expression can only depend on constants
13 |
14 | RECURSIVE \* recursive operators must be declared in advance
15 |
16 | Op ==
17 | Op(a, b, c) ==
18 | Op(op2(_), a) == \* Syntax to use a higher-order operator
19 |
20 | (* --algorithm
21 | \* variables global to algorithm
22 | variables v1 = ,
23 | v2 \in , \* v2 can be any element in the set
24 | v3 \in ; \* All <> possibilities will be tested
25 |
26 | \* Any operators in a define block can reference PlusCal variables
27 | define
28 | Op ==
29 | end define;
30 |
31 | macro Macro(, ...)
32 | begin
33 |
34 | end macro;
35 |
36 | procedure Procedure(, )
37 | variables proc_v1 = , ... \* no \in
38 | begin
39 |
40 | return;
41 | end procedure;
42 |
43 | (*
44 | Each process has a value. All values must be comparable
45 | Inside a process you can retrieve its value with `self`
46 | *)
47 | process Single_Process =
48 | variables v1 = , v2 \in ; \* local to process
49 | begin
50 |
51 | end process;
52 |
53 | \* making a process fair means it cannot 'stutter', or stall out.
54 | fair process Process \in \* one process per element
55 | variables v1 \in ; \* similar processes can choose different elements
56 | begin
57 |
58 | end process;
59 |
60 | (* For a single process system, instead of processes you do
61 |
62 |
63 |
64 |
65 | begin
66 |
67 | end algorithm; *)
68 |
69 | end algorithm; *)
70 |
71 | ====
72 |
73 |
--------------------------------------------------------------------------------
/content/reference/types.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Data Types"
3 | weight = 1
4 | +++
5 |
6 | ## Primitives
7 |
8 | ### Boolean
9 |
10 | TRUE, FALSE.
11 |
12 | ```
13 | BOOLEAN = {TRUE, FALSE}
14 | ```
15 |
16 | ### Numbers
17 |
18 | 1, -1, -2, etc. You need to `EXTENDS Integers` to perform arithmetic operations.
19 |
20 | ### Strings
21 |
22 | "a", "b", "ab", etc.
23 |
24 | ### Model Values
25 |
26 | Defined in the model options. Only assignable to constants. A model value is unequal to anything but itself.
27 |
28 | ## Sets
29 |
30 | ```tla
31 | {"a", "bc"} = {"a", "bc"}
32 |
33 | S == {1, 2, 3}
34 |
35 | 3 \in S = TRUE; 4 \in S = FALSE;
36 | {2, 3} \subseteq S = TRUE; {2, 4} \subseteq S = FALSE
37 |
38 | S \union {3, 4} = {1, 2, 3, 4}
39 | S \intersect {3, 4} = {3}
40 | S \ {3, 4} = {1, 2}
41 |
42 | UNION {{1}, {2}} = {1, 2}
43 | SUBSET {1, 2} = {{}, {1}, {2}, {1, 2}}
44 |
45 | EXTENDS Integers
46 | 1..3 = S
47 |
48 | {x*x : x \in S} = {1, 4, 9}
49 | {x*y : x \in S, y \in S} = {1, 2, 3, 4, 6, 9}
50 |
51 | {x \in S : x >= 2} = {3}
52 | {<> \in S \X S : x + y > 4} = {<<2, 3>>, <<3, 2>> <<3, 3>>}
53 |
54 | EXTENDS FiniteSets
55 | IsFiniteSet(S) = TRUE
56 | Cardinality(S) = 3
57 | ```
58 |
59 | ## Functions
60 |
61 | ```tla
62 | S == {1, 2, 3}
63 |
64 | F(S) == [x \in S |-> x + 1]
65 | F(1..10)[4] = 5
66 |
67 | F(S) == [x \in S, y \in S |-> x + y]
68 | F(1..10)[2, 3] = 5
69 | F(1..10)[<<2, 3>>] = 5
70 |
71 | F[x \in 1..10] == x + 1
72 | F[2] = 3
73 |
74 | DOMAIN [x \in S |-> P(x)] = S
75 |
76 | [{1, 2} -> BOOLEAN] = {
77 | <>, <>,
78 | <>, <>
79 | }
80 | ```
81 |
82 | ## Tuples
83 |
84 | All function operations also apply to tuples. A tuple has domain 1..N, where N is the length of the tuple.
85 |
86 | ```tla
87 | T == <<"a", "b">>
88 |
89 | DOMAIN T = 1..2
90 | <<"a", "b">>[1] = "a"
91 |
92 | {1, 2} \X T = {
93 | <<1, "a">>, <<1, "b">>,
94 | <<2, "a">>, <<2, "b">>
95 | }
96 |
97 | EXTENDS Sequences
98 | T == <<"a", "b", "c", "d">>
99 |
100 | Len(T) = 4
101 | Head(T) = "a"
102 | Tail(T) = <<"b", "c", "d">>
103 |
104 | <<"e">> \o T = <<"e", "a", "b", "c", "d">>
105 | Append(T, "e") = <<"a", "b", "c", "d", "e">>
106 | SubSeq(T, 2, 3) = <<"b", "c">>
107 | SelectSeq(T, LAMBDA x: x \in {"a", "d"}) = <<"a", "d">>
108 | ```
109 |
110 | ## Structures
111 |
112 | All function operations also apply to structures. The domain is the set of strings corresponding to the structure's keys.
113 |
114 | ```tla
115 | S == [a |-> 1, b |-> 2]
116 | DOMAIN S = {"a", "b"}
117 | S['a'] = 1
118 | S.b = 2
119 |
120 | [a: {1, 2}, b: {"x", "y"}] =
121 | {
122 | [a |-> 1, b |-> "x"], [a |-> 1, b |-> "y"],
123 | [a |-> 2, b |-> "x"], [a |-> 2, b |-> "y"]
124 | }
125 | ```
126 |
127 | ## Bags
128 |
129 | See [Specifying Systems](https://lamport.azurewebsites.net/tla/book.html).
130 |
--------------------------------------------------------------------------------
/content/techniques/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Techniques"
3 | weight = 600
4 | +++
5 |
6 | While TLA+ is a powerful tool, it does not provide a lot of guidance on how to write good specifications. This section will cover some of the problems you might run into with your specs, as well as ways around them.
7 |
--------------------------------------------------------------------------------
/content/techniques/cond-steps.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Conditional Steps"
3 | weight = 1
4 | +++
5 |
6 | Sometimes you may want to combine `either` with labels, so that branching steps are possible. For example:
7 |
8 | ```
9 | either
10 | Push:
11 | \* code
12 | or
13 | Pop:
14 | \* code
15 | end either
16 | After:
17 | \* code
18 | ```
19 |
20 | However, you may also want some steps to only be possible in certain cases. For example, we might want that we can only pop a non-empty stack. Here are two ways of doing that:
21 |
22 | ```
23 | either
24 | Push:
25 | \* code
26 | or
27 | if stack_not_empty() then
28 | Pop:
29 | \* code
30 | end if
31 | end either
32 | After:
33 | \* code
34 | ```
35 |
36 | ```
37 | either
38 | Push:
39 | \* code
40 | or
41 | await stack_not_empty()
42 | Pop:
43 | \* code
44 | end either
45 | After:
46 | \* code
47 | ```
48 |
49 | While the both will prevent you from running `Pop` if `stack_not_empty` is false, they mean different things for the rest of your system. Here's how TLC interprets each of them:
50 |
51 | * _If Case_: TLC can run either the first or second branch. In the second branch, it checks the conditional, sees that the conditional is false, and then jumps to the end of the if block. So on reaching the `either`, TLC checks two behaviors: "go to `Push`" or "skip to `After`".
52 | * _Await Case_: In order run the second branch, `stack_not_empty` must be true. Since it's false, the second branch can't run, meaning only the first branch is possible. So there is only one possible behavior: "go to `Push`".
53 |
54 | In other words, in the `if` spec, depending on the state of the stack, there are three possible behaviors: `Push->After`, `Pop->After`, and `After`. In the `await` spec, there's only `Push->After` and `Pop->After`. Generally, the latter is what you want, so you should use `await` in this case unless you're sure that the skipping the `either` is something you want.
55 |
56 | One thing that **does not** work is putting the `await` in `Pop`:
57 |
58 | ```
59 | either
60 | Push:
61 | \* code
62 | or
63 | Pop:
64 | await stack_not_empty()
65 | \* code
66 | end either
67 | After:
68 | \* code
69 | ```
70 | This is because there's nothing stopping TLC from _reaching_ Pop; the `await` only matters afterwards. In this case, if the stack is empty, there's no way for TLC to run the `Pop` step and no other processes to run instead, so this is a deadlock.
71 |
72 | All of this, of course, assumes this is a single-process system. In a multiprocess system, other processes may potentially alter the stack, so `Pop` is not an automatic deadlock.
73 |
74 | ## Conditional Processes
75 |
76 | We can also guard a process in the same way:
77 |
78 | ```tla
79 | await condition;
80 | call process;
81 | ```
82 |
83 | Similar to above, we can't put the `await` inside the process.. So we have to have an `await` every time we want to call the process, which is error prone. While we can't avoid this, we can ensure that we raise an error if we miss the guard:
84 |
85 | ```tla
86 | process p()
87 | begin
88 | P:
89 | assert condition;
90 | \* code
91 | end
92 | ```
93 | We still need to manually include the `await` statements, but if we forget the assertion fails and spec is broken.
--------------------------------------------------------------------------------
/content/techniques/history.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Multistep Invariants"
3 | weight = 3
4 | +++
5 |
6 | If we want to check an invariant only after a specific action, we can use `assert`. But what if we want to check an invariant only after a specific sequence of actions? For example, if we move forward and then backwards, we should be in the same position as we started. TLA+ doesn't provide a native way to test those, but we can use sequences to write our own.
7 |
8 | Let's begin with some framework code:
9 |
10 | ```tla
11 | variables xpos = 0, t = 0
12 | begin
13 | Move:
14 | while t < 10 do
15 | either
16 | xpos := xpos + 1
17 | or
18 | xpos := xpos - 1
19 | end either;
20 | t := t + 1;
21 | end while;
22 | ```
23 |
24 | In order to test our invariant, we need some way of knowing the previous action, as well as how it changed the position. We can do this by adding a "history" variable, and then appending the last action and state with each step. In the following example, the history variable is named `actions`.
25 |
26 | ```tla
27 | EXTENDS Integers, TLC, Sequences
28 | CONSTANTS EAST, WEST, INIT
29 |
30 | Action(action, state) == [action |-> action, state |-> state]
31 |
32 | (* --algorithm alg
33 | variables
34 | xpos = 0,
35 | t = 0,
36 | action = INIT
37 | actions = <>;
38 |
39 | begin
40 | Move:
41 | while t < 10 do
42 | either
43 | xpos := xpos + 1;
44 | action := EAST;
45 | or
46 | xpos := xpos - 1;
47 | action := WEST;
48 | end either;
49 | actions := Append(actions, Action(action, xpos));
50 | t := t + 1;
51 | end while;
52 | end algorithm; *)
53 | ```
54 |
55 | Our invariant is now definable over pairs of the most recent action.
56 |
57 | ```tla
58 | define MoveInvariant ==
59 | IF Len(actions) > 2 THEN \* require two after init
60 | LET
61 | len == Len(actions)
62 | recent == SubSeq(actions, len-2, len)
63 | from == recent[1].state
64 | to == recent[3].state
65 | a == <>
67 | IN CASE
68 | a = <> -> TRUE
69 | []a = <> -> from = to
70 | []a = <> -> from = to
71 | []a = <> -> TRUE
72 | ELSE TRUE
73 | end define;
74 | ```
75 |
76 | {{% notice note %}}
77 | We could have replaced two of the cases with `[] OTHERWISE -> TRUE`, but by enumerating them explicitly, any missed cases will raise an error. Pattern matching!
78 | {{% /notice %}}
79 |
80 | ### Advanced Cases
81 |
82 | With a full history, we can also write more sophisticated invariants. For example, in this case, we don't need to compare the last two actions, since we can operate over the whole history:
83 |
84 | ```tla
85 | MoveInvariant ==
86 | LET count(token) ==
87 | Len(SelectSeq(actions, LAMBDA y: y.action = token))
88 | IN xpos = count(EAST) - count(WEST)
89 | ```
90 |
91 | ### Limitations
92 |
93 | Multistep invariants get clunky when you have multiple processes, since you have to store the state, action, and process. Additionally, it gets less useful when applying invariants to complex states.
94 |
--------------------------------------------------------------------------------
/content/techniques/img/depth-first.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/techniques/img/depth-first.png
--------------------------------------------------------------------------------
/content/techniques/img/state-constraint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/techniques/img/state-constraint.png
--------------------------------------------------------------------------------
/content/techniques/infinite-loops.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Infinite Loops"
3 | weight = 11
4 | +++
5 |
6 | Infinite loops are useful to model, as they are a great way of representing things like cronjobs or worker pools. You can add infinite loops in the same way as any other language, by using `while` or `goto`.
7 |
8 | ```tla
9 | process whileprocess = "while"
10 | begin While:
11 | while TRUE do
12 | skip
13 | end while
14 | end process
15 |
16 | process gotoprocess = "goto"
17 | begin Goto:
18 | skip;
19 | goto Goto;
20 | end process;
21 | ```
22 |
23 | There are two specific problems with using infinite loops in TLA+. The first is that if the infinite loop produces a state change, TLC might try to check an infinite state space. The second is that it makes checking termination harder: your program is done when everything _but_ the infinite loop has terminated.
24 |
25 | ### State Space Restriction
26 |
27 | If we try to check the following spec, TLC will run out of memory:
28 |
29 | ```
30 | variable x = 0;
31 | begin Adder:
32 | while TRUE do
33 | x := x + 1;
34 | end while
35 | end algorithm;
36 | ```
37 |
38 | There's an infinite number of possible states here: `x = 1`, `x = 2`, etc. The naive way of fixing this would be to add a time counter:
39 |
40 | ```
41 | variable x = 0, time = 0;
42 | begin Adder:
43 | while time < 10 do
44 | x := x + 1;
45 | time := time + 1;
46 | end while
47 | end algorithm;
48 | ```
49 |
50 | However, this can quickly get untenable. Another options is to use the regular loops and switch to a depth-first search. This lets you force the model to terminate in a finite number of steps.
51 | 
52 |
53 | The last option is to use a state constraint. A state constraint is a formula restricting the possible states: When a state does not comply with the constraint, model will finish running.
54 | 
55 |
56 | One pitfall with depth-first search and state constraint is that your model might have an error, but you don't reach it in the specified time.
57 |
--------------------------------------------------------------------------------
/content/techniques/merging-functions.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Merging Functions"
3 | weight = 1.5
4 | +++
5 |
6 | In addition to general debugging tools, extending TLC adds two function operators:
7 |
8 | * `a :> b` is the function `[x \in {a} |-> b]`, or the function that maps a to b.
9 | * `f1 @@ f2` merges both functions into a new one with the same domain and values. If some element is in both domains, it uses f1.
10 |
11 | `@@` in particular is a great tool for simplifying PlusCal specs. As a toy example, imagine we have a sequence of digits and want to count the number of occurrences of each digit. Here's one way to write that:
12 |
13 | ```tla
14 | EXTENDS TLC, Integers, Sequences, FiniteSets
15 |
16 | Digits == 0..9
17 | Count(seq) ==
18 | [x \in Digits |-> Cardinality({y \in DOMAIN seq: seq[y] = x})]
19 |
20 | (* --algorithm counter
21 |
22 | variables seq \in [1..5 -> Digits],
23 | counter = [x \in Digits |-> 0],
24 | pos = 1;
25 |
26 | begin
27 | while pos <= Len(seq) do
28 | counter[seq[pos]] := counter[seq[pos]] + 1;
29 | pos := pos + 1;
30 | end while;
31 | assert counter = Count(seq);
32 | end algorithm; *)
33 | ```
34 |
35 | That works, but what if instead of a sequence of digits, it was a sequence of sets of digits? The solution gets a little messy (and the state space is much larger):
36 |
37 | ```tla
38 | Digits == 0..2
39 | Count(seq) ==
40 | [x \in Digits |-> Cardinality({y \in DOMAIN seq: x \in seq[y]})]
41 |
42 | (* --algorithm counter
43 |
44 | variables seq \in [1..5 -> SUBSET Digits],
45 | counter = [x \in Digits |-> 0],
46 | pos = 1;
47 |
48 | begin
49 | while pos <= Len(seq) do
50 | counter := [
51 | x \in Digits |->
52 | IF x \in seq[pos]
53 | THEN counter[x] + 1
54 | ELSE counter[x]
55 | ];
56 | pos := pos + 1;
57 | end while;
58 | assert counter = Count(seq);
59 | end algorithm; *)
60 | ```
61 |
62 | With `@@`, we can make the assignment much cleaner:
63 |
64 | ```tla
65 | counter := [x \in seq[pos] |-> counter[x] + 1] @@ counter;
66 | ```
--------------------------------------------------------------------------------
/content/techniques/model-values.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Using Model Values"
3 | weight = 2
4 | +++
5 |
6 | When should you be using model values instead of strings and numbers? The main advantage of model values is they compare false to everything but themselves. If `M` is a model value, `M = 0`, `M = "0"`, and `M = {0}` are all false. In contrast, `0 = "0"` isn't false. It's an error in your spec.
7 |
8 | In theory, you'll never want to compare two incomparables. In practice, we sometimes need to work around limitations in TLA+. As a good rule of thumb, if you're not directly processing strings as part of your system, **prefer model values to strings**.
9 |
10 | ### Processes
11 |
12 | How do we represent N clients and one server? The following way seems reasonable, but it fails:
13 |
14 | ```tla
15 | process clients \in 1..N
16 | process server = 1
17 | ```
18 |
19 | The problem here is that each process must be assigned to a separate value, and 1 is used twice. We could instead assign `server = 0`, but that just hides the problem. We might try to use a string instead, like this:
20 |
21 | ```tla
22 | process clients \in 1..N
23 | process server = "server"
24 | ```
25 |
26 | But this also fails: 1 and "server" are not comparable. However, if we instead use a model value for server, it's valid:
27 |
28 | ```tla
29 | process clients \in 1..N
30 | process server = Server
31 | ```
32 |
33 | ### Sets
34 |
35 | If a value could be true, false, or unknown, how do we best represent it? For two of those we'd want to use booleans, however "unknown" is a string and can't be compare to booleans. Instead, we can write `{TRUE, FALSE, UNKNOWN}` and make `UNKNOWN` a model value.
36 |
37 | This is especially important when working with functions. A function's domain must be a set, and all elements in a set must be comparable to each other. So you can't have a function that mixes strings and numbers, but you can have one that mixes strings and model values.
38 |
39 | ## Sets of Model Values
40 |
41 | What about model sets? They're obviously useful in cases where we're using numbers just to distinguish processes. For example, the ideal way to write the server-client proccesses would be
42 |
43 | ```tla
44 | process clients \in Clients
45 | process server = Server
46 | ```
47 |
48 | Where `Clients = {c1, c2, ...}`. Why is this better than numbers? Aside from being easier to understand, it means you can make the set symmetrical. This, as mentioned before, makes your specs take considerably less time to run. This is true even outside of processes. For example, given the following simple algorithm:
49 |
50 | ```tla
51 | begin
52 | with x \in S do
53 | skip;
54 | end with;
55 | ```
56 |
57 | If `S = {1, 2, 3}`, then TLC will check three behaviors. If `S = {s1, s2, s3}` _and_ `S` is symmetric, TLC will check only one behavior and infer the rest. In cases where this is a safe assumption (no liveness tests), it's a good optimization.
--------------------------------------------------------------------------------
/content/techniques/performance.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Optimizing TLC"
3 | draft = true
4 | weight = 90
5 | +++
6 |
7 | One of the biggest challenges in specification is not writing the spec, but running it. Since TLC looks through the entire state space, TK
--------------------------------------------------------------------------------
/content/temporal-logic/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Temporal Properties"
3 | weight = 500
4 | +++
5 |
6 | When I said we were barely going to cover TLA+, I wasn't kidding.
7 |
8 | Temporal Properties are the heart and soul of TLA+. It's how the language does _anything_ in the first place. Which is why it's kind of depressing that I'm going to spend almost no time on it. That's because of PlusCal abstracts away most of it for us. This section explains a little bit of the parts we, as startup folk, might find useful, and assuage my guilt at not covering a pretty major part of the system.
9 |
--------------------------------------------------------------------------------
/content/temporal-logic/operators/livelock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/temporal-logic/operators/livelock.png
--------------------------------------------------------------------------------
/content/temporal-logic/termination/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Termination"
3 | weight = 0.5
4 | +++
5 |
6 | Will the following PlusCal snippet ever finish?
7 |
8 | {{% code finish %}}
9 |
10 | The most common temporal logic you'll want to check is _Termination_, and TLC provides a handy button to test just that.
11 |
12 | 
13 |
14 | This will succeed if, for all behaviors, the spec _ends_. Let's see what happens when we run this:
15 |
16 | 
17 |
18 | Well, that was certainly unexpected! This is called _stuttering_. The problem is that the system can choose not to run any step at all. This has never been a problem before because we were making sure things didn't break if time passed, but now things break if time doesn't pass.
19 |
20 | How do we get around this? What we want is something called _fairness_: the property that if a given label is always enabled, we will eventually run it. We make this happen by specifying the process as a `fair process`.
21 |
22 | {{% code fairness %}}
23 |
24 | Confirm this works as expected.
25 |
26 | {{% notice note %}}
27 | There's a way to enforce fairness for a single process app, but it's a bit finicky so I'm leaving it out.
28 | {{% /notice %}}
--------------------------------------------------------------------------------
/content/temporal-logic/termination/img/stuttering.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/temporal-logic/termination/img/stuttering.png
--------------------------------------------------------------------------------
/content/temporal-logic/termination/img/termination.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/temporal-logic/termination/img/termination.png
--------------------------------------------------------------------------------
/content/temporal-logic/termination/tla/fairness.tla:
--------------------------------------------------------------------------------
1 | EXTENDS TLC, Integers
2 |
3 | (* --algorithm counter
4 | variable x = 0;
5 |
6 | fair process counter = "counter"
7 | begin Count:
8 | while x < 10 do
9 | x := x + 1;
10 | end while;
11 | end process;
12 |
13 | end algorithm; *)
--------------------------------------------------------------------------------
/content/temporal-logic/termination/tla/finish.tla:
--------------------------------------------------------------------------------
1 | EXTENDS TLC, Integers
2 |
3 | (* --algorithm counter
4 | variable x = 0;
5 | begin
6 | while x < 10 do
7 | x := x + 1;
8 | end while;
9 | end algorithm; *)
10 |
--------------------------------------------------------------------------------
/content/temporal-logic/usage/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Using Temporal Properties"
3 | weight = 2
4 | +++
5 |
6 | Most often, you're not interested in checking temporal properties. If you are, though, here are some things to watch out for.
7 |
8 | ### Liveness is Slow
9 |
10 | It's easy to check that reachable states satisfy invariants. But to check liveness, _how you reach those states_ also matters. If a thousand routes lead through state S, that's 1,000 routes that need to be checked for liveness and only one state that needs to be checked for safety. So liveness is intrinsically much, _much_ slower than checking invariants.
11 |
12 | ### Temporal Properties are Very Slow
13 |
14 | The Toolbox has a number of optimizations to make it easier to check invariants: multithreading, model symmetry sets, cloud computing, etc. These all assume, though, that we only care about individual states. None of these apply to temporal properties. So it's even slower to check than you'd think at first.
15 |
16 | An especially important one to watch out for are symmetric models. TLC can check them for temporal properties. _However_, the symmetry properties can provide false negatives: it can say that your spec satisfies the properties when it actually doesn't.
17 |
18 | ### Stuttering and Fairness
19 |
20 | Regular processes can stutter. Sometimes this is part of what you expect in your system- maybe you can't rely on the message queue always being available. If not, though, you need to explicitly use `fair process`.
21 |
22 | ## Recommendations
23 |
24 | * Use separate models for invariants and temporal properties.
25 | * Use smaller sets of model values to check invariants than you do for temporal properties.
26 | * Consider testing the same temporal property among several models with different setups.
27 | * Do not use symmetric model sets when testing liveness.
28 |
--------------------------------------------------------------------------------
/content/tla/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "TLA+"
3 | weight = 200
4 | +++
5 |
6 | Now that we have our PlusCal scaffold, it's time to learn TLA+ proper. TLA+ is a mathematical description language. Instead of saying how to find the value you want, you instead say the properties of what you want. For example, the largest element of a set is `CHOOSE x \in S : \A y \in S : y <= x`. That's not an algorithm. It's just "the number that's bigger than the other numbers."
7 |
8 | This gives us incredible specification power. Complex properties and invariants can be expressed in just a few lines. On the downside, it can also be very intimidating. It's also possible to accidentally build uncheckable models. It's easy, for example, to define the set of all universal turing machines that halt. If you feed that into TLC, though, it will throw an error back. There's a bit of an art to writing TLA+ specs. Let's get started.
9 |
10 | Point of note: we're going to be almost completely ignoring the "temporal" part of "Temporal Logic of Actions". As a simple heuristic, we're never, _ever_ going to be talking about "primed and unprimed operators", which make up like 95% of _Specifying Systems._ At its core, TLA+ is a beautiful way to elegantly express the temporal properties of a complicated system. For our uses, TLA+ is a way of writing better PlusCal specs. Sacrilegious? Probably. Easier? Yup.
11 |
--------------------------------------------------------------------------------
/content/tla/expressions.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Expressions"
3 | weight = 2
4 | +++
5 |
6 | We've been implicitly using _expressions_ up until now; we just haven't clarified them. For our purposes, an expression is __anything that follows a `==`, `=`, `:=`, or `\in`__. In this section we'll cover some general expression modifiers.
7 |
8 | ### Logical Junctions
9 |
10 | We've used these for a while now: `/\` is "and", `\/` is "or". We can join expressions with them. The one subtlety is that this is the _only_ case where TLA+ is whitespace sensitive. If you start a line with an indented junction, TLA+ considers that the start of a subclause. For example,
11 |
12 | ```tla
13 | /\ TRUE
14 | \/ TRUE
15 | /\ FALSE \* (T \/ T) /\ F
16 |
17 | /\ TRUE
18 | \/ TRUE
19 | \/ FALSE \* (T \/ T \/ F)
20 |
21 | \/ TRUE
22 | \/ TRUE
23 | /\ FALSE \* T \/ (T /\ F)
24 | ```
25 |
26 | Etc. As a general rule of thumb:
27 |
28 | * If two logical operators are on the same level of indentation, they are part of the same level of expression.
29 | * If a logical operator is on a higher level of indentation, it's part of the previous operator statement.
30 | * Use only one type of operator per level of indentation.
31 |
32 | Generally if you mess this up the spec will crash, so you're unlikely to get a logic bug through this.
33 |
34 | ### LET-IN
35 |
36 | Any expression can use LET-IN to add local operators and definitions to just that expression alone.
37 |
38 | ```tla
39 | LET IsEven(x) == x % 2 = 0
40 | IN IsEven(5)
41 |
42 | LET IsEven(x) == x % 2 = 0
43 | Five == 5
44 | IN IsEven(Five)
45 |
46 | LET IsEven(x) == LET Two == 2
47 | Zero == 0
48 | IN x % Two = Zero
49 | Five == 5
50 | IN IsEven(Five)
51 | ```
52 |
53 | The whitespace does not matter: we can write `LET IsEven(x) == x % 2 = 0 Five == 5 IN IsEven(Five)` and it will correctly parse it as two separate operators in the LET. You should use newlines though, because you care about legibility.
54 |
55 | ### IF-THEN-ELSE
56 |
57 | This is exactly what you expect it to be.
58 |
59 | ```tla
60 | IsEven(x) == IF x % 2 = 0
61 | THEN TRUE
62 | ELSE FALSE
63 | ```
64 |
65 | As before, alignment doesn't matter, but you should align them anyway unless you really hate your coworkers.
66 |
67 | ### CASE
68 |
69 | Case is _mostly_ how you'd expect it to act, with one subtle difference.
70 |
71 | ```tla
72 | CASE x = 1 -> TRUE
73 | [] x = 2 -> TRUE
74 | [] x = 3 -> 7
75 | [] OTHER -> FALSE
76 | ```
77 |
78 | OTHER is the default. If none of the cases match and you leave out an OTHER, TLC considers that an error. If _more than one match_, though, TLC will pick one for you and _not_ branch. In other words, the following code
79 |
80 | ```tla
81 | CASE TRUE -> FALSE
82 | [] TRUE -> TRUE
83 | ```
84 |
85 | _May or may not be true._ Be careful.
86 |
87 | ## Nesting
88 |
89 | All parts of expressions are expressions or identifiers, so you can put expressions inside other expressions. Additionally, all expressions can be used inside PlusCal code.
90 |
--------------------------------------------------------------------------------
/content/tla/operators.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Operators"
3 | weight = 1
4 | +++
5 |
6 | An operator is a thing that does a thing. It's what programmers might refer to as a function. You use a `==` to define them.
7 |
8 | ```
9 | Five == 5
10 | Five + 5 \* 10
11 | ```
12 |
13 | You can also give them arguments.
14 |
15 | ```
16 | IsFive(x) == x = 5
17 | ```
18 |
19 | Or multiple arguments.
20 |
21 | ```
22 | SumWithFive(a, b) == a + b + 5
23 | ```
24 |
25 | You can use them anywhere you use any other expression.
26 |
27 | ```
28 | { Five, SumWithFive(Five, Five) } \* { 5, 15 }
29 | ```
30 |
31 | {{% notice tip %}}
32 | Remember, you can use the "No Behavior Spec" option in your TLC model to test various operators and cases.
33 | {{% /notice %}}
34 |
35 | {{% q %}}
36 | Write an operator that tests if two numbers are not equal.
37 |
38 | {{% ans neq %}}
39 | `Neq(a,b) == a /= b` works, as does `Neq(a,b) == ~(a = b)`.
40 | {{% /ans %}}
41 | {{%/q %}}
42 |
43 | ### Higher-Order Operators
44 |
45 | You can write operators that take other operators if you use a special syntax:
46 |
47 | ``` tla
48 | Sum(a, b) == a + b
49 | Do(op(_,_), a, b) == op(a, b)
50 |
51 | Do(Sum, 1, 2) = 3
52 | ```
53 |
54 | You can also make operators recursive if you specify them with the `RECURSIVE` keyword before invocation:
55 |
56 | ``` tla
57 | RECURSIVE SetReduce(_, _, _)
58 |
59 | SetReduce(Op(_, _), S, value) == IF S = {} THEN value
60 | ELSE LET s == CHOOSE s \in S: TRUE
61 | IN SetReduce(Op, S \ {s}, Op(s, value))
62 |
63 | CandlesOnChannukah == SetReduce(Sum, 2..9, 0) \* 44
64 | ```
65 |
66 | {{% q %}}
67 | Write an operator that determines whether a second operator is commutative over two given numbers. An operator is commutative if `f(a,b) = f(b,a)`.
68 |
69 | {{% ans commutative %}}
70 | `IsCommutative(f(_, _), a, b) == f(a, b) = f(b, a)`
71 | {{% /ans %}}
72 | {{%/q %}}
73 |
74 | ## Integrating with PlusCal
75 |
76 | If your operator doesn't reference any PlusCal variables (such as `IsEmpty(S) == S = {}`), you can put it above the start of the PlusCal algorithm and it will be usable like any other expression.
77 |
78 | If your operator _does_ reference any PlusCal variables (such as `HasMoneyLeft == money > 0`), it has to appear in or after the algorithm. The first way to do this is to put it after the TLA+ translation. This is simple, but it also means the PlusCal can't call the operator. Fine for invariants, less-fine for conditionals. To place the operator directly in your code, you can use a `define` block:
79 |
80 | ```
81 | define
82 | Foo(bar) == baz
83 | \* ...
84 | end define
85 | ```
86 |
87 | Your `define` block must come before the `begin`.
88 |
--------------------------------------------------------------------------------
/content/tla/tuples/img/solution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/tla/tuples/img/solution.png
--------------------------------------------------------------------------------
/content/tla/tuples/tla/hanoi.tla:
--------------------------------------------------------------------------------
1 | ---- MODULE hanoi ----
2 | EXTENDS TLC, Sequences, Integers
3 |
4 | (* --algorithm hanoi
5 | variables tower = <<<<1, 2, 3>>, <<>>, <<>>>>,
6 |
7 | define
8 | D == DOMAIN tower
9 | end define;
10 |
11 | begin
12 | while TRUE do
13 | assert tower[3] /= <<1, 2, 3>>;
14 | with from \in {x \in D : tower[x] /= <<>>},
15 | to \in {
16 | y \in D :
17 | \/ tower[y] = <<>>
18 | \/ Head(tower[from]) < Head(tower[y])
19 | }
20 | do
21 | tower[from] := Tail(tower[from]) ||
22 | tower[to] := <> \o tower[to];
23 | end with;
24 | end while;
25 | end algorithm; *)
26 | ====
27 |
--------------------------------------------------------------------------------
/layouts/index.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/layouts/partials/custom-footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ template "_internal/google_analytics.html" . }}
4 |
--------------------------------------------------------------------------------
/layouts/partials/footer.html:
--------------------------------------------------------------------------------
1 | {{ if .Params.chapter }}
2 |
3 | {{ end }}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
24 | {{ partial "custom-footer.html" . }}
25 |
26 |
27 |
--------------------------------------------------------------------------------
/layouts/partials/logo.html:
--------------------------------------------------------------------------------
1 | Written by Hillel Wayne. This work is licensed under a Creative Commons Attribution 4.0 International License.
2 | About
3 | ● Ask for Help
4 | ● Github
5 | ● Donate
6 |
--------------------------------------------------------------------------------
/layouts/partials/menu-footer.html:
--------------------------------------------------------------------------------
1 |
because I can't do websites to save my life
2 |
--------------------------------------------------------------------------------
/layouts/partials/script.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/layouts/shortcodes/ans.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
4 |
5 |
--------------------------------------------------------------------------------
/staging-content/example-specs/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Example Specs"
3 | reference = true
4 | weight = 0
5 | +++
6 |
7 | This section provides examples systems, how to think about designing them, and final specs.
8 |
--------------------------------------------------------------------------------
/static/css/bootstrap.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.7 (http://getbootstrap.com)
3 | * Copyright 2011-2017 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 |
7 | /*!
8 | * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=920d6d97aece97d31f12d823bf829701)
9 | * Config saved to config.json and https://gist.github.com/920d6d97aece97d31f12d823bf829701
10 | */
11 | /*!
12 | * Bootstrap v3.3.7 (http://getbootstrap.com)
13 | * Copyright 2011-2016 Twitter, Inc.
14 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15 | */
16 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
17 | .collapse {
18 | display: none;
19 | }
20 | .collapse.in {
21 | display: block;
22 | }
23 | tr.collapse.in {
24 | display: table-row;
25 | }
26 | tbody.collapse.in {
27 | display: table-row-group;
28 | }
29 | .collapsing {
30 | position: relative;
31 | height: 0;
32 | overflow: hidden;
33 | -webkit-transition-property: height, visibility;
34 | -o-transition-property: height, visibility;
35 | transition-property: height, visibility;
36 | -webkit-transition-duration: 0.35s;
37 | -o-transition-duration: 0.35s;
38 | transition-duration: 0.35s;
39 | -webkit-transition-timing-function: ease;
40 | -o-transition-timing-function: ease;
41 | transition-timing-function: ease;
42 | }
43 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/.commit:
--------------------------------------------------------------------------------
1 | ff5ef7c0205721295cce57f94e00999f9d1864dd
2 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Grav
4 | Copyright (c) 2016 MATHIEU CORNIC
5 | Copyright (c) 2017 Valere JEANTET
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | this software and associated documentation files (the "Software"), to deal in
9 | the Software without restriction, including without limitation the rights to
10 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | the Software, and to permit persons to whom the Software is furnished to do so,
12 | subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/README.md:
--------------------------------------------------------------------------------
1 | # Hugo Learn Theme
2 |
3 | This repository contains a theme for [Hugo](https://gohugo.io/), based on great [Grav Learn Theme](http://learn.getgrav.org/).
4 |
5 | Visit the [theme documentation](https://learn.netlify.com/en/) to see what is going on. It is actually built with this theme.
6 |
7 | ## Main features
8 |
9 | - Automatic Search
10 | - Multilingual mode
11 | - Unlimited menu levels
12 | - Automatic next/prev buttons to navigate through menu entries
13 | - Image resizing, shadow…
14 | - Attachments files
15 | - List child pages
16 | - Mermaid diagram (flowchart, sequence, gantt)
17 | - Customizable look and feel and themes variants
18 | - Buttons, Tip/Note/Info/Warning boxes, Expand
19 |
20 | ## Installation
21 |
22 | Navigate to your themes folder in your Hugo site and use the following commands:
23 |
24 | ```
25 | $ cd themes
26 | $ git clone https://github.com/matcornic/hugo-theme-learn.git
27 | ```
28 |
29 | Check that your Hugo version is minimum `0.25` with `hugo version`.
30 |
31 | 
32 |
33 | ## Usage
34 |
35 | - [Visit the documentation](https://learn.netlify.com/en/)
36 |
37 | ## Download old versions (prior to 2.0.0)
38 |
39 | If you need old version for compatibility purpose, either download [theme source code from releases](https://github.com/matcornic/hugo-theme-learn/releases) or use the right git tag. For example, with `1.1.0`
40 |
41 | - Direct download way: https://github.com/matcornic/hugo-theme-learn/archive/1.1.0.zip
42 | - Git way:
43 |
44 | ```shell
45 | cd themes/hugo-theme-learn
46 | git checkout tags/1.1.0
47 | ```
48 |
49 | For both solutions, the documentation is available at https://github.com/matcornic/hugo-theme-learn/releases/download/1.1.0/hugo-learn-doc-1.1.0.zip
50 |
51 | ## Credits
52 |
53 | Many thanks to [@vjeantet](https://github.com/vjeantet/) for the fork [docdock](https://github.com/vjeantet/hugo-theme-docdock). The v2 of this theme is mainly based on his work !
54 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/archetypes/chapter.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "{{ replace .TranslationBaseName "-" " " | title }}"
3 | date = {{ .Date }}
4 | weight = 5
5 | chapter = true
6 | pre = "X. "
7 | +++
8 |
9 | ### Chapter X
10 |
11 | # Some Chapter title
12 |
13 | Lorem Ipsum.
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/archetypes/default.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "{{ replace .TranslationBaseName "-" " " | title }}"
3 | date = {{ .Date }}
4 | weight = 5
5 | +++
6 |
7 | Lorem Ipsum.
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 MATHIEU CORNIC
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/config.toml:
--------------------------------------------------------------------------------
1 | baseURL = "/"
2 | languageCode = "en-US"
3 | defaultContentLanguage = "en"
4 |
5 | title = "Hugo Learn Documentation"
6 | theme = "hugo-theme-learn"
7 | themesdir = "../.."
8 | metaDataFormat = "yaml"
9 | defaultContentLanguageInSubdir= true
10 |
11 | [params]
12 | editURL = "https://github.com/matcornic/hugo-theme-learn/edit/master/exampleSite/content/"
13 | description = "Documentation for Hugo Learn Theme"
14 | author = "Mathieu Cornic"
15 | showVisitedLinks = true
16 |
17 | [outputs]
18 | home = [ "HTML", "RSS", "JSON"]
19 |
20 | [Languages]
21 | [Languages.en]
22 | title = "Documentation for Hugo Learn Theme"
23 | weight = 1
24 | languageName = "English"
25 |
26 | [[Languages.en.menu.shortcuts]]
27 | name = " Github repo"
28 | identifier = "ds"
29 | url = "https://github.com/matcornic/hugo-theme-learn"
30 | weight = 10
31 |
32 | [[Languages.en.menu.shortcuts]]
33 | name = " Showcases"
34 | url = "showcase"
35 | weight = 11
36 |
37 | [[Languages.en.menu.shortcuts]]
38 | name = " Hugo Documentation"
39 | identifier = "hugodoc"
40 | url = "https://gohugo.io/"
41 | weight = 20
42 |
43 | [[Languages.en.menu.shortcuts]]
44 | name = " Credits"
45 | url = "/credits"
46 | weight = 30
47 |
48 | [Languages.fr]
49 | title = "Documentation du thème Hugo Learn"
50 | weight = 2
51 | languageName = "Français"
52 |
53 | [[Languages.fr.menu.shortcuts]]
54 | name = " Repo Github"
55 | identifier = "ds"
56 | url = "https://github.com/matcornic/hugo-theme-learn"
57 | weight = 10
58 |
59 | [[Languages.fr.menu.shortcuts]]
60 | name = " Vitrine"
61 | url = "/showcase"
62 | weight = 11
63 |
64 | [[Languages.fr.menu.shortcuts]]
65 | name = " Documentation Hugo"
66 | identifier = "hugodoc"
67 | url = "https://gohugo.io/"
68 | weight = 20
69 |
70 | [[Languages.fr.menu.shortcuts]]
71 | name = " Crédits"
72 | url = "/credits"
73 | weight = 30
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/_index.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Learn Theme for Hugo"
3 | ---
4 |
5 | # Hugo learn theme
6 |
7 | [Hugo-theme-learn](http://github.com/matcornic/hugo-theme-learn) is a theme for [Hugo](https://gohugo.io/), a fast and modern static website engine written in Go. Where Hugo is often used for blogs, this multilingual-ready theme is **fully designed for documentation**.
8 |
9 | This theme is a partial porting of the [Learn theme](http://learn.getgrav.org/) of [Grav](https://getgrav.org/), a modern flat-file CMS written in PHP.
10 |
11 | {{% notice tip %}}Learn theme works with a _page tree structure_ to organize content : All contents are pages, which belong to other pages. [read more about this]({{%relref "cont/pages/_index.md"%}})
12 | {{% /notice %}}
13 |
14 | ## Main features
15 |
16 | * [Automatic Search]({{%relref "basics/configuration/_index.md#activate-search" %}})
17 | * [Multilingual mode]({{%relref "cont/i18n/_index.md" %}})
18 | * **Unlimited menu levels**
19 | * **Automatic next/prev buttons to navigate through menu entries**
20 | * [Image resizing, shadow...]({{%relref "cont/markdown.en.md#images" %}})
21 | * [Attachments files]({{%relref "shortcodes/attachments.en.md" %}})
22 | * [List child pages]({{%relref "shortcodes/children/_index.md" %}})
23 | * [Mermaid diagram]({{%relref "shortcodes/mermaid.en.md" %}}) (flowchart, sequence, gantt)
24 | * [Customizable look and feel and themes variants]({{%relref "basics/style-customization/_index.md"%}})
25 | * [Buttons]({{%relref "shortcodes/button.en.md" %}}), [Tip/Note/Info/Warning boxes]({{%relref "shortcodes/notice.en.md" %}}), [Expand]({{%relref "shortcodes/expand.en.md" %}})
26 |
27 | 
28 |
29 | ## Contribute to this documentation
30 | Feel free to update this content, just click the **Edit this page** link displayed on top right of each page, and pullrequest it
31 |
32 | {{% notice info %}}
33 | Your modification will be deployed automatically when merged.
34 | {{% /notice %}}
35 |
36 | ## Documentation website
37 | This current documentation has been statically generated with Hugo with a simple command : `hugo -t hugo-theme-learn` -- source code is [available here at GitHub](https://github.com/matcornic/hugo-theme-learn)
38 |
39 | {{% notice note %}}
40 | Automatically published and hosted thanks to [Netlify](https://www.netlify.com/). Read more about [Automated HUGO deployments with Netlify](https://www.netlify.com/blog/2015/07/30/hosting-hugo-on-netlifyinsanely-fast-deploys/)
41 | {{% /notice %}}
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/_index.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Learn Theme for Hugo"
3 | ---
4 |
5 | # Thème Hugo learn
6 |
7 | [Hugo-theme-learn](http://github.com/matcornic/hugo-theme-learn) est un thème pour [Hugo](https://gohugo.io/), un générateur de site statique, rapide et modern, écrit en Go. Tandis que Hugo est souvent utilisé pour des blogs, ce thème multi-langue est **entièrement conçu pour la documentation**.
8 |
9 | Ce thème est un portage partiel du [thème Learn](http://learn.getgrav.org/) de [Grav](https://getgrav.org/), un CMS modern écrit en PHP.
10 |
11 | {{% notice tip %}}Le thème Learn fonctionne grâce à la structure de page aborescentes pour organiser le contenu: tous les contenus sont des pages qui appartiennent à d'autres pages. [Plus d'infos]({{%relref "cont/pages/_index.md"%}})
12 | {{% /notice %}}
13 |
14 | ## Fonctionnalités principales
15 |
16 | * [Recherche automatique]({{%relref "basics/configuration/_index.md#activer-recherche" %}})
17 | * [Mode multi-langue]({{%relref "cont/i18n/_index.md" %}})
18 | * **Nombre de niveau infini dans le menu**
19 | * **Boutons suivant/précédent automatiquement générés pour naviguer entre les items du menu**
20 | * [Taille d'image, ombres...]({{%relref "cont/markdown.fr.md#images" %}})
21 | * [Fichiers joints]({{%relref "shortcodes/attachments.fr.md" %}})
22 | * [Lister les pages filles]({{%relref "shortcodes/children/_index.md" %}})
23 | * [Diagrammes Mermaid]({{%relref "shortcodes/mermaid.fr.md" %}}) (flowchart, sequence, gantt)
24 | * [Style configurable and variantes de couleurs]({{%relref "basics/style-customization/_index.md"%}})
25 | * [Boutons]({{%relref "shortcodes/button.fr.md" %}}), [Messages Astuce/Note/Info/Attention]({{%relref "shortcodes/notice.fr.md" %}}), [Expand]({{%relref "shortcodes/expand.fr.md" %}})
26 |
27 | 
28 |
29 | ## Contribuer à cette documentation
30 |
31 | N'hésitez pas à mettre à jour ce contenu en cliquant sur le lien **Modifier cette page** en haut de chaque page, et créer la Pull Request associée.
32 |
33 | {{% notice info %}}
34 | Votre modification sera déployée automatiquement quand elle sera mergée.
35 | {{% /notice %}}
36 |
37 | ## Site de documentation
38 |
39 | Cette documentation statique a été générée avec Hugo avec une simple commande : `hugo -t hugo-theme-learn` -- le code source est [disponible sur Github](https://github.com/matcornic/hugo-theme-learn)
40 |
41 | {{% notice note %}}
42 | Le site est auomatiquement publié et hébergé par [Netlify](https://www.netlify.com/). Plus d'infos sur le [déploiement de site Hugo avec Netlify](https://www.netlify.com/blog/2015/07/30/hosting-hugo-on-netlifyinsanely-fast-deploys/)(En anglais)
43 | {{% /notice %}}
44 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/basics/_index.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Basics
3 | weight: 5
4 | pre: "1. "
5 | chapter: true
6 | ---
7 |
8 | ### Chapter 1
9 |
10 | # Basics
11 |
12 | Discover what this Hugo theme is all about and the core-concepts behind it.
13 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/basics/_index.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Démarrage
3 | weight: 5
4 | pre: "1. "
5 | chapter: true
6 | ---
7 |
8 | ### Chapitre 1
9 |
10 | # Démarrage
11 |
12 | Découvrez comment utiliser ce thème Hugo et apprenez en les concepts
13 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/basics/configuration/_index.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | date: 2016-04-09T16:50:16+02:00
3 | title: Configuration
4 | weight: 20
5 | ---
6 |
7 | ## Global site parameters
8 |
9 | On top of [Hugo global configuration](https://gohugo.io/overview/configuration/), **Hugo-theme-learn** lets you define the following parameters in your `config.toml` (here, values are default).
10 |
11 | Note that some of these parameters are explained in details in other sections of this documentation.
12 |
13 | ```toml
14 | [params]
15 | # Prefix URL to edit current page. Will display an "Edit this page" button on top right hand corner of every page.
16 | # Useful to give opportunity to people to create merge request for your doc.
17 | # See the config.toml file from this documentation site to have an example.
18 | editURL = ""
19 | # Author of the site, will be used in meta information
20 | author = ""
21 | # Description of the site, will be used in meta information
22 | description = ""
23 | # Shows a checkmark for visited pages on the menu
24 | showVisitedLinks = false
25 | # Disable search function. It will hide search bar
26 | disableSearch = false
27 | # Javascript and CSS cache are automatically busted when new version of site is generated.
28 | # Set this to true to disable this behavior (some proxies don't handle well this optimization)
29 | disableAssetsBusting = false
30 | # Set this to true to disable copy-to-clipboard button for inline code.
31 | disableInlineCopyToClipBoard = false
32 | # A title for shortcuts in menu is set by default. Set this to true to disable it.
33 | disableShortcutsTitle = false
34 | # When using mulitlingual website, disable the switch language button.
35 | disableLanguageSwitchingButton = false
36 | # Order sections in menu by "weight" or "title". Default to "weight"
37 | ordersectionsby = "weight"
38 | # Change default color scheme with a variant one. Can be "red", "blue", "green".
39 | themeVariant = ""
40 | ```
41 |
42 | ## Activate search
43 |
44 | If not already present, add the follow lines in the same `config.toml` file.
45 |
46 | ```toml
47 | [outputs]
48 | home = [ "HTML", "RSS", "JSON"]
49 | ```
50 |
51 | Learn theme uses the last improvement available in hugo version 20+ to generate a json index file ready to be consumed by lunr.js javascript search engine.
52 |
53 | > Hugo generate lunrjs index.json at the root of public folder.
54 | > When you build the site with hugo server, hugo generates it internally and of course it don’t show up in the filesystem
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/basics/configuration/_index.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | date: 2016-04-09T16:50:16+02:00
3 | title: Configuration
4 | weight: 20
5 | ---
6 |
7 | ## Paramètres globaux du site
8 |
9 | En plus de la [configuration globale d'Hugo](https://gohugo.io/overview/configuration/), **Hugo-theme-learn** vous permet de définir les paramètres suivant dans votre fichier `config.toml` (ci-dessous sont affichées les valeurs par défaut).
10 |
11 | Notez que certains de ces paramètres sont expliqués en détails dans d'autres sections de cette documentation.
12 |
13 | ```toml
14 | [params]
15 | # L'URL préfixe pour éditer la page courante. Ce paramètre affichera un bouton "Modifier cette page" on haut de de chacune des pages.
16 | # Pratique pour donner les possibilité à vos utilisateurs de créer une merge request pour votre doc.
17 | # Allez voir le fichier config.toml de cette documentation pour avoir un exemple.
18 | editURL = ""
19 | # Autheur du site, est utilisé dans les informations meta
20 | author = ""
21 | # Description du site, est utilisé dans les informations meta
22 | description = ""
23 | # Affiche une icône lorsque la page a été visitée
24 | showVisitedLinks = false
25 | # Désactive la fonction de recherche. Une valeur à true cache la barre de recherche.
26 | disableSearch = false
27 | # Par défaut, le cache Javascript et CSS est automatiquement vidé lorsqu'une nouvelle version du site est générée.
28 | # Utilisez ce paramètre lorsque vous voulez désactiver ce comportement (c'est parfois incompatible avec certains proxys)
29 | disableAssetsBusting = false
30 | # Utilisez ce paramètre pour désactiver le bouton copy-to-clipboard pour le code formatté sur une ligne.
31 | disableInlineCopyToClipBoard = false
32 | # Un titre est défini par défaut lorsque vous utilisez un raccourci dans le menu. Utilisez ce paramètre pour le cacher.
33 | disableShortcutsTitle = false
34 | # Quand vous utilisez un site multi-langue, utilisez ce paramètre pour désactiver le bouton de changement de langue.
35 | disableLanguageSwitchingButton = false
36 | # Ordonne les sections dans menu par poids ("weight") ou titre ("title"). Défaut à "weight"
37 | ordersectionsby = "weight"
38 | # Utilisez ce paramètre pour modifier le schéma de couleur du site. Les valeurs par défaut sont "red", "blue", "green".
39 | themeVariant = ""
40 | ```
41 |
42 | ## Activer la recherche {#activer-recherche}
43 |
44 | Si ce n'est pas déjà présent, ajoutez les lignes suivantes dans le fichier `config.toml`.
45 |
46 | ```toml
47 | [outputs]
48 | home = [ "HTML", "RSS", "JSON"]
49 | ```
50 |
51 | Le thème *Learn* utilise les dernières amélioraions d'Hugo pour générer un fichier d'index JSON, prêt à être consommé par le moteur de recherche lunr.js.
52 |
53 | > Hugo génère lunrjs index.json à la racine du dossier `public`.
54 | > Quand vous générez le site avec `hugo server`, Hugo génère le fichier en mémoire, il n'est donc pas disponible sur le disque.
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/basics/installation/images/chapter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/basics/installation/images/chapter.png
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/basics/requirements/_index.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Requirements
3 | weight: 10
4 | disableToc: true
5 | ---
6 |
7 | Thanks to the simplicity of Hugo, this page is as empty as this theme needs requirements.
8 |
9 | Just download latest version of [Hugo binary (> 0.25)](https://gohugo.io/getting-started/installing/) for your OS (Windows, Linux, Mac) : it's that simple.
10 |
11 | 
12 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/basics/requirements/_index.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Prérequis
3 | weight: 10
4 | disableToc: true
5 | ---
6 |
7 | Grâce à la simplicité d'Hugo, cette page est vide car il n'y a quasi pas de prérequis pour utiliser le thème.
8 |
9 | Téléchargez la dernière version du [binaire Hugo (> 0.25)](https://gohugo.io/getting-started/installing/) pour votre Système d'exploitation (Windows, Linux, Mac) : et c'est tout !
10 |
11 | 
12 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/basics/requirements/images/magic.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/basics/requirements/images/magic.gif
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/basics/style-customization/images/blue-variant.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/basics/style-customization/images/blue-variant.png
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/basics/style-customization/images/green-variant.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/basics/style-customization/images/green-variant.png
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/basics/style-customization/images/red-variant.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/basics/style-customization/images/red-variant.png
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/cont/_index.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Content
3 | weight: 10
4 | chapter: true
5 | pre: "2. "
6 | ---
7 |
8 | ### Chapter 2
9 |
10 | # Content
11 |
12 | Find out how to create and organize your content quickly and intuitively.
13 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/cont/_index.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Contenu
3 | weight: 10
4 | chapter: true
5 | pre: "2. "
6 | ---
7 |
8 | ### Chapitre 2
9 |
10 | # Contenu
11 |
12 | Découvrez comment créer et organiser votre contenu facilement et intuitivement.
13 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/cont/archetypes.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Archetypes
3 | weight: 10
4 | ---
5 |
6 | Using the command: `hugo new [relative new content path]`, you can start a content file with the date and title automatically set. While this is a welcome feature, active writers need more : [archetypes](https://gohugo.io/content/archetypes/).
7 |
8 | It is pre-configured skeleton pages with default front matter. Please refer to the documentation for types of page to understand the differences.
9 |
10 | ## Chapter {#archetypes-chapter}
11 |
12 | To create a Chapter page, run the following commands
13 |
14 | ```
15 | hugo new --kind chapter /_index.md
16 | ```
17 |
18 | It will create a page with predefined Front-Matter:
19 |
20 | ```markdown
21 | +++
22 | title = "{{ replace .TranslationBaseName "-" " " | title }}"
23 | date = {{ .Date }}
24 | weight = 5
25 | chapter = true
26 | pre = "X. "
27 | +++
28 |
29 | ### Chapter X
30 |
31 | # Some Chapter title
32 |
33 | Lorem Ipsum.
34 | ```
35 |
36 | ## Default
37 |
38 | To create a default page, run either one of the following commands
39 |
40 | ```
41 | # Either
42 | hugo new //_index.md
43 | # Or
44 | hugo new /.md
45 | ```
46 |
47 | It will create a page with predefined Front-Matter:
48 |
49 | ```markdown
50 | +++
51 | title = "{{ replace .TranslationBaseName "-" " " | title }}"
52 | date = {{ .Date }}
53 | weight = 5
54 | +++
55 |
56 | Lorem Ipsum.
57 | ```
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/cont/archetypes.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Archétypes
3 | weight: 10
4 | ---
5 |
6 | En utilisant la commande: `hugo new [chemin vers nouveau contenu]`, vous pouvez créer un nouveau fichier avec la date et le title automatiquement initialisé. Même si c'est une fonctionnalité intéressante, elle reste limitée pour les auteurs actifs qui ont besoin de mieux : les [archetypes](https://gohugo.io/content/archetypes/).
7 |
8 | Les archétypes sont des squelettes de pages préconfigurées avec un Front Matter par défaut. Merci de vous référer à la documentation pour connaitre les différents types de page.
9 |
10 | ## Chapitre {#archetypes-chapter}
11 |
12 | Pour créer un chapitre, lancez les commandes suivantes
13 |
14 | ```
15 | hugo new --kind chapter /_index.md
16 | ```
17 |
18 | Cela crééra une page avec le Front Matter suivant:
19 |
20 | ```markdown
21 | +++
22 | title = "{{ replace .TranslationBaseName "-" " " | title }}"
23 | date = {{ .Date }}
24 | weight = 5
25 | chapter = true
26 | pre = "X. "
27 | +++
28 |
29 | ### Chapter X
30 |
31 | # Some Chapter title
32 |
33 | Lorem Ipsum.
34 | ```
35 |
36 | ## Défaut
37 |
38 | Pour créer une page classique, lancer l'une des deux commandes suivantes
39 |
40 | ```
41 | # Soit
42 | hugo new //_index.md
43 | # Ou
44 | hugo new /.md
45 | ```
46 |
47 | Cela crééra une page avec le Front Matter suivant:
48 |
49 | ```markdown
50 | +++
51 | title = "{{ replace .TranslationBaseName "-" " " | title }}"
52 | date = {{ .Date }}
53 | weight = 5
54 | +++
55 |
56 | Lorem Ipsum.
57 | ```
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/cont/i18n/_index.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | date: 2016-04-09T16:50:16+02:00
3 | title: Multilingual and i18n
4 | weight: 30
5 | ---
6 |
7 | **Learn theme** is fully compatible with Hugo multilingual mode.
8 |
9 | It provides:
10 |
11 | - Translation strings for default values (English and French). Feel free to contribute !
12 | - Automatic menu generation from multilingual content
13 | - In-browser language switching
14 |
15 | 
16 |
17 | ## Basic configuration
18 |
19 | After learning [how Hugo handle multilingual websites](https://gohugo.io/content-management/multilingual), define your languages in your `config.toml` file.
20 |
21 | For example with current French and English website.
22 |
23 | ```toml
24 | # English is the default language
25 | defaultContentLanguage = "en"
26 | # Force to have /en/my-page and /fr/my-page routes, even for default language.
27 | defaultContentLanguageInSubdir= true
28 |
29 | [Languages]
30 | [Languages.en]
31 | title = "Documentation for Hugo Learn Theme"
32 | weight = 1
33 | languageName = "English"
34 |
35 | [Languages.fr]
36 | title = "Documentation du thème Hugo Learn"
37 | weight = 2
38 | languageName = "Français"
39 | ```
40 |
41 | Then, for each new page, append the *id* of the language to the file.
42 |
43 | - Single file `my-page.md` is split in two files:
44 | - in English: `my-page.en.md`
45 | - in French: `my-page.fr.md`
46 | - Single file `_index.md` is split in two files:
47 | - in English: `_index.en.md`
48 | - in French: `_index.fr.md`
49 |
50 | {{% notice info %}}
51 | Be aware that only translated pages are displayed in menu. It's not replaced with default language content.
52 | {{% /notice %}}
53 |
54 | {{% notice tip %}}
55 | Use [slug](https://gohugo.io/content-management/multilingual/#translate-your-content) Front Matter parameter to translate urls too.
56 | {{% /notice %}}
57 |
58 | ## Overwrite translation strings
59 |
60 | Translations strings are used for common default values used in the theme (*Edit this page* button, *Search placeholder* and so on). Translations are available in french and english but you may use another language or want to override default values.
61 |
62 | To override these values, create a new file in your local i18n folder `i18n/.toml` and inspire yourself from the theme `themes/hugo-theme-learn/i18n/en.toml`
63 |
64 | By the way, as these translations could be used by other people, please take the time to propose a translation by [making a PR](https://github.com/matcornic/hugo-theme-learn/pulls) to the theme !
65 |
66 | ## Disable language switching
67 |
68 | Switching the language in the browser is a great feature, but for some reasons you may want to disable it.
69 |
70 | Just set `disableLanguageSwitchingButton=true` in your `config.toml`
71 |
72 | ```toml
73 | [params]
74 | # When using mulitlingual website, disable the switch language button.
75 | disableLanguageSwitchingButton = true
76 | ```
77 |
78 | 
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/cont/i18n/_index.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | date: 2016-04-09T16:50:16+02:00
3 | title: Multi-langue et i18n
4 | weight: 30
5 | ---
6 |
7 | **Learn** est complètement compatible avec le mode multi-langue d'Hugo.
8 |
9 | Il fournit :
10 |
11 | - Des *translation strings* pour les valeurs par défaut utilisées par le thème (Anglais et Français). N'hésitez pas à contribuer !
12 | - Génération automatique du menu avec le contenu multi-langue
13 | - Modification de la langue dans le navigateur
14 |
15 | 
16 |
17 | ## Configuration simple
18 |
19 | Après avoir appris [comment Hugo gère les sites multi-langue](https://gohugo.io/content-management/multilingual), définissez vos langues dans votre fichier `config.toml`.
20 |
21 | Par exemple, pour ce site, avec du contenu en français et en anglais.
22 |
23 | ```toml
24 | # Anglais est la langue par défaut
25 | defaultContentLanguage = "en"
26 | # Force d'avoir /en/ma-page et /fr/ma-page routes, même avec la langue par défaut.
27 | defaultContentLanguageInSubdir= true
28 |
29 | [Languages]
30 | [Languages.en]
31 | title = "Documentation for Hugo Learn Theme"
32 | weight = 1
33 | languageName = "English"
34 |
35 | [Languages.fr]
36 | title = "Documentation du thème Hugo Learn"
37 | weight = 2
38 | languageName = "Français"
39 | ```
40 |
41 | Puis, pour chaque nouvelle page, ajoutez *l'id* de la langue du fichier.
42 |
43 | - Le fichier `my-page.md` est découpé en deux fichiers :
44 | - en anglais : `my-page.en.md`
45 | - en français : `my-page.fr.md`
46 | - Le fichier `_index.md` est découpé en deux fichiers :
47 | - en anglais: `_index.en.md`
48 | - en français: `_index.fr.md`
49 |
50 | {{% notice info %}}
51 | Attention, seulement les pages traduites sont affichées dans le menu. Le contenu n'est pas remplacé par les pages de la langue par défaut.
52 | {{% /notice %}}
53 |
54 | {{% notice tip %}}
55 | Utilisez le paramètre du Front Matter [slug](https://gohugo.io/content-management/multilingual/#translate-your-content) pour traduire également les URLs.
56 | {{% /notice %}}
57 |
58 | ## Surcharger les *translation strings*
59 |
60 | Les *Translations strings* sont utilisées comme valeurs par défaut dans le thème (Bouton *Modifier la page*, Element de subsitution *Recherche*, etc.). Les traductions sont disponibles en français et en anglais mais vous pouvez utiliser n'importe quelle autre langue et surcharger avec vos propres valeurs.
61 |
62 | Pour surcharger ces valeurs, créer un nouveau fichier dans votre dossier i18n local `i18n/.toml` et inspirez vous du thème `themes/hugo-theme-learn/i18n/en.toml`
63 |
64 | D'ailleurs, ces traductions pour servir à tout le monde, donc svp prenez le temps de [proposer une Pull Request](https://github.com/matcornic/hugo-theme-learn/pulls) !
65 |
66 | ## Désactiver le changement de langue
67 |
68 | Vous pouvez changer de langue directement dans le navigateur. C'est une super fonctionnalité, mais vous avez peut-être besoin de la désactiver.
69 |
70 | Pour ce faire, ajouter le paramètre `disableLanguageSwitchingButton=true` dans votre `config.toml`
71 |
72 | ```toml
73 | [params]
74 | # Quand vous utilisez un site en multi-langue, désactive le bouton de changment de langue.
75 | disableLanguageSwitchingButton = true
76 | ```
77 |
78 | 
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/cont/i18n/images/i18n-menu.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/cont/i18n/images/i18n-menu.gif
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/cont/pages/images/frontmatter-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/cont/pages/images/frontmatter-icon.png
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/cont/pages/images/pages-chapter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/cont/pages/images/pages-chapter.png
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/cont/pages/images/pages-default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/cont/pages/images/pages-default.png
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/credits.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Credits
3 | disableToc: true
4 | ---
5 |
6 | ## Contributors
7 |
8 | Thanks to them for make Open Source Software a better place !
9 |
10 | {{% ghcontributors "https://api.github.com/repos/matcornic/hugo-theme-learn/contributors?per_page=100" %}}
11 |
12 | And a special thanks to [@vjeantet](https://github.com/vjeantet) for his work on [docdock](https://github.com/vjeantet/hugo-theme-docdock), a fork of hugo-theme-learn. v2.0.0 of this theme is inspired by his work.
13 |
14 | ## Packages and libraries
15 | * [mermaid](https://knsv.github.io/mermaid) - generation of diagram and flowchart from text in a similar manner as markdown
16 | * [font awesome](http://fontawesome.io/) - the iconic font and CSS framework
17 | * [jQuery](https://jquery.com) - The Write Less, Do More, JavaScript Library
18 | * [lunr](https://lunrjs.com) - Lunr enables you to provide a great search experience without the need for external, server-side, search services...
19 | * [horsey](https://bevacqua.github.io/horsey/) - Progressive and customizable autocomplete component
20 | * [clipboard.js](https://zenorocha.github.io/clipboard.js) - copy text to clipboard
21 | * [highlight.js](https://highlightjs.org) - Javascript syntax highlighter
22 | * [modernizr](https://modernizr.com) - A JavaScript toolkit that allows web developers to use new CSS3 and HTML5 features while maintaining a fine level of control over browsers that don't support
23 |
24 | ## Tooling
25 |
26 | * [Netlify](https://www.netlify.com) - Continuous deployement and hosting of this documentation
27 | * [Hugo](https://gohugo.io/)
28 |
29 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/credits.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Crédits
3 | disableToc: true
4 | ---
5 |
6 | ## Contributeurs
7 |
8 | Merci à eux de rendre le monde Open Source meilleur !
9 |
10 | {{% ghcontributors "https://api.github.com/repos/matcornic/hugo-theme-learn/contributors?per_page=100" %}}
11 |
12 | Et un grand merci à [@vjeantet](https://github.com/vjeantet) pour son travail sur [docdock](https://github.com/vjeantet/hugo-theme-docdock), un fork de _hugo-theme-learn_. La v2.0.0 du thème est en grande partie inspirée de son travail.
13 |
14 | ## Packages et librairies
15 | * [mermaid](https://knsv.github.io/mermaid) - géneration de diagrames et graphiques à partir de texte similaire à Markdown
16 | * [font awesome](http://fontawesome.io/) - Le framework de polices iconiques
17 | * [jQuery](https://jquery.com) - La plus connue des librairies Javascript
18 | * [lunr](https://lunrjs.com) - Lunr fournit des fonctions de recherche sans service externe
19 | * [horsey](https://bevacqua.github.io/horsey/) - Autocomplétion de composants (utiliser pour les suggestions de recherche)
20 | * [clipboard.js](https://zenorocha.github.io/clipboard.js) - Copier le texte dans le presse-papier
21 | * [highlight.js](https://highlightjs.org) - Mise en valeur de syntaxes
22 | * [modernizr](https://modernizr.com) - Une boite à outil Javascript qui permet aux développeurs d'utiliser les dernières fonctionnalités de CSS et HTML5, même sur de vieux navigateurs.
23 |
24 | ## Outils
25 |
26 | * [Netlify](https://www.netlify.com) - Déploiement continue et hébergement de cette documentation
27 | * [Hugo](https://gohugo.io/)
28 |
29 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/_index.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | date: 2016-04-09T16:50:16+02:00
3 | title: Shortcodes
4 | pre: "3. "
5 | weight: 15
6 | ---
7 |
8 | Hugo uses Markdown for its simple content format. However, there are a lot of things that Markdown doesn’t support well. You could use pure HTML to expand possibilities.
9 |
10 | But this happens to be a bad idea. Everyone uses Markdown because it's pure and simple to read even non-rendered. You should avoid HTML to keep it as simple as possible.
11 |
12 | To avoid this limitations, Hugo created [shortcodes](https://gohugo.io/extras/shortcodes/). A shortcode is a simple snippet inside a page.
13 |
14 | **Hugo-theme-learn** provides multiple shortcodes on top of existing ones.
15 |
16 | {{%children style="h2" description="true" %}}
17 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/_index.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | date: 2016-04-09T16:50:16+02:00
3 | title: Shortcodes
4 | pre: "3. "
5 | weight: 15
6 | ---
7 |
8 | Hugo utilise Markdown pour son format simple. Cependant, il y a beaucoup de chose que Markdown ne supporte pas bien. On pourrait utiliser du HTML pur pour améliorer les capacité du Markdown.
9 |
10 | Mais c'est probablement une mauvaise idée. Tout le monde utilise le Markdown parce que c'est pur et simple à lire même lorsqu'il est affiché en texte brut. Vous devez éviter le HTML autant que possible pour garder le contenu simple.
11 |
12 | Cependant, pour éviter les limitations, Hugo a créé les [shortcodes](https://gohugo.io/extras/shortcodes/). Un shortcode est un bout de code (*snippet*) dans une page.
13 |
14 | **Hugo-theme-learn** fournit de multiple shortcodes en plus de ceux existant.
15 |
16 | {{%children style="h2" description="true" %}}
17 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/BachGavotteShort.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/BachGavotteShort.mp3
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/Carroll_AliceAuPaysDesMerveilles.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/Carroll_AliceAuPaysDesMerveilles.pdf
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/adivorciarsetoca00cape.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/adivorciarsetoca00cape.pdf
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/hugo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/hugo.png
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/movieselectricsheep-flock-244-32500-2.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/movieselectricsheep-flock-244-32500-2.mp4
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Attachments
3 | description : "The Attachments shortcode displays a list of files attached to a page."
4 | ---
5 |
6 | The Attachments shortcode displays a list of files attached to a page.
7 |
8 | {{% attachments /%}}
9 |
10 | ## Usage
11 |
12 | The shortcurt lists files found in a **specific folder**.
13 | Currently, it support two implementations for pages
14 |
15 | 1. If your page is a markdown file, attachements must be place in a **folder** named like your page and ending with **.files**.
16 |
17 | > * content
18 | > * _index.md
19 | > * page.files
20 | > * attachment.pdf
21 | > * page.md
22 |
23 | 2. If your page is a **folder**, attachements must be place in a nested **'files'** folder.
24 |
25 | > * content
26 | > * _index.md
27 | > * page
28 | > * index.md
29 | > * files
30 | > * attachment.pdf
31 |
32 | Be aware that if you use a multilingual website, you will need to have as many folders as languages.
33 |
34 | That's all !
35 |
36 | ### Parameters
37 |
38 | | Parameter | Default | Description |
39 | |:--|:--|:--|
40 | | title | "Attachments" | List's title |
41 | | style | "" | Choose between "orange", "grey", "blue" and "green" for nice style |
42 | | pattern | ".*" | A regular expressions, used to filter the attachments by file name.
The **pattern** parameter value must be [regular expressions](https://en.wikipedia.org/wiki/Regular_expression).
43 |
44 | For example:
45 |
46 | * To match a file suffix of 'jpg', use **.*jpg** (not *.jpg).
47 | * To match file names ending in 'jpg' or 'png', use **.*(jpg|png)**
48 |
49 | ### Examples
50 |
51 | #### List of attachments ending in pdf or mp4
52 |
53 |
54 | {{%/*attachments title="Related files" pattern=".*(pdf|mp4)"/*/%}}
55 |
56 | renders as
57 |
58 | {{%attachments title="Related files" pattern=".*(pdf|mp4)"/%}}
59 |
60 | #### Colored styled box
61 |
62 | {{%/*attachments style="orange" /*/%}}
63 |
64 | renders as
65 |
66 | {{% attachments style="orange" /%}}
67 |
68 |
69 | {{%/*attachments style="grey" /*/%}}
70 |
71 | renders as
72 |
73 | {{% attachments style="grey" /%}}
74 |
75 | {{%/*attachments style="blue" /*/%}}
76 |
77 | renders as
78 |
79 | {{% attachments style="blue" /%}}
80 |
81 | {{%/*attachments style="green" /*/%}}
82 |
83 | renders as
84 |
85 | {{% attachments style="green" /%}}
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/BachGavotteShort.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/BachGavotteShort.mp3
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/Carroll_AliceAuPaysDesMerveilles.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/Carroll_AliceAuPaysDesMerveilles.pdf
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/adivorciarsetoca00cape.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/adivorciarsetoca00cape.pdf
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/hugo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/hugo.png
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/movieselectricsheep-flock-244-32500-2.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/movieselectricsheep-flock-244-32500-2.mp4
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Attachments (Pièces jointes)
3 | description : "The Attachments shortcode displays a list of files attached to a page."
4 | ---
5 |
6 | Le shortcode *Attachments* affiche une liste de pièces jointes d'une page.
7 |
8 | {{% attachments /%}}
9 |
10 | ## Utilisation
11 |
12 | Le shortcode affiche la liste de fichiers trouvés dans un **dossier spécifique**
13 | A l'heure actuelle, il supporte deux implémentations
14 |
15 | 1. Si votre page est un fichier Markdown, les pièces jointes doivent être placée dans un **dossier** nommé comme le nom de la page et suffixé par **.files**.
16 |
17 | > * content
18 | > * _index.md
19 | > * page.files
20 | > * attachment.pdf
21 | > * page.md
22 |
23 | 2. Si votre page est un **dossier**, les pièces jointes doivent être placées dans un dossier fils **'files'**.
24 |
25 | > * content
26 | > * _index.md
27 | > * page
28 | > * index.md
29 | > * files
30 | > * attachment.pdf
31 |
32 | Attention, si votre site est multi-langue, vous devrez avec autant de dossier qu'il y a de langues.
33 |
34 | C'est tout !
35 |
36 | ### Paramètres
37 |
38 | | Paramètre | Défaut | Description |
39 | |:--|:--|:--|
40 | | title | "Pièces jointes" | Titre de la liste |
41 | | style | "" | Choisir entre "orange", "grey", "blue" et "green" pour un style plus sympa |
42 | | pattern | ".*" | Une expression régulière, utilisée pour filtrer les pièces jointes par leur nom de fichier.
Le paramètre **pattern** doit être une [expression régulière](https://en.wikipedia.org/wiki/Regular_expression).
43 |
44 | Par exemple:
45 |
46 | * Pour trouver les fichiers avec le suffixe 'jpg', utilisez **.*jpg** (pas *.jpg).
47 | * Pour trouver les fichiers avec les suffixe 'jpg' ou 'png', utilisez **.*(jpg|png)**
48 |
49 | ### Exemples
50 |
51 | #### Lister les pièces jointes de type pdf ou mp4
52 |
53 |
54 | {{%/*attachments title="Fichiers associés" pattern=".*(pdf|mp4)"/*/%}}
55 |
56 | s'affiche comme
57 |
58 | {{%attachments title="Fichiers associés" pattern=".*(pdf|mp4)"/%}}
59 |
60 | #### Modifier le style
61 |
62 | {{%/*attachments style="orange" /*/%}}
63 |
64 | s'affiche comme
65 |
66 | {{% attachments style="orange" /%}}
67 |
68 |
69 | {{%/*attachments style="grey" /*/%}}
70 |
71 | s'affiche comme
72 |
73 | {{% attachments style="grey" /%}}
74 |
75 | {{%/*attachments style="blue" /*/%}}
76 |
77 | s'affiche comme
78 |
79 | {{% attachments style="blue" /%}}
80 |
81 | {{%/*attachments style="green" /*/%}}
82 |
83 | s'affiche comme
84 |
85 | {{% attachments style="green" /%}}
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/button.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Button
3 | description : "Nice buttons on your page."
4 | ---
5 |
6 | A button is a just a clickable button with optional icon.
7 |
8 | ```
9 | {{%/* button href="https://getgrav.org/" */%}}Get Grav{{%/* /button */%}}
10 | {{%/* button href="https://getgrav.org/" icon="fa fa-download" */%}}Get Grav with icon{{%/* /button */%}}
11 | {{%/* button href="https://getgrav.org/" icon="fa fa-download" icon-position="right" */%}}Get Grav with icon right{{%/* /button */%}}
12 | ```
13 |
14 | {{% button href="https://getgrav.org/" %}}Get Grav{{% /button %}}
15 | {{% button href="https://getgrav.org/" icon="fa fa-download" %}}Get Grav with icon{{% /button %}}
16 | {{% button href="https://getgrav.org/" icon="fa fa-download" icon-position="right" %}}Get Grav with icon right{{% /button %}}
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/button.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Button (Bouton)
3 | description : "De beaux boutons sur votre page."
4 | ---
5 |
6 | Le shortcode *button* est simplement un bouton cliquable avec une icône optionnelle.
7 |
8 | ```
9 | {{%/* button href="https://getgrav.org/" */%}}Téléchargez Grav{{%/* /button */%}}
10 | {{%/* button href="https://getgrav.org/" icon="fa fa-download" */%}}Téléchargez Grav avec icône{{%/* /button */%}}
11 | {{%/* button href="https://getgrav.org/" icon="fa fa-download" icon-position="right" */%}}Téléchargez Grav avec icône à droite{{%/* /button */%}}
12 | ```
13 |
14 | {{% button href="https://getgrav.org/" %}}Téléchargez Grav{{% /button %}}
15 | {{% button href="https://getgrav.org/" icon="fa fa-download" %}}Téléchargez Grav avec icône{{% /button %}}
16 | {{% button href="https://getgrav.org/" icon="fa fa-download" icon-position="right" %}}Téléchargez Grav avec icône à droite{{% /button %}}
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/_index.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title : Children
3 | description : List the child pages of a page
4 | ---
5 |
6 | Use the children shortcode to list the child pages of a page and the further descendants (children's children). By default, the shortcode displays links to the child pages.
7 |
8 | ## Usage
9 |
10 | | Parameter | Default | Description |
11 | |:--|:--|:--|
12 | | page | _current_ | Specify the page name (section name) to display children for |
13 | | style | "li" | Choose the style used to display descendants. It could be any HTML tag name |
14 | | showhidden | "false" | When true, child pages hidden from the menu will be displayed |
15 | | description | "false" | Allows you to include a short text under each page in the list. when no description exists for the page, children shortcode takes the first 70 words of your content. [read more info about summaries on gohugo.io](https://gohugo.io/content/summaries/) |
16 | | depth | 1 | Enter a number to specify the depth of descendants to display. For example, if the value is 2, the shortcode will display 2 levels of child pages. **Tips:** set 999 to get all descendants|
17 | | sort | none | Sort Children By
Weight - to sort on menu order
Name - to sort alphabetically on menu label
Identifier - to sort alphabetically on identifier set in frontmatter
URL - URL
|
18 |
19 | ## Demo
20 |
21 | {{%/* children */%}}
22 |
23 | {{% children %}}
24 |
25 | {{%/* children description="true" */%}}
26 |
27 | {{%children description="true" %}}
28 |
29 | {{%/* children depth="3" showhidden="true" */%}}
30 |
31 | {{% children depth="3" showhidden="true" %}}
32 |
33 | {{%/* children style="h2" depth="3" description="true" */%}}
34 |
35 | {{% children style="h2" depth="3" description="true" %}}
36 |
37 | {{%/* children style="div" depth="999" */%}}
38 |
39 | {{% children style="div" depth="999" %}}
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/_index.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title : Children (Pages filles)
3 | description : Liste les pages filles de la page
4 | ---
5 |
6 | Utilisez le shortcode *children* pour lister les pages filles de la page et tous ses déscendants (pages filles de pages filles). Par défaut, le shortcode affiche des liens vers les pages filles.
7 |
8 | ## Utilisation
9 |
10 | | Paramètre | Défaut | Description |
11 | |:--|:--|:--|
12 | | page | _current_ | Spécifie le nom de la page (nom de la section) à afficher |
13 | | style | "li" | Choisi le style à utiliser pour afficher les descendants. Cela peut être n'importe quel balise HTML |
14 | | showhidden | "false" | Quand *true*, pages filles cachées dans le menu seront affichées quand même |
15 | | description | "false" | Permet d'inclure le texte de la description de la page sous chaque entré de la liste. quand aucune description existe pour la page, le shortcode prend les 70 premiers mots du contenu. [plus d'infos sur gohugo.io](https://gohugo.io/content/summaries/) |
16 | | depth | 1 | Nombre de descendants à afficher. Par exemple, si la valeur est 2, le shortcode va afficher 2 niveaux de pages filels. **Astuce:** Utilisez 999 pour avoir tous les descendants|
17 | | sort | | Tri les pages filles par
Weight - Poids
Name - Nom
Identifier - Trier alphabétiquement par identifiant configuré dans le front matter
URL - URL
|
18 |
19 | ## Démo
20 |
21 | {{%/* children */%}}
22 |
23 | {{% children %}}
24 |
25 | {{%/* children description="true" */%}}
26 |
27 | {{%children description="true" %}}
28 |
29 | {{%/* children depth="3" showhidden="true" */%}}
30 |
31 | {{% children depth="3" showhidden="true" %}}
32 |
33 | {{%/* children style="h2" depth="3" description="true" */%}}
34 |
35 | {{% children style="h2" depth="3" description="true" %}}
36 |
37 | {{%/* children style="div" depth="999" */%}}
38 |
39 | {{% children style="div" depth="999" %}}
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/_index.en.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 1"
3 | description = "This is a demo child page"
4 | +++
5 |
6 | This is a demo child page
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/_index.fr.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 1"
3 | description = "Ceci est une page test"
4 | +++
5 |
6 | Ceci est une page de demo
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/_index.en.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 1-1"
3 | description = "This is a demo child page"
4 | +++
5 |
6 | This is a demo child page
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/_index.fr.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 1-1"
3 | description = "Ceci est une page test"
4 | +++
5 |
6 | Ceci est une page de demo
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/children-1-1-1/_index.en.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 1-1-1"
3 | description = "This is a demo child page"
4 | +++
5 |
6 | This is a demo child page
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/children-1-1-1/_index.fr.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 1-1-1"
3 | description = "Ceci est une page test"
4 | +++
5 |
6 | Ceci est une page de demo
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/children-1-1-1/children-1-1-1-1/_index.en.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 1-1-1-1"
3 | description = "This is a demo child page"
4 | +++
5 |
6 | This is a demo child page
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/children-1-1-1/children-1-1-1-1/_index.fr.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 1-1-1-1"
3 | description = "Ceci est une page test"
4 | +++
5 |
6 | Ceci est une page de demo
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/children-1-1-1/children-1-1-1-1/children-1-1-1-1-1/_index.en.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 1-1-1-1-1"
3 | description = "This is a demo child page"
4 | +++
5 |
6 | This is a demo child page
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/children-1-1-1/children-1-1-1-1/children-1-1-1-1-1/_index.fr.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 1-1-1-1-1"
3 | description = "Ceci est une page test"
4 | +++
5 |
6 | Ceci est une page de demo
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-2/_index.en.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 2"
3 | description = ""
4 | +++
5 |
6 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
7 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
8 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
9 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
10 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
11 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-2/_index.fr.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 2"
3 | description = ""
4 | +++
5 |
6 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
7 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
8 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
9 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
10 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
11 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-2/test3.en.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page test 3"
3 | description = "This is a page test"
4 | +++
5 |
6 | This is a test 3 demo child page
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-2/test3.fr.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page test 3"
3 | description = "Ceci est une page test"
4 | +++
5 |
6 | Ceci est une page de demo test 3
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-3/_index.en.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 3"
3 | description = "This is a demo child page"
4 | +++
5 |
6 | This is a demo child page, not displayed in the menu
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-3/_index.fr.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 3"
3 | description = "Ceci est une page test"
4 | +++
5 |
6 | Ceci est une page de demo
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-4/_index.en.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 4"
3 | description = "This is a demo child page"
4 | hidden = true
5 | +++
6 |
7 | This is a demo child page, not displayed in the menu
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-4/_index.fr.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page 4"
3 | description = "Ceci est une page test"
4 | hidden = true
5 | +++
6 |
7 | Ceci est une page de demo
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/test.en.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page test"
3 | description = "This is a page test"
4 | +++
5 |
6 | This is a test demo child page
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/children/test.fr.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "page test"
3 | description = "Ceci est une page test"
4 | +++
5 |
6 | Ceci est une page de demo
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/expand.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title : Expand
3 | description : "Displays an expandable/collapsible section of text on your page"
4 | ---
5 |
6 | The Expand shortcode displays an expandable/collapsible section of text on your page.
7 | Here is an example
8 |
9 | {{%expand%}}
10 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
11 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
12 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
13 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
14 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
15 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
16 | {{%/expand%}}
17 |
18 |
19 | ## Usage
20 |
21 |
22 | this shortcode takes exactly one optional parameter to define the text that appears next to the expand/collapse icon. (default is "Expand me...")
23 |
24 | {{%/*expand "Is this learn theme rocks ?" */%}}Yes !.{{%/* /expand*/%}}
25 |
26 | {{%expand "Is this learn theme rocks ?" %}}Yes !{{% /expand%}}
27 |
28 | # Demo
29 |
30 | {{%/*expand*/%}}
31 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
32 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
33 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
34 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
35 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
36 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
37 | {{%/* /expand*/%}}
38 |
39 |
40 | {{%expand%}}Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
41 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
42 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
43 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
44 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
45 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.{{% /expand%}}
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/expand.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title : Expand
3 | description : "Affiche une section de texte qui se plie et se déplie"
4 | ---
5 |
6 | Le shortcode *Expand* affiche une section de texte qui se plie et se déplie.
7 | Ci-dessous un exemple.
8 |
9 | {{%expand%}}
10 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
11 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
12 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
13 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
14 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
15 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
16 | {{%/expand%}}
17 |
18 |
19 | ## Utilisation
20 |
21 |
22 | Ce shortcode prends exactement un paramètre optionel pour définir le texte à côté de l'icone. (valeur par défaut est "Déroulez-moi...")
23 |
24 | {{%/*expand "Est-ce que ce thème envoie du pâté ?" */%}}Oui !.{{%/* /expand*/%}}
25 |
26 | {{%expand "Est-ce que ce thème envoie du pâté ?" %}}Oui !{{% /expand%}}
27 |
28 | # Demo
29 |
30 | {{%/*expand*/%}}
31 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
32 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
33 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
34 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
35 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
36 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
37 | {{%/* /expand*/%}}
38 |
39 |
40 | {{%expand%}}Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
41 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
42 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
43 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
44 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
45 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.{{% /expand%}}
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/mermaid.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title : "Mermaid"
3 | description : "Generation of diagram and flowchart from text in a similar manner as markdown"
4 | ---
5 |
6 | [Mermaid](https://mermaidjs.github.io/) is a library helping you to generate diagram and flowcharts from text, in a similar manner as Markdown.
7 |
8 | Just insert your mermaid code in the `mermaid` shortcode and that's it.
9 |
10 | ## Flowchart example
11 | {{*mermaid align="left"*/>}}
12 | graph LR;
13 | A[Hard edge] -->|Link text| B(Round edge)
14 | B --> C{Decision}
15 | C -->|One| D[Result one]
16 | C -->|Two| E[Result two]
17 | {{* /mermaid */>}}
18 |
19 | renders as
20 |
21 | {{}}
22 | graph LR;
23 | A[Hard edge] -->|Link text| B(Round edge)
24 | B --> C{Decision}
25 | C -->|One| D[Result one]
26 | C -->|Two| E[Result two]
27 | {{< /mermaid >}}
28 |
29 | ## Sequence example
30 |
31 | {{*mermaid*/>}}
32 | sequenceDiagram
33 | participant Alice
34 | participant Bob
35 | Alice->>John: Hello John, how are you?
36 | loop Healthcheck
37 | John->John: Fight against hypochondria
38 | end
39 | Note right of John: Rational thoughts prevail...
40 | John-->Alice: Great!
41 | John->Bob: How about you?
42 | Bob-->John: Jolly good!
43 | {{* /mermaid */>}}
44 |
45 | renders as
46 |
47 | {{}}
48 | sequenceDiagram
49 | participant Alice
50 | participant Bob
51 | Alice->>John: Hello John, how are you?
52 | loop Healthcheck
53 | John->John: Fight against hypochondria
54 | end
55 | Note right of John: Rational thoughts prevail...
56 | John-->Alice: Great!
57 | John->Bob: How about you?
58 | Bob-->John: Jolly good!
59 | {{< /mermaid >}}
60 |
61 | ## GANTT Example
62 |
63 | {{*mermaid*/>}}
64 | gantt
65 | dateFormat YYYY-MM-DD
66 | title Adding GANTT diagram functionality to mermaid
67 | section A section
68 | Completed task :done, des1, 2014-01-06,2014-01-08
69 | Active task :active, des2, 2014-01-09, 3d
70 | Future task : des3, after des2, 5d
71 | Future task2 : des4, after des3, 5d
72 | section Critical tasks
73 | Completed task in the critical line :crit, done, 2014-01-06,24h
74 | Implement parser and jison :crit, done, after des1, 2d
75 | Create tests for parser :crit, active, 3d
76 | Future task in critical line :crit, 5d
77 | Create tests for renderer :2d
78 | Add to mermaid :1d
79 | {{* /mermaid */>}}
80 |
81 |
82 | render as
83 |
84 | {{}}
85 | gantt
86 | dateFormat YYYY-MM-DD
87 | title Adding GANTT diagram functionality to mermaid
88 | section A section
89 | Completed task :done, des1, 2014-01-06,2014-01-08
90 | Active task :active, des2, 2014-01-09, 3d
91 | Future task : des3, after des2, 5d
92 | Future task2 : des4, after des3, 5d
93 | section Critical tasks
94 | Completed task in the critical line :crit, done, 2014-01-06,24h
95 | Implement parser and jison :crit, done, after des1, 2d
96 | Create tests for parser :crit, active, 3d
97 | Future task in critical line :crit, 5d
98 | Create tests for renderer :2d
99 | Add to mermaid :1d
100 | {{}}
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/mermaid.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title : "Mermaid"
3 | description : "Génération de diagrammes à partir de texte, dans le même style que Markdown"
4 | ---
5 |
6 | [Mermaid](https://mermaidjs.github.io/) est une bibliothèque Javascript qui permet de générer des diagrammes (séquence, état, gantt, etc.) à partir de texte, dans le même style que Markdown.
7 |
8 | Insérer votre code Mermaid dans un shortcode `mermaid` et c'est tout.
9 |
10 | ## Flowchart example
11 | {{*mermaid align="left"*/>}}
12 | graph LR;
13 | A[Bords droits] -->|Lien texte| B(Bords arondis)
14 | B --> C{Décision}
15 | C -->|Un| D[Résultat un]
16 | C -->|Deux| E[Résultat deux]
17 | {{* /mermaid */>}}
18 |
19 | renders as
20 |
21 | {{}}
22 | graph LR;
23 | A[Bords droits] -->|Lien texte| B(Bords arondis)
24 | B --> C{Décision}
25 | C -->|Un| D[Résultat un]
26 | C -->|Deux| E[Résultat deux]
27 | {{< /mermaid >}}
28 |
29 | ## Sequence example
30 |
31 | {{*mermaid*/>}}
32 | sequenceDiagram
33 | participant Alice
34 | participant Bob
35 | Alice->>John: Salut John, comment vas-tu?
36 | loop Vérification
37 | John->John: Se bat contre l'hyponcodrie.
38 | end
39 | Note right of John: Les pensées rationnelles prédominent...
40 | John-->Alice: Super!
41 | John->Bob: Et toi?
42 | Bob-->John: Au top!
43 | {{* /mermaid */>}}
44 |
45 | renders as
46 |
47 | {{}}
48 | sequenceDiagram
49 | participant Alice
50 | participant Bob
51 | Alice->>John: Salut John, comment vas-tu?
52 | loop Vérification
53 | John->John: Se bat contre l'hyponcodrie.
54 | end
55 | Note right of John: Les pensées rationnelles prédominent...
56 | John-->Alice: Super!
57 | John->Bob: Et toi?
58 | Bob-->John: Au top!
59 | {{< /mermaid >}}
60 |
61 | ## GANTT Example
62 |
63 | {{*mermaid*/>}}
64 | gantt
65 | dateFormat YYYY-MM-DD
66 | title Ajout de la fonctionnalité de GANTT à Mermaid
67 | section Une section
68 | Tâche complétée :done, des1, 2014-01-06,2014-01-08
69 | Tâche en cours :active, des2, 2014-01-09, 3d
70 | Future tâche : des3, after des2, 5d
71 | Future tâche 2 : des4, after des3, 5d
72 | section Tâches critiques
73 | Tâche complétée dans le chemin critique :crit, done, 2014-01-06,24h
74 | Implémenter le parser et jison :crit, done, after des1, 2d
75 | Créer des tests pour le parser :crit, active, 3d
76 | Future tâche dans le chemin critique :crit, 5d
77 | Créer des tests pour le renderer :2d
78 | Ajout à Mermaid :1d
79 | {{* /mermaid */>}}
80 |
81 |
82 | render as
83 |
84 | {{}}
85 | gantt
86 | dateFormat YYYY-MM-DD
87 | title Ajout de la fonctionnalité de GANTT à Mermaid
88 | section Une section
89 | Tâche complétée :done, des1, 2014-01-06,2014-01-08
90 | Tâche en cours :active, des2, 2014-01-09, 3d
91 | Future tâche : des3, after des2, 5d
92 | Future tâche 2 : des4, after des3, 5d
93 | section Tâches critiques
94 | Tâche complétée dans le chemin critique :crit, done, 2014-01-06,24h
95 | Implémenter le parser et jison :crit, done, after des1, 2d
96 | Créer des tests pour le parser :crit, active, 3d
97 | Future tâche dans le chemin critique :crit, 5d
98 | Créer des tests pour le renderer :2d
99 | Ajout à Mermaid :1d
100 | {{}}
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/notice.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Notice
3 | description : "Disclaimers to help you structure your page"
4 | ---
5 |
6 | The notice shortcode shows 4 types of disclaimers to help you structure your page.
7 |
8 | ### Note
9 |
10 | ```
11 | {{%/* notice note */%}}
12 | A notice disclaimer
13 | {{%/* /notice */%}}
14 | ```
15 |
16 | renders as
17 |
18 | {{% notice note %}}
19 | A notice disclaimer
20 | {{% /notice %}}
21 |
22 | ### Info
23 |
24 | ```
25 | {{%/* notice info */%}}
26 | An information disclaimer
27 | {{%/* /notice */%}}
28 | ```
29 |
30 | renders as
31 |
32 | {{% notice info %}}
33 | An information disclaimer
34 | {{% /notice %}}
35 |
36 | ### Tip
37 |
38 | ```
39 | {{%/* notice tip */%}}
40 | A tip disclaimer
41 | {{%/* /notice */%}}
42 | ```
43 |
44 | renders as
45 |
46 | {{% notice tip %}}
47 | A tip disclaimer
48 | {{% /notice %}}
49 |
50 | ### Warning
51 |
52 | ```
53 | {{%/* notice warning */%}}
54 | An warning disclaimer
55 | {{%/* /notice */%}}
56 | ```
57 |
58 | renders as
59 |
60 | {{% notice warning %}}
61 | A warning disclaimer
62 | {{% /notice %}}
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/notice.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Notice
3 | description : "Message pour vous aider à structurer votre contenu"
4 | ---
5 |
6 | Le shortcode *Notice* permet d'afficher 4 types de message pour vous aider à structurer votre contenu.
7 |
8 | ### Note
9 |
10 | ```
11 | {{%/* notice note */%}}
12 | Une notice de type *note*
13 | {{%/* /notice */%}}
14 | ```
15 |
16 | s'affiche comme
17 |
18 | {{% notice note %}}
19 | Une notice de type *note*
20 | {{% /notice %}}
21 |
22 | ### Info
23 |
24 | ```
25 | {{%/* notice info */%}}
26 | Une notice de type *info*
27 | {{%/* /notice */%}}
28 | ```
29 |
30 | s'affiche comme
31 |
32 | {{% notice info %}}
33 | Une notice de type *info*
34 | {{% /notice %}}
35 |
36 | ### Tip
37 |
38 | ```
39 | {{%/* notice tip */%}}
40 | Une notice de type *tip*
41 | {{%/* /notice */%}}
42 | ```
43 |
44 | s'affiche comme
45 |
46 | {{% notice tip %}}
47 | Une notice de type *tip*
48 | {{% /notice %}}
49 |
50 | ### Warning
51 |
52 | ```
53 | {{%/* notice warning */%}}
54 | Une notice de type *warning*
55 | {{%/* /notice */%}}
56 | ```
57 |
58 | s'affiche comme
59 |
60 | {{% notice warning %}}
61 | Une notice de type *warning*
62 | {{% /notice %}}
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/siteparam.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Site param
3 | description : "Get value of site params variables in your page."
4 | ---
5 |
6 | `siteparam` shortcode is used to help you print values of site params.
7 |
8 | For instance, in this current site, the `editURL` variable is used in `config.toml`
9 |
10 | ```toml
11 | [params]
12 | editURL = "https://github.com/matcornic/hugo-theme-learn/edit/master/exampleSite/content/"
13 | ```
14 |
15 | Use the `siteparam` shortcode to display its value.
16 |
17 | ```
18 | `editURL` Value : {{%/* siteparam "editURL" */%}}
19 | ```
20 |
21 | is displayed as
22 |
23 | `editURL` Value : {{% siteparam "editURL" %}}
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/shortcodes/siteparam.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Site param
3 | description : "Afficher la valeur d'un paramètre global du site dans votre page"
4 | ---
5 |
6 | Les shortcode `siteparam` est utilisé pour vous aider à afficher des valeurs provenant des paramètres globaux du site.
7 |
8 | Par exemple, dans ce site, le paramètre `editURL` est utilisé dans le fichier `config.toml`
9 |
10 | ```toml
11 | [params]
12 | editURL = "https://github.com/matcornic/hugo-theme-learn/edit/master/exampleSite/content/"
13 | ```
14 |
15 | Utilisez le shortcode `siteparam` pour affichier sa valeur.
16 |
17 | ```
18 | Valeur de `editURL` : {{%/* siteparam "editURL" */%}}
19 | ```
20 |
21 | s'affiche comme
22 |
23 | Valeur de `editURL` : {{% siteparam "editURL" %}}
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/showcase.en.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Showcase
3 | disableToc: true
4 | ---
5 |
6 | #### [TAT](https://ovh.github.io/tat/overview/) by OVH
7 | 
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/content/showcase.fr.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Vitrine
3 | disableToc: true
4 | slug: vitrine
5 | ---
6 |
7 | #### [TAT](https://ovh.github.io/tat/overview/) par OVH
8 | 
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/layouts/partials/custom-footer.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/layouts/partials/logo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/themes/hugo-theme-learn/exampleSite/layouts/partials/menu-footer.html:
--------------------------------------------------------------------------------
1 |