[
  {
    "path": ".dockerignore",
    "content": ".git\n.gitignore\ndocker-compose.yml\nDockerfile\n"
  },
  {
    "path": ".github/workflows/tests-macos.yml",
    "content": "name: MacOS Tests\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  build:\n    runs-on: macos-latest\n    steps:\n    - uses: actions/checkout@v4\n    - run: ./share/adapters/rfc.sh\n"
  },
  {
    "path": ".github/workflows/tests-ubuntu.yml",
    "content": "name: Ubuntu Tests\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n  schedule:\n    - cron:  '0 9 * * 4'\n\njobs:\n  build:\n    runs-on: ubuntu-24.04\n    steps:\n    - uses: actions/checkout@v4\n    - run: ./share/adapters/rfc.sh\n    - name: install dependencies\n      run: pip install --upgrade -r requirements.txt\n    - name: fetch upstream cheat sheets\n      run: python lib/fetch.py fetch-all\n    - name: run bash tests\n      run: bash tests/run-tests.sh\n    - name: run pytest\n      run: pytest lib/\n\n  docker:\n    runs-on: ubuntu-20.04\n    steps:\n    - uses: actions/checkout@v2\n    - run: docker-compose build\n    - run: docker images\n    - run: |\n        docker-compose -f docker-compose.yml up -d\n        # docker-compose -f docker-compose.yml -f docker-compose.debug.yml up -d\n        docker-compose ps\n        # wait until the web server is up\n        wget --timeout 3 --tries=5 --spider localhost:8002 2>&1 | grep -i http\n        docker-compose logs --no-color\n    - run: CHEATSH_TEST_STANDALONE=NO bash tests/run-tests.sh\n\n    \n"
  },
  {
    "path": ".gitignore",
    "content": "*.pyc\n*.swp\nlog/\nve/\nshare/vim/.vim/\nshare/vim/.viminfo\ntypescript\nvenv/\nbin/upstream\nupstream/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "There are several ways how you can \ncontribute to cheat.sh and make it better and more useful:\n\n1. Suggest a GitHub repository (or other information source) to be attached to cheat.sh. Just create an issue for it, where the name and the URL of the repository is specified. Please keep in mind, that the repository's license has to permit its usage by cheat.sh;\n2. Create an adapter for some repository and add it to cheat.sh;\n3. Create a Editor plugin for cheat.sh;\n4. Create a new cheat sheet in one of its upstream repositories;\n5. Go through the list of open issues, and try to fix some of them, or at least understand and share your opinion about them, if you have it.\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM alpine:3.14\n# fetching cheat sheets\n## installing dependencies\nRUN apk add --update --no-cache git py3-six py3-pygments py3-yaml py3-gevent \\\n      libstdc++ py3-colorama py3-requests py3-icu py3-redis sed\n## copying\nWORKDIR /app\nCOPY . /app\n## building missing python packages\nRUN apk add --no-cache --virtual build-deps py3-pip g++ python3-dev libffi-dev \\\n    && pip3 install --no-cache-dir --upgrade pygments \\\n    && pip3 install --no-cache-dir -r requirements.txt \\\n    && apk del build-deps\n## fetching cheat sheets\nRUN mkdir -p /root/.cheat.sh/log/ \\\n    && python3 lib/fetch.py fetch-all\n\n# installing server dependencies\nRUN apk add --update --no-cache py3-jinja2 py3-flask bash gawk\nENTRYPOINT [\"python3\", \"-u\", \"bin/srv.py\"]\nCMD [\"\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2025 Igor Chubin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "\n\n![cheat.sh logo](http://cheat.sh/files/big-logo-v2-fixed.png)\n\nUnified access to the best community driven cheat sheets repositories of the world.\n\nLet's imagine for a moment that there is such a thing as an ideal cheat sheet.\nWhat should it look like?\nWhat features should it have?\n\n* **Concise** — It should only contain the things you need, and nothing else.\n* **Fast** — It should be possible to use it instantly.\n* **Comprehensive** — It should contain answers for every possible question.\n* **Universal** — It should be available everywhere, anytime, without any preparations.\n* **Unobtrusive** — It should not distract you from your main task.\n* **Tutoring** — It should help you to learn the subject.\n* **Inconspicuous** — It should be possible to use it completely unnoticed.\n\nSuch a thing exists! It's easy to [install](#installation) and there's even [auto-complete](#tab-completion).\n\n\n## Features\n\n**cheat.sh**\n\n* Has a simple curl/browser/editor interface.\n* Covers 56 programming languages, several DBMSes, and more than 1000 most important UNIX/Linux commands.\n* Provides access to the best community driven cheat sheets repositories in the world, on par with StackOverflow.\n* Available everywhere, no installation needed, but can be installed for offline usage.\n* Ultrafast, returns answers within 100 ms, as a rule.\n* Has a convenient command line client, `cht.sh`, that is very advantageous and helpful, though not mandatory.\n* Can be used directly from code editors, without opening a browser and not switching your mental context.\n* Supports a special stealth mode where it can be used fully invisibly without ever touching a key and making sounds.\n\n<p align=\"center\">\n  <img src='https://cheat.sh/files/demo-curl.gif'/>\n</p>\n\n## Contents\n\n* [Features](#features)\n* [Usage](#usage)\n* [Command line client, cht.sh](#command-line-client-chtsh)\n  * [Installation](#installation)\n  * [Client usage](#client-usage)\n  * [Tab-completion](#tab-completion)\n    - [Bash Tab completion](#bash-tab-completion)\n    - [ZSH Tab completion](#zsh-tab-completion)\n  * [Stealth mode](#stealth-mode)\n  * [Windows command line client](#windows-command-line-client)\n* [Self-Hosting](#self-hosting)\n  * [Docker](#docker)\n* [Editors integration](#editors-integration)\n  * [Vim](#vim)\n  * [Emacs](#emacs)\n  * [Visual Studio Code](#visual-studio-code)\n  * [Sublime](#sublime)\n  * [IntelliJ IDEA](#intellij-idea)\n  * [QT Creator](#qtcreator)\n* [Special pages](#special-pages)\n* [Search](#search)\n* [Programming languages cheat sheets](#programming-languages-cheat-sheets)\n* [Cheat sheets sources](#cheat-sheets-sources)\n* [How to contribute](#how-to-contribute)\n  * [How to edit a cheat sheet](#how-to-edit-a-cheat-sheet)\n  * [How to add a cheat sheet](#how-to-add-a-cheat-sheet)\n  * [How to add a cheat sheet repository](#how-to-add-a-cheat-sheet-repository)\n\n## Usage\n\nTo get a cheat sheet for a UNIX/Linux command from a command line, query the service using `curl` or any other HTTP/HTTPS client\nspecifying the name of the command in the query:\n\n```\n    curl cheat.sh/tar\n    curl cht.sh/curl\n    curl https://cheat.sh/rsync\n    curl https://cht.sh/tr\n```\nAs you can see, you can use both HTTPS and HTTP to access the service, and both the long (cheat.sh) and the short (cht.sh) service names.\n\nHere `tar`, `curl`, `rsync`, and `tr` are names of the UNIX/Linux commands you want to get cheat sheets for.\n\nIf you don't know the name of the command you need, you can search for it using the `~KEYWORD` notation.\nFor example, to see how you can make `snapshots` of a filesystem/volume/something else:\n```\n    curl cht.sh/~snapshot\n```\n\n<p align=\"center\">\n  <img src='https://cheat.sh/files/cht.sh-url-structure.png'/>\n</p>\n\nThe programming language cheat sheets are located in special namespaces dedicated to them.\n\n```\n    curl cht.sh/go/Pointers\n    curl cht.sh/scala/Functions\n    curl cht.sh/python/lambda\n```\n\nTo get the list of available programming language cheat sheets, use the special query `:list`:\n\n```\n    curl cht.sh/go/:list\n```\n\nAlmost each programming language has a special page named `:learn`\nthat describes the language basics (that's a direct mapping from the *\"Learn X in Y\"* project).\nIt could be a good starting point if you've just started learning a language.\n\nIf there is no cheat sheet for a programming language query (and it is almost always the case),\nit is generated on the fly, based on available cheat sheets and answers on StackOverflow.\nOf course, there is no guarantee that the returned cheat sheet will be a 100% hit, but it is almost always exactly what you are looking for.\n\nTry these (and your own) queries to get the impression of that, what the answers look like:\n```\n    curl cht.sh/go/reverse+a+list\n    curl cht.sh/python/random+list+elements\n    curl cht.sh/js/parse+json\n    curl cht.sh/lua/merge+tables\n    curl cht.sh/clojure/variadic+function\n```\n\nIf you don't like an answer for your queries, you can pick another one. For that, repeat the query with an additional parameter `/1`, `/2` etc. appended:\n\n```\n    curl cht.sh/python/random+string\n    curl cht.sh/python/random+string/1\n    curl cht.sh/python/random+string/2\n```\n\nCheat sheets are formatted as code of the queried programming language (at least we are trying our best to do so)\nso they can be pasted into a program in this language directly. Text comments, if there are any, are formatted according to the language syntax.\n\n```lua\n    $ curl cht.sh/lua/table+keys\n    -- lua: retrieve list of keys in a table\n\n    local keyset={}\n    local n=0\n\n    for k,v in pairs(tab) do\n      n=n+1\n      keyset[n]=k\n    end\n\n    --[[\n       [ Note that you cannot guarantee any order in keyset. If you want the\n       [ keys in sorted order, then sort keyset with table.sort(keyset).\n       [ \n       [ [lhf] [so/q/12674345] [cc by-sa 3.0]\n       ]]\n\n```\n\nIf you don't need text comments in the answer, you can eliminate them\nusing a special option `\\?Q`:\n```lua\n    $ curl cht.sh/lua/table+keys\\?Q\n    local keyset={}\n    local n=0\n\n    for k,v in pairs(tab) do\n      n=n+1\n      keyset[n]=k\n    end\n```\n\nAnd if you don't need syntax highlighting, switch it off using `\\?T`.\nYou can combine the options together:\n\n```\n    curl cht.sh/go/reverse+a+list\\?Q\n    curl cht.sh/python/random+list+elements\\?Q\n    curl cht.sh/js/parse+json\\?Q\n    curl cht.sh/lua/merge+tables\\?QT\n    curl cht.sh/clojure/variadic+function\\?QT\n```\n\nFull list of all options described below and in `/:help`.\n\nTry your own queries. Follow these rules:\n\n1. Try to be more specific (`/python/append+file` is better than `/python/file` and `/python/append`).\n2. Ask practical question if possible (yet theoretical question are possible too).\n3. Ask programming language questions only; specify the name of the programming language as the section name.\n4. Separate words with `+` instead of spaces.\n5. Do not use special characters, they are ignored anyway.\n6. If you want to eliminate cheat sheets containing some word, add it to the query with `+-`: `python/multiply+matrices+-numpy`\n\nRead more about the programming languages queries below.\n\n----\n\n## Command line client, cht.sh\n\nThe cheat.sh service has its own command line client (`cht.sh`) that\nhas several useful features compared to querying the service directly with `curl`:\n\n* Special shell mode with a persistent queries context and readline support.\n* Queries history.\n* Clipboard integration.\n* Tab completion support for shells (bash, fish, zsh).\n* Stealth mode.\n\n### Installation\n\nTo install the client:\n\n```bash\nPATH_DIR=\"$HOME/bin\"  # or another directory on your $PATH\nmkdir -p \"$PATH_DIR\"\ncurl https://cht.sh/:cht.sh > \"$PATH_DIR/cht.sh\"\nchmod +x \"$PATH_DIR/cht.sh\"\n```\n\nor to install it globally (for all users):\n\n```bash\ncurl -s https://cht.sh/:cht.sh | sudo tee /usr/local/bin/cht.sh && sudo chmod +x /usr/local/bin/cht.sh\n```\n\nNote: The package \"rlwrap\" is a required dependency to run in shell mode. Install this using `sudo apt install rlwrap`\n\n### Client usage\n\nNow, you can use `cht.sh` instead of `curl`, and write your queries in more natural way,\nwith spaces instead of `+`:\n\n```\n    $ cht.sh go reverse a list\n    $ cht.sh python random list elements\n    $ cht.sh js parse json\n```\n\nIt is even more convenient to start the client in a special shell mode:\n```\n    $ cht.sh --shell\n    cht.sh> go reverse a list\n```\n\nIf all your queries are about the same language, you can change the context\nand spare repeating the programming language name:\n```\n    $ cht.sh --shell\n    cht.sh> cd go\n    cht.sh/go> reverse a list\n```\nor even start the client in this context:\n```\n    $ cht.sh --shell go\n    cht.sh/go> reverse a list\n    ...\n    cht.sh/go> join a list\n    ...\n```\n\nIf you want to change the context, you can do it with the `cd` command,\nor if you want do a single query for some other language, just prepend it with `/`:\n\n```\n    $ cht.sh --shell go\n    ...\n    cht.sh/go> /python dictionary comprehension\n    ...\n```\n\nIf you want to copy the last answer into the clipboard, you can\nuse the `c` (`copy`) command, or `C` (`ccopy`, without comments).\n\n```\n    cht.sh/python> append file\n    #  python - How do you append to a file?\n\n    with open(\"test.txt\", \"a\") as myfile:\n        myfile.write(\"appended text\")\n    cht.sh/python> C\n    copy: 2 lines copied to the selection\n```\n\nType `help` for other internal `cht.sh` commands.\n\n```\n\tcht.sh> help\n\thelp    - show this help\n\thush    - do not show the 'help' string at start anymore\n\tcd LANG - change the language context\n\tcopy    - copy the last answer in the clipboard (aliases: yank, y, c)\n\tccopy   - copy the last answer w/o comments (cut comments; aliases: cc, Y, C)\n\texit    - exit the cheat shell (aliases: quit, ^D)\n\tid [ID] - set/show an unique session id (\"reset\" to reset, \"remove\" to remove)\n\tstealth - stealth mode (automatic queries for selected text)\n\tupdate  - self update (only if the scriptfile is writeable)\n\tversion - show current cht.sh version\n\t/:help  - service help\n\tQUERY   - space separated query staring (examples are below)\n\t\t\t\t  cht.sh> python zip list\n\t\t\t\t  cht.sh/python> zip list\n\t\t\t\t  cht.sh/go> /python zip list\n```\n\nThe `cht.sh` client has its configuration file which is located at `~/.cht.sh/cht.sh.conf`\n(location of the file can be overridden by the environment variable `CHTSH_CONF`).\nUse it to specify query options that you would use with each query.\nFor example, to switch syntax highlighting off create the file with the following\ncontent:\n\n```bash\nCHTSH_QUERY_OPTIONS=\"T\"\n```\n\nOr if you want to use a special syntax highlighting theme:\n\n```bash\nCHTSH_QUERY_OPTIONS=\"style=native\"\n```\n\n(`curl cht.sh/:styles-demo` to see all supported styles).\n\nOther cht.sh configuration parameters:\n\n```bash\nCHTSH_CURL_OPTIONS=\"-A curl\"        # curl options used for cht.sh queries\nCHTSH_URL=https://cht.sh            # URL of the cheat.sh server\n```\n\n### Tab completion\n\n\n#### Bash Tab completion\n\nTo activate tab completion support for `cht.sh`, add the `:bash_completion` script to your `~/.bashrc`:\n\n```bash\n    curl https://cheat.sh/:bash_completion > ~/.bash.d/cht.sh\n    . ~/.bash.d/cht.sh\n    # and add . ~/.bash.d/cht.sh to ~/.bashrc\n```\n\n#### ZSH Tab completion\n\nTo activate tab completion support for `cht.sh`, add the `:zsh` script to the *fpath* in your `~/.zshrc`:\n\n```zsh\n    curl https://cheat.sh/:zsh > ~/.zsh.d/_cht\n    echo 'fpath=(~/.zsh.d/ $fpath)' >> ~/.zshrc\n    # Open a new shell to load the plugin\n```\n\n----\n\n### Stealth mode\n\nBeing used fully unnoticed is one of the most important property of any cheat sheet.\n\ncheat.sh can be used completely unnoticed too. The cheat.sh client, `cht.sh`, has\na special mode, called **stealth mode**. Using that, you don't even need to touch your\nkeyboard to open a cheat sheet.\n\nIn this mode, as soon as you select some text with the mouse (and thus adding it\ninto the selection buffer of X Window System or into the clipboard) it's used\nas a query string for cheat.sh, and the correspondent cheat sheet is automatically shown.\n\nLet's imagine, that you are having an online interview, where your interviewer asks you\nsome questions using a shared document (say Google Docs) and you are supposed\nto write your coding answers there (it's possible too that you'll type in the questions\non your own, just to show to the interviewer that you've heard it right).\n\nWhen using the stealth mode of `cht.sh`, the only thing you need to do in order to see\na cheat sheet for some question, is to select the question using the mouse.\nIf you don't want any text in the answers and the only thing you need is code,\nuse the `Q` option when starting the stealth mode.\n\n<p align=\"center\">\n  <img src='https://cheat.sh/files/stealth-mode.gif'/>\n</p>\n\n```\nYou: Hi!                                            | $ cht.sh --shell python\nShe: Hi!                                            | cht.sh/python> stealth Q\nShe: Are you ready for a small interview?           | stealth: you are in the stealth mode; select any text\nShe: Just a couple of questions                     | stealth: selections longer than 5 words are ignored\nShe: We will talk about python                      | stealth: query arguments: ?Q\nShe: Let's start from something simple.             | stealth: use ^C to leave this mode\nShe: Do you know how to reverse a list in python?   |\nYou: Sure                                           |\nYou: (selecting \"reverse a list\")                   | stealth: reverse a list\n                                                    | reverse_lst = lst[::-1]\nYou: lst[::-1]?                                     |\nShe: Good.                                          |\nShe: Do you know how to chain a list of lists?      |\nYou: (selecting \"chain a list of lists\")            | stealth: chain a list of lists\n                                                    | import itertools\n                                                    | a = [[\"a\",\"b\"], [\"c\"]]\n                                                    | print list(itertools.chain.from_iterable(a))\nYou: May I use external modules?                    |\nShe: What module do you want to use?                |\nYou: itertools                                      |\nShe: Yes, you may use it                            |\nYou: Ok, then:                                      |\nYou: itertools.chain.from_iterable(a)               |\nShe: Good. Let's try something harder.              |\nShe: What about quicksort implementation?           |\nYou: (selecting \"quicksort implementation\")         | stealth: quicksort implementation\nYou: Let me think about it.                         | (some big and clumsy lowlevel implementation shown)\nYou: Well...(starting typing it in)                 | def sort(array=[12,4,5,6,7,3,1,15]):\n                                                    |     less = []\nShe: (seeing your ugly pascal style)                |     equal = []\nShe: Could you write it more concise?               |     greater = []\n                                                    |     if len(array) > 1:\nYou: What do you mean?                              |         pivot = array[0]\n                                                    |         for x in array:\nShe: I mean,                                        |             if x < pivot: less.append(x)\nShe: do you really need all these ifs and fors?     |             if x == pivot: equal.append(x)\nShe: Could you maybe just use filter instead?       |             if x > pivot: greater.append(x)\n                                                    |         return sort(less)+equal+sort(greater)\nYou: quicksort with filter?                         |     else:\n                                                    |         return array\nShe: Yes                                            |\nYou: (selecting \"quicksort with filter\")            | stealth: quicksort with filter\nYou: Ok, I will try.                                | return qsort(filter(lt, L[1:]))+[pivot] \\\nYou: Something like this?                           |     +qsort(filter(ge, L[1:]))\nYou: qsort(filter(lt, L[1:]))+[pivot] \\             |\n       + qsort(filter(ge, L[1:]))                   |\n                                                    |\nShe: Yes! Perfect! Exactly what I wanted to see!    |\n                                                    |\n\n```\n\nOf course, this is just for fun, and you should never cheat in your coding interviews,\nbecause you know what happens when you do.\n\n![when you lie in your interview](http://cheat.sh/files/when-you-lie-katze.png)\n\n### Windows command line client\n\nYou can access cheat.sh from Windows command line too.\n\nUse cheat.sh command line client for that: [`cht.exe`](https://github.com/tpanj/cht.exe).\nIt supports:\n\n* output colorization;\n* command line options;\n* its own configuration file.\n\nYou can also use [`scoop`](https://github.com/lukesampson/scoop) command-line installer for Windows to get it:\n```batch\nscoop install cht\n```\n\n----\n\n## Self-Hosting\n\n### Docker\n\nCurrently, the easiest way to get a self-hosted instance running is by using\nthe `docker-compose.yml` file.\n\n    docker-compose up\n\nThis builds and runs the image with baked in cheatsheets and starts the app\nand a Redis instance to back it, making the service available at\nhttp://localhost:8002 This is currently an early implementation and should\nprobably not be used for anything outside of internal/dev/personal use right\nnow.\n\n## Editors integration\n\nYou can use *cheat.sh* directly from the editor\n(*Emacs*, *Sublime*, *Vim*, and *Visual Studio Code* are currently supported;\nnot all features are supported by all plugins though; see below).\nInstead of opening your browser, googling, browsing Stack Overflow\nand eventually copying the code snippets you need into the clipboard\nand later pasting them into the editor,\nyou can achieve the same instantly and without leaving the editor at all!\n\nHere is what it looks like in Vim:\n\n1. If you have a question while editing a program, you can just type\nyour question directly in the buffer and press `<leader>KK`. You will get\nthe answer to your question in pager. (with `<leader>KB` you'll get the answer\nin a separate buffer).\n\n2. If you like the answer, you can manually paste it from the buffer or\nthe pager, or if you are lazy you can use `<leader>KP` to paste it below/under\nyour question (or replace you question using `<leader>KR`). If you want the\nanswer without the comments, `<leader>KC` replays the last query\ntoggling them.\n\nIf you use some static analysis plugin such as *syntastic* (for Vim), you can use\nits warning and error messages as cheat.sh queries: place the cursor on the problem line\nand press `<leader>KE`: explanation for the warning will be opened in a new buffer.\n\nFeatures supported by cheat.sh plugins for different editors:\n\n|Feature            |Emacs|Sublime|Vim|VSCode|IDEA|QtCreator|\n|-------------------|-----|-------|---|------|----|---------|\n|Command queries    |✓    |✓      |✓  |✓     |✓   |✓        |\n|Queries from buffer|     |       |✓  |✓     |    |✓        |\n|Toggle comments    |     |       |✓  |✓     |✓   |✓        |\n|Prev/next answer   |     |       |✓  |✓     |✓   |✓        |\n|Multiple answers   |     |✓      |   |      |✓   |         |\n|Warnings as queries|     |       |✓  |      |    |         |\n|Queries history    |     |       |✓  |✓     |    |         |\n|Session id         |     |       |✓  |      |    |         |\n|Configurable server|✓    |       |✓  |✓     |    |✓        |\n\n### Vim\n\n* [cheat.sh-vim](https://github.com/dbeniamine/cheat.sh-vim) — Vim support\n\nHere is Vim configuration example:\n\n```vim\n\" some configuration above ...\n\nlet mapleader=\" \"\n\ncall vundle#begin()\nBundle 'gmarik/vundle'\nBundle 'scrooloose/syntastic'\nBundle 'dbeniamine/cheat.sh-vim'\ncall vundle#end()\n\nlet g:syntastic_javascript_checkers = [ 'jshint' ]\nlet g:syntastic_ocaml_checkers = ['merlin']\nlet g:syntastic_python_checkers = ['pylint']\nlet g:syntastic_shell_checkers = ['shellcheck']\n\n\" some configuration below ...\n```\n\nIn this example, several Vim plugins are used:\n\n* [gmarik/vundle](https://github.com/VundleVim/Vundle.vim) — Vim plugin manager\n* [scrooloose/syntastic](https://github.com/vim-syntastic/syntastic) — Syntax checking plugin\n* [cheat.sh-vim](https://github.com/dbeniamine/cheat.sh-vim) — Vim support\n\nSyntastic shows warnings and errors (found by code analysis tools: `jshint`, `merlin`, `pylint`, `shellcheck` etc.),\nand `cheat.sh-vim` shows you explanations for the errors and warnings\nand answers on programming languages queries written in the editor.\n\nWatch a demo, where the most important features of the cheat.sh Vim plugin are shown (5 Min):\n\n<p align=\"center\">\n  <img src='https://cheat.sh/files/vim-demo.gif'/>\n</p>\n\nOr, if you want to scroll and/or pause, the same on YouTube:\n\n<p align=\"center\">\n  <a href=\"http://www.youtube.com/watch?feature=player_embedded&v=xyf6MJ0y-z8\n  \" target=\"_blank\"><img src=\"http://img.youtube.com/vi/xyf6MJ0y-z8/0.jpg\" \n  alt=\"cheat.sh-vim: Using cheat.sh from vim\" width=\"700\" height=\"490\" border=\"10\" /></a>\n</p>\n\n<!-- [![asciicast](https://asciinema.org/a/c6QRIhus7np2OOQzmQ2RNXzRZ.png)](https://asciinema.org/a/c6QRIhus7np2OOQzmQ2RNXzRZ) -->\n\n### Emacs\n\n* [cheat-sh.el](https://github.com/davep/cheat-sh.el) — Emacs support (available also at cheat.sh/:emacs)\n* cheat.sh/:emacs-ivy — Emacs support for ivy users\n\n[![asciicast](https://asciinema.org/a/3xvqwrsu9g4taj5w526sb2t35.png)](https://asciinema.org/a/3xvqwrsu9g4taj5w526sb2t35)\n\n\n### Visual Studio Code\n\n* [vscode-snippet](https://github.com/mre/vscode-snippet)\n* Install it from [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=vscode-snippet.Snippet)\n\nUsage: \n\n1. Hit <kbd>⌘ Command</kbd> + <kbd>⇧ Shift</kbd> + <kbd>p</kbd>\n2. Run `Snippet: Find`.\n3. Type your query and hit enter.\n\n[![vscode-snippet](https://cheat.sh/files/vscode-snippet-demo.gif)](https://github.com/mre/vscode-snippet)\n\n*(GIF courtesy: Matthias Endler, @mre)*\n\n### Sublime\n\n* [cheat.sh-sublime-plugin](https://github.com/gauravk-in/cheat.sh-sublime-plugin/)\n\nUsage:\n\n1.  Write your query string.\n2.  Select the query string.\n3.  Press <kbd>Cmd</kbd> + <kbd>⇧ Shift</kbd> + <kbd>B</kbd> to replace the selected query string by the answer generated from `cht.sh`.\n\n[![cheat.sh-sublime-plugin-demo](https://cheat.sh/files/demo-sublime.gif)](https://github.com/gauravk-in/cheat.sh-sublime-plugin)\n\n*(GIF courtesy: Gaurav Kukreja, @gauravk-in)*\n\n### IntelliJ IDEA \n\n* [idea-cheatsh-plugin](https://github.com/szymonprz/idea-cheatsh-plugin)\n* Install from [idea plugins marketplace](https://plugins.jetbrains.com/plugin/11942-cheat-sh-code-snippets) \n\nUsage: \n\n1. Write query string\n2. Select the query string\n3. Press keyboard shortcut <kbd>Alt</kbd> + <kbd>C</kbd> , <kbd>S</kbd> to replace the selected query string by the answer\n\n[![idea-cheatsh-plugin](https://cheat.sh/files/idea-demo.gif)](https://github.com/szymonprz/idea-cheatsh-plugin)\n\n*(GIF courtesy: Szymon Przebierowski, @szymonprz)*\n\n### QtCreator\n\n* [cheatsh-qtcreator](https://github.com/pozemka/cheatsh-qtcreator)\n\nCurrent features:\n\n*    search word under cursor\n*    search selected\n*    query search\n*    disable comments\n*    paste answer (?TQ version)\n*    custom server URL\n*    custom search context (default is cpp)\n*    hotkeys and menu\n\n[![cheatsh-qtcreator](https://user-images.githubusercontent.com/1259724/73876361-ecce5d00-4867-11ea-9f75-c5b127a9739c.gif)](https://github.com/pozemka/cheatsh-qtcreator)\n\n*(GIF courtesy: Pozemka, @pozemka)*\n\n## Special pages\n\nThere are several special pages that are not cheat sheets.\nTheir names start with colon and have special meaning.\n\n\nGetting started:\n\n```\n    :help               description of all special pages and options\n    :intro              cheat.sh introduction, covering the most important usage questions\n    :list               list all cheat sheets (can be used in a subsection too: /go/:list)\n```\n\nCommand line client `cht.sh` and shells support:\n```\n    :cht.sh             code of the cht.sh client\n    :bash_completion    bash function for tab completion\n    :bash               bash function and tab completion setup\n    :fish               fish function and tab completion setup\n    :zsh                zsh function and tab completion setup\n```\n\nEditors support:\n\n```\n    :vim                cheat.sh support for Vim\n    :emacs              cheat.sh function for Emacs\n    :emacs-ivy          cheat.sh function for Emacs (uses ivy)\n```\n\nOther pages:\n\n```\n    :post               how to post new cheat sheet\n    :styles             list of color styles\n    :styles-demo        show color styles usage examples\n    :random             fetches a random page (can be used in a subsection too: /go/:random)\n```\n\n## Search\n\nTo search for a keyword, use the query:\n\n```\n    /~keyword\n```\n\nIn this case search is not recursive — it is conducted only in a page of the specified level.\nFor example:\n\n```\n    /~snapshot          look for snapshot in the first level cheat sheets\n    /scala/~currying     look for currying in scala cheat sheets\n```\n\nFor a recursive search in all cheat sheets, use double slash:\n\n```\n    /~snapshot/r         look for snapshot in all cheat sheets\n```\n\nYou can use special search options after the closing slash:\n\n```\n    /~shot/bi           case insensitive (i), word boundaries (b)\n```\n\nList of search options:\n\n```\n    i   case insensitive search\n    b   word boundaries\n    r   recursive search\n```\n\n## Programming languages cheat sheets\n\nCheat sheets related to programming languages\nare organized in namespaces (subdirectories), that are named according\nto the programming language.\n\nFor each supported programming language\nthere are several special cheat sheets: its own sheet, `hello`, `:list` and `:learn`.\nSay for lua it will look like:\n\n```\n    lua\n    lua/hello\n    lua/:list\n    lua/:learn\n```\n\nSome languages has the one-liners-cheat sheet, `1line`:\n\n```\n    perl/1line\n```\n* `hello` describes how you can start with the language — install it if needed, build and run its programs, and it shows the \"Hello world\" program written in the language;\n* `:list` shows all topics related to the language\n* `:learn` shows a learn-x-in-minutes language cheat sheet perfect for getting started with the language.\n* `1line` is a collection of one-liners in this language\n* `weirdness` is a collection of examples of weird things in this language\n\n![cheat.sh usage](http://cheat.sh/files/supported-languages-c++.png)\n\nAt the moment, cheat.sh covers the 58 following programming languages (alphabetically sorted):\n\n|Prefix     |Language  |Basics|One-liners|Weirdness|StackOverflow|\n|-----------|----------|------|----------|---------|-------------|\n|`arduino/` |Arduino   |      |          |         |✓            |\n|`assembly/`|Assembly  |      |          |         |✓            |\n|`awk/`     |AWK       |✓     |          |         |✓            |\n|`bash/`    |Bash      |✓     |          |         |✓            |\n|`basic/`   |BASIC     |      |          |         |✓            |\n|`bf/`      |Brainfuck |✓     |          |         |✓            |\n|`c/`       |C         |✓     |          |         |✓            |\n|`chapel/`  |Chapel    |✓     |          |         |✓            |\n|`clean/`   |Clean     |      |          |         |✓            |\n|`clojure/` |Clojure   |✓     |          |         |✓            |\n|`coffee/`  |CoffeeScript|✓   |          |         |✓            |\n|`cpp/`     |C++       |✓     |          |         |✓            |\n|`csharp/`  |C#        |✓     |          |         |✓            |\n|`d/`       |D         |✓     |          |         |✓            |\n|`dart/`    |Dart      |✓     |          |         |✓            |\n|`delphi/`  |Dephi     |      |          |         |✓            |\n|`dylan/`   |Dylan     |✓     |          |         |✓            |\n|`eiffel/`  |Eiffel    |      |          |         |✓            |\n|`elixir/`  |Elixir    |✓     |          |         |✓            |\n|`elisp/`   |ELisp     |✓     |          |         |✓            |\n|`elm/`     |Elm       |✓     |          |         |✓            |\n|`erlang/`  |Erlang    |✓     |          |         |✓            |\n|`factor/`  |Factor    |✓     |          |         |✓            |\n|`fortran/` |Fortran   |✓     |          |         |✓            |\n|`forth/`   |Forth     |✓     |          |         |✓            |\n|`fsharp/`  |F#        |✓     |          |         |✓            |\n|`go/`      |Go        |✓     |          |         |✓            |\n|`groovy/`  |Groovy    |✓     |          |         |✓            |\n|`haskell/` |Haskell   |✓     |          |         |✓            |\n|`java/`    |Java      |✓     |          |         |✓            |\n|`js/`      |JavaScript|✓     |✓         |✓        |✓            |\n|`julia/`   |Julia     |✓     |          |         |✓            |\n|`kotlin/`  |Kotlin    |✓     |          |         |✓            |\n|`latex/`   |LaTeX     |✓     |          |         |✓            |\n|`lisp/`    |Lisp      |✓     |          |         |✓            |\n|`lua/`     |Lua       |✓     |          |         |✓            |\n|`matlab/`  |MATLAB    |✓     |          |         |✓            |\n|`nim/`     |Nim       |✓     |          |         |✓            |\n|`ocaml/`   |OCaml     |✓     |          |         |✓            |\n|`octave/`  |Octave    |✓     |          |         |✓            |\n|`perl/`    |Perl      |✓     |✓         |         |✓            |\n|`perl6/`   |Perl 6    |✓     |✓         |         |✓            |\n|`php/`     |PHP       |✓     |          |         |✓            |\n|`pike/`    |Pike      |      |          |         |✓            |\n|`python/`  |Python    |✓     |✓         |         |✓            |\n|`python3/` |Python 3  |✓     |          |         |✓            |\n|`r/`       |R         |✓     |          |         |✓            |\n|`racket/`  |Racket    |✓     |          |         |✓            |\n|`ruby/`    |Ruby      |✓     |          |         |✓            |\n|`rust/`    |Rust      |✓     |          |         |✓            |\n|`scala/`   |Scala     |✓     |          |         |✓            |\n|`scheme/`  |Scheme    |✓     |          |         |✓            |\n|`solidity/`|Solidity  |✓     |          |         |✓            |\n|`swift/`   |Swift     |✓     |          |         |✓            |\n|`tcsh/`    |Tcsh      |✓     |          |         |✓            |\n|`tcl/`     |Tcl       |✓     |          |         |✓            |\n|`objective-c/`|Objective-C|✓ |          |         |✓            |\n|`vb/`      |VisualBasic|✓    |          |         |✓            |\n|`vbnet/`   |VB.Net    |✓     |          |         |✓            |\n\nAnd several other topics, that are though related to programming,\nare not programming languages:\n\n|Prefix     |Topic     |Basics|StackOverflow|\n|-----------|----------|------|-------------|\n|`cmake/`   |CMake     |✓     |✓            |\n|`django/`  |Django    |      |✓            |\n|`flask/`   |Flask     |      |✓            |\n|`git/`     |Git       |✓     |✓            |\n\n## Cheat sheets sources\n\nInstead of creating yet another mediocre cheat sheet repository,\nwe are concentrating our efforts on creation of a unified\nmechanism to access selected existing well developed and good maintained\ncheat sheet repositories covering topics of our interest:\nprogramming and operating systems usage.\n\n*cheat.sh* uses selected community driven cheat sheet repositories\nand information sources, maintained by thousands of users, developers and authors\nall over the world\n(in the *Users* column number of contributors/number of stars is shown):\n\n| Cheat sheets            | Repository                                                                          | C/U*                                                                                                                    | Stars                                                                                                    | Creation Date |\n|-------------------------|-------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|---------------|\n| UNIX/Linux, programming | [cheat.sheets](https://github.com/chubin/cheat.sheets)                              | ![](https://img.shields.io/github/contributors-anon/chubin/cheat.sheets?label=%F0%9F%91%A5&labelColor=white)            | ![](https://img.shields.io/github/stars/chubin/cheat.sheets?label=%E2%AD%90&labelColor=white)            | May 1, 2017   |\n| UNIX/Linux commands     | [tldr-pages/tldr](https://github.com/tldr-pages/tldr)                               | ![](https://img.shields.io/github/contributors-anon/tldr-pages/tldr?label=%F0%9F%91%A5&labelColor=white)                | ![](https://img.shields.io/github/stars/tldr-pages/tldr?label=%E2%AD%90&labelColor=white)                | Dec 8, 2013   |\n| UNIX/Linux commands     | [cheat/cheat](https://github.com/cheat/cheat)                                       | ![](https://img.shields.io/github/contributors-anon/cheat/cheat?label=%F0%9F%91%A5&labelColor=white)                    | ![](https://img.shields.io/github/stars/cheat/cheat?label=%E2%AD%90&labelColor=white)                    | Jul 28, 2013  |\n| Programming languages   | [adambard/learnxinyminutes-docs](https://github.com/adambard/learnxinyminutes-docs) | ![](https://img.shields.io/github/contributors-anon/adambard/learnxinyminutes-docs?label=%F0%9F%91%A5&labelColor=white) | ![](https://img.shields.io/github/stars/adambard/learnxinyminutes-docs?label=%E2%AD%90&labelColor=white) | Jun 23, 2013  |\n| Go                      | [a8m/go-lang-cheat-sheet](https://github.com/a8m/go-lang-cheat-sheet)               | ![](https://img.shields.io/github/contributors-anon/a8m/go-lang-cheat-sheet?label=%F0%9F%91%A5&labelColor=white)        | ![](https://img.shields.io/github/stars/a8m/go-lang-cheat-sheet?label=%E2%AD%90&labelColor=white)        | Feb 9, 2014   |\n| Perl                    | [pkrumnis/perl1line.txt](https://github.com/pkrumins/perl1line.txt)                 | ![](https://img.shields.io/github/contributors-anon/pkrumins/perl1line.txt?label=%F0%9F%91%A5&labelColor=white)         | ![](https://img.shields.io/github/stars/pkrumins/perl1line.txt?label=%E2%AD%90&labelColor=white)         | Nov 4, 2011   |\n| Programming languages   | [StackOverflow](https://stackoverflow.com)                                          | [14M](https://stackexchange.com/leagues/1/alltime/stackoverflow)                                                        | N/A                                                                                                      | Sep 15, 2008  |\n\n<sup>(*) C/U — contributors for GitHub repositories, Users for Stackoverflow</sup>\n\nPie diagram reflecting cheat sheets sources distribution (by number of cheat sheets on cheat.sh originating from a repository):\n\n![cheat.sh cheat sheets repositories](http://cheat.sh/files/stat-2017-06-05.png)\n\n## How to contribute\n\n### How to edit a cheat sheet\n\nIf you want to edit a cheat.sh cheat sheet, you should edit it in the upstream repository.\nYou will find the name of the source repository in a browser when you open a cheat sheet.\nThere are two github buttons at the bottom of the page: the second one is the button\nof the repository, which belongs the current cheat sheet.\n\nYou can edit the cheat sheet directly in your browser (you need a github account for it).\nThere is an edit button in the top right corner. If you click on it, an editor will be open.\nThere you will change the cheat sheet (under the hood: the upstream repository is forked, your changes are\ncommitted in the forked repository, a pull request to the upstream repository owner is sent).\n\n![cheat.sh cheat sheets repositories](http://cheat.sh/files/edit-cheat-sheet.png)\n\n### How to add a cheat sheet\n\nIf you want to add a cheat sheet, you have one of the following\nways:\n\n* Add it to one of the external cheat sheets repositories; you should decide on your own what is the best repository for your cheat sheet;\n* Add it to the local cheat.sh repository ([cheat.sheets](https://github.com/chubin/cheat.sheets)) on github (fork, commit, pull request);\n* Post it on cheat.sh using curl or a web browser ([cheat.sh/:post](http://cheat.sh/:post)).\n\nIf you want to change an existing cheat sheet,\nyou have to find the original repository (when you open a cheat sheet in a browser,\nyou see the repository's github button in the bottom of the cheat sheet),\nthe cheat sheet is coming from, and change it there.\nAfter some time the changes will be synchronized on cheat.sh.\n\n### How to add a cheat sheet repository\n\nIf you want to add a cheat sheet repository to cheat.sh, please open an issue:\n\n* [Add a new repository](https://github.com/chubin/cheat.sh/issues/new)\n\nPlease specify the name of the repository, and give its short description.\n\n\n## Installation and standalone usage\n\nYou don't need to install anything, to start using *cheat.sh*.\n\nThere are two cases, when you want to install *cheat.sh* locally:\n\n1. You plan to use it off-line, without Internet access;\n2. You want to use your own cheat sheets (additionally, or as a replacement).\n\nInstallation process in described in details here: [cheat.sh standalone installation](doc/standalone.md)\n"
  },
  {
    "path": "bin/app.py",
    "content": "#!/usr/bin/env python\n# vim: set encoding=utf-8\n# pylint: disable=wrong-import-position,wrong-import-order\n\n\"\"\"\nMain server program.\n\nConfiguration parameters:\n\n    path.internal.malformed\n    path.internal.static\n    path.internal.templates\n    path.log.main\n    path.log.queries\n\"\"\"\n\nfrom __future__ import print_function\n\nimport sys\n\nif sys.version_info[0] < 3:\n    reload(sys)\n    sys.setdefaultencoding(\"utf8\")\n\nimport sys\nimport logging\nimport os\nimport requests\nimport jinja2\nfrom flask import Flask, request, send_from_directory, redirect, Response\n\nsys.path.append(os.path.abspath(os.path.join(__file__, \"..\", \"..\", \"lib\")))\nfrom config import CONFIG\nfrom limits import Limits\nfrom cheat_wrapper import cheat_wrapper\nfrom post import process_post_request\nfrom options import parse_args\n\nfrom stateful_queries import save_query, last_query\n\n\nif not os.path.exists(os.path.dirname(CONFIG[\"path.log.main\"])):\n    os.makedirs(os.path.dirname(CONFIG[\"path.log.main\"]))\nlogging.basicConfig(\n    filename=CONFIG[\"path.log.main\"],\n    level=logging.DEBUG,\n    format=\"%(asctime)s %(message)s\",\n)\n# Fix Flask \"exception and request logging\" to `stderr`.\n#\n# When Flask's werkzeug detects that logging is already set, it\n# doesn't add its own logger that prints exceptions.\nstderr_handler = logging.StreamHandler()\nlogging.getLogger().addHandler(stderr_handler)\n#\n# Alter log format to disting log lines from everything else\nstderr_handler.setFormatter(logging.Formatter(\"%(filename)s:%(lineno)s: %(message)s\"))\n\n\n#\n# Sometimes werkzeug starts logging before an app is imported\n# (https://github.com/pallets/werkzeug/issues/1969)\n# resulting in duplicating lines. In that case we need root\n# stderr handler to skip lines from werkzeug.\nclass SkipFlaskLogger(object):\n    def filter(self, record):\n        if record.name != \"werkzeug\":\n            return True\n\n\nif logging.getLogger(\"werkzeug\").handlers:\n    stderr_handler.addFilter(SkipFlaskLogger())\n\n\napp = Flask(__name__)  # pylint: disable=invalid-name\napp.jinja_loader = jinja2.ChoiceLoader(\n    [app.jinja_loader, jinja2.FileSystemLoader(CONFIG[\"path.internal.templates\"])]\n)\n\nLIMITS = Limits()\n\nPLAIN_TEXT_AGENTS = [\n    \"curl\",\n    \"httpie\",\n    \"lwp-request\",\n    \"wget\",\n    \"python-requests\",\n    \"openbsd ftp\",\n    \"powershell\",\n    \"fetch\",\n    \"aiohttp\",\n    \"xh\",\n]\n\n\ndef _is_html_needed(user_agent):\n    \"\"\"\n    Basing on `user_agent`, return whether it needs HTML or ANSI\n    \"\"\"\n    return all([x not in user_agent for x in PLAIN_TEXT_AGENTS])\n\n\ndef is_result_a_script(query):\n    return query in [\":cht.sh\"]\n\n\n@app.route(\"/files/<path:path>\")\ndef send_static(path):\n    \"\"\"\n    Return static file `path`.\n    Can be served by the HTTP frontend.\n    \"\"\"\n    return send_from_directory(CONFIG[\"path.internal.static\"], path)\n\n\n@app.route(\"/favicon.ico\")\ndef send_favicon():\n    \"\"\"\n    Return static file `favicon.ico`.\n    Can be served by the HTTP frontend.\n    \"\"\"\n    return send_from_directory(CONFIG[\"path.internal.static\"], \"favicon.ico\")\n\n\n@app.route(\"/malformed-response.html\")\ndef send_malformed():\n    \"\"\"\n    Return static file `malformed-response.html`.\n    Can be served by the HTTP frontend.\n    \"\"\"\n    dirname, filename = os.path.split(CONFIG[\"path.internal.malformed\"])\n    return send_from_directory(dirname, filename)\n\n\ndef log_query(ip_addr, found, topic, user_agent):\n    \"\"\"\n    Log processed query and some internal data\n    \"\"\"\n    log_entry = \"%s %s %s %s\\n\" % (ip_addr, found, topic, user_agent)\n    with open(CONFIG[\"path.log.queries\"], \"ab\") as my_file:\n        my_file.write(log_entry.encode(\"utf-8\"))\n\n\ndef get_request_ip(req):\n    \"\"\"\n    Extract IP address from `request`\n    \"\"\"\n\n    if req.headers.getlist(\"X-Forwarded-For\"):\n        ip_addr = req.headers.getlist(\"X-Forwarded-For\")[0]\n        if ip_addr.startswith(\"::ffff:\"):\n            ip_addr = ip_addr[7:]\n    else:\n        ip_addr = req.remote_addr\n    if req.headers.getlist(\"X-Forwarded-For\"):\n        ip_addr = req.headers.getlist(\"X-Forwarded-For\")[0]\n        if ip_addr.startswith(\"::ffff:\"):\n            ip_addr = ip_addr[7:]\n    else:\n        ip_addr = req.remote_addr\n\n    return ip_addr\n\n\ndef get_answer_language(request):\n    \"\"\"\n    Return preferred answer language based on\n    domain name, query arguments and headers\n    \"\"\"\n\n    def _parse_accept_language(accept_language):\n        languages = accept_language.split(\",\")\n        locale_q_pairs = []\n\n        for language in languages:\n            try:\n                if language.split(\";\")[0] == language:\n                    # no q => q = 1\n                    locale_q_pairs.append((language.strip(), \"1\"))\n                else:\n                    locale = language.split(\";\")[0].strip()\n                    weight = language.split(\";\")[1].split(\"=\")[1]\n                    locale_q_pairs.append((locale, weight))\n            except IndexError:\n                pass\n\n        return locale_q_pairs\n\n    def _find_supported_language(accepted_languages):\n        for lang_tuple in accepted_languages:\n            lang = lang_tuple[0]\n            if \"-\" in lang:\n                lang = lang.split(\"-\", 1)[0]\n            return lang\n        return None\n\n    lang = None\n    hostname = request.headers[\"Host\"]\n    if hostname.endswith(\".cheat.sh\"):\n        lang = hostname[:-9]\n\n    if \"lang\" in request.args:\n        lang = request.args.get(\"lang\")\n\n    header_accept_language = request.headers.get(\"Accept-Language\", \"\")\n    if lang is None and header_accept_language:\n        lang = _find_supported_language(_parse_accept_language(header_accept_language))\n\n    return lang\n\n\ndef _proxy(*args, **kwargs):\n    # print \"method=\", request.method,\n    # print \"url=\", request.url.replace('/:shell-x/', ':3000/')\n    # print \"headers=\", {key: value for (key, value) in request.headers if key != 'Host'}\n    # print \"data=\", request.get_data()\n    # print \"cookies=\", request.cookies\n    # print \"allow_redirects=\", False\n\n    url_before, url_after = request.url.split(\"/:shell-x/\", 1)\n    url = url_before + \":3000/\"\n\n    if \"q\" in request.args:\n        url_after = \"?\" + \"&\".join(\"arg=%s\" % x for x in request.args[\"q\"].split())\n\n    url += url_after\n    print(url)\n    print(request.get_data())\n    resp = requests.request(\n        method=request.method,\n        url=url,\n        headers={key: value for (key, value) in request.headers if key != \"Host\"},\n        data=request.get_data(),\n        cookies=request.cookies,\n        allow_redirects=False,\n    )\n\n    excluded_headers = [\n        \"content-encoding\",\n        \"content-length\",\n        \"transfer-encoding\",\n        \"connection\",\n    ]\n    headers = [\n        (name, value)\n        for (name, value) in resp.raw.headers.items()\n        if name.lower() not in excluded_headers\n    ]\n\n    response = Response(resp.content, resp.status_code, headers)\n    return response\n\n\n@app.route(\"/\", methods=[\"GET\", \"POST\"])\n@app.route(\"/<path:topic>\", methods=[\"GET\", \"POST\"])\ndef answer(topic=None):\n    \"\"\"\n    Main rendering function, it processes incoming weather queries.\n    Depending on user agent it returns output in HTML or ANSI format.\n\n    Incoming data:\n        request.args\n        request.headers\n        request.remote_addr\n        request.referrer\n        request.query_string\n    \"\"\"\n\n    user_agent = request.headers.get(\"User-Agent\", \"\").lower()\n    html_needed = _is_html_needed(user_agent)\n    options = parse_args(request.args)\n\n    if topic in [\n        \"apple-touch-icon-precomposed.png\",\n        \"apple-touch-icon.png\",\n        \"apple-touch-icon-120x120-precomposed.png\",\n    ] or (topic is not None and any(topic.endswith(\"/\" + x) for x in [\"favicon.ico\"])):\n        return \"\"\n\n    request_id = request.cookies.get(\"id\")\n    if topic is not None and topic.lstrip(\"/\") == \":last\":\n        if request_id:\n            topic = last_query(request_id)\n        else:\n            return \"ERROR: you have to set id for your requests to use /:last\\n\"\n    else:\n        if request_id:\n            save_query(request_id, topic)\n\n    if request.method == \"POST\":\n        process_post_request(request, html_needed)\n        if html_needed:\n            return redirect(\"/\")\n        return \"OK\\n\"\n\n    if \"topic\" in request.args:\n        return redirect(\"/%s\" % request.args.get(\"topic\"))\n\n    if topic is None:\n        topic = \":firstpage\"\n\n    if topic.startswith(\":shell-x/\"):\n        return _proxy()\n        # return requests.get('http://127.0.0.1:3000'+topic[8:]).text\n\n    lang = get_answer_language(request)\n    if lang:\n        options[\"lang\"] = lang\n\n    ip_address = get_request_ip(request)\n    if \"+\" in topic:\n        not_allowed = LIMITS.check_ip(ip_address)\n        if not_allowed:\n            return \"429 %s\\n\" % not_allowed, 429\n\n    html_is_needed = _is_html_needed(user_agent) and not is_result_a_script(topic)\n    if html_is_needed:\n        output_format = \"html\"\n    else:\n        output_format = \"ansi\"\n    result, found = cheat_wrapper(\n        topic, request_options=options, output_format=output_format\n    )\n    if \"Please come back in several hours\" in result and html_is_needed:\n        malformed_response = open(\n            os.path.join(CONFIG[\"path.internal.malformed\"])\n        ).read()\n        return malformed_response\n\n    log_query(ip_address, found, topic, user_agent)\n    if html_is_needed:\n        return result\n    return Response(result, mimetype=\"text/plain\")\n"
  },
  {
    "path": "bin/clean_cache.py",
    "content": "import sys\nimport redis\n\nREDIS = redis.Redis(host=\"localhost\", port=6379, db=0)\n\nfor key in sys.argv[1:]:\n    REDIS.delete(key)\n"
  },
  {
    "path": "bin/release.py",
    "content": "#!/usr/bin/env python\n\nfrom __future__ import print_function\n\nfrom datetime import datetime\nimport os\nfrom os import path\nimport re\nimport shutil\nimport subprocess\nfrom subprocess import Popen\nimport sys\n\nSHARE_DIR = path.join(path.dirname(__file__), \"../share/\")\n\n\ndef run(args):\n    return Popen(args, stdout=sys.stdout, stderr=sys.stderr).wait()\n\n\nstatus = subprocess.check_output([\"git\", \"status\", \"--porcelain\"])\nif len(status) > 0:\n    print(\"Unclean working tree. Commit or stash changes first.\", file=sys.stderr)\n    sys.exit(1)\n\ntimestamp = datetime.utcnow().strftime(\"%Y-%m-%d %H:%M:%S +0000\")\n\ncht_curr = path.join(SHARE_DIR, \"cht.sh.txt\")\ncht_new = path.join(SHARE_DIR, \"cht.sh.txt.new\")\n\nre_version = re.compile(r\"^__CHTSH_VERSION=(.*)$\")\nre_timestamp = re.compile(r\"^__CHTSH_DATETIME=.*$\")\n\nwith open(cht_curr, \"rt\") as fin:\n    with open(cht_new, \"wt\") as fout:\n        for line in fin:\n            match = re_version.match(line)\n            if match:\n                version = int(match.group(1)) + 1\n                fout.write(\"__CHTSH_VERSION=%s\\n\" % version)\n                continue\n\n            match = re_timestamp.match(line)\n            if match:\n                fout.write('__CHTSH_DATETIME=\"%s\"\\n' % timestamp)\n                continue\n\n            fout.write(line)\n\nshutil.copymode(cht_curr, cht_new)\nos.remove(cht_curr)\nos.rename(cht_new, cht_curr)\n\nmessage = \"cht: v%s\" % version\nrun([\"git\", \"add\", cht_curr])\nrun([\"git\", \"commit\", \"-m\", message])\nrun([\"git\", \"tag\", \"cht@%s\" % version, \"-m\", message])\n"
  },
  {
    "path": "bin/srv.py",
    "content": "#!/usr/bin/env python\n#\n# Serving cheat.sh with `gevent`\n#\n\nfrom gevent.monkey import patch_all\nfrom gevent.pywsgi import WSGIServer\n\npatch_all()\n\nimport os\nimport sys\n\nfrom app import app, CONFIG\n\n\nif \"--debug\" in sys.argv:\n    # Not all debug mode features are available under `gevent`\n    # https://github.com/pallets/flask/issues/3825\n    app.debug = True\n\nif \"CHEATSH_PORT\" in os.environ:\n    port = int(os.environ.get(\"CHEATSH_PORT\"))\nelse:\n    port = CONFIG[\"server.port\"]\n\nsrv = WSGIServer((CONFIG[\"server.bind\"], port), app)\nprint(\"Starting gevent server on {}:{}\".format(srv.address[0], srv.address[1]))\nsrv.serve_forever()\n"
  },
  {
    "path": "doc/README-ja.md",
    "content": " 唯一のチートシート https://cheat.sh/ が必要です\n\n世界の最高のコミュニティ駆動チートシートリポジトリへの統一されたアクセス。\n\n理想的なチートシートのようなものがあるとすぐに想像してみましょう。 どのように見える？ どのような機能が必要ですか？\n\n    簡潔に – 簡潔にする必要があります。 それはあなたが必要とするものだけを含んでいなければなりません。\n    速く – それを即座に使用することが可能でなければなりません。\n    包括的 – あなたが持つ可能性があるすべての質問に対する回答を含める必要があります。\n    普遍的な – 準備ができていなくても、必要に応じてどこでもすぐに利用できるはずです。\n    邪魔になりません – あなたの主な仕事からあなたをそらすことはありません。\n    先入観 – それはあなたがその科目を学ぶのに役立ちます。\n    目立たない – 完全に気付かれないで使用することが可能でなければならない。\n\nそんなことは存在しない。\n特徴\n\nチート.sh\n\n    単純なカール/ブラウザインターフェイスを備えています。\n    55のプログラミング言語、いくつかのDBMS、および1000以上の最も重要なUNIX / Linuxコマンドをカバーしています。\n    世界で最も優れたコミュニティ主導のチートシートリポジトリへのアクセスと、StackOverflowへのアクセスを提供します。\n    あらゆる場所で利用でき、インストールは必要ありません。\n    ultrafastは、原則として100ミリ秒以内に回答を返します。\n    便利で便利なコマンドラインクライアントcht.shがありますが、これは必須ではありません。\n    ブラウザを開いて精神的なコンテキストを切り替えることなく、コードエディタから直接使用することができます。\n    特殊モード（ステルスモード）をサポートしています。このモードでは、鍵に触れたり、音を出させたりすることなく、完全に目に見えない状態で使用できます。\n\n使用法\n\nコマンドラインからUNIX / Linuxコマンドのチートシートを取得するには、 curlまたは他のHTTP / HTTPSクライアントを使用して、クエリのコマンド名を指定してサービスをクエリします。\n\n```\n    curl cheat.sh/tar\n    curl cht.sh/curl\n    curl https://cheat.sh/rsync\n    curl https://cht.sh/tr\n```\n\nご覧のとおり、HTTPSとHTTPの両方を使用してサービスにアクセスし、長い（cheat.sh）サービス名と短い（cht.sh）サービス名の両方にアクセスできます。\n\nここで、 tar 、 curl 、 rsync 、 trはUNIX / Linuxコマンドの名前です。あなたはチートシートを入手したいと思っています。\n\n必要なコマンドの名前がわからない場合は、 ~KEYWORD記法を使用して検索することができます。 たとえば、ファイルシステム/ボリューム/その他のsnapshotsを作成する方法を知るには：\n\n```\n    curl cht.sh/~snapshot\n```\n\nプログラミング言語チートシートは、ルート名前空間には直接配置されず、専用の特別な名前空間に配置されます。\n\n```\n    curl cht.sh/go/Pointers\n    curl cht.sh/scala/Functions\n    curl cht.sh/python/lambda\n```\n\n利用可能なプログラミング言語チートシートのリストを取得するには、特別なクエリを実行します。list：\n\n```\n    curl cht.sh/go/:list\n```\n\n（ほぼ）それぞれのプログラミング言語には、 :learnという名前の特別なページがあります。これは、言語の基礎を説明しています（ 「Learn X in Y」プロジェクトからの直接マッピングです）。 あなたが言語を学び始めたばかりの方は、良い出発点になるかもしれません。\n\nいくつかのプログラミング言語のクエリ用のチートシートがない場合（ほとんどの場合そうです）、利用可能なチートシートとStackOverflowでの回答に基づいてオンザフライで生成されます。 もちろん、返されたチートシートが100％ヒットしたという保証はありませんが、ほとんど常にあなたが探しているものです。\n\nこれらの（そしてあなた自身の）クエリを試して、その印象をどのように見えるかを見てみましょう：\n\n```\n    curl cht.sh/go/reverse+a+list\n    curl cht.sh/python/random+list+elements\n    curl cht.sh/js/parse+json\n    curl cht.sh/lua/merge+tables\n    curl cht.sh/clojure/variadic+function\n```\n\nいくつかのクエリの答えが気に入らない場合は、別のパラメータを選択することができます：追加のパラメータ/1 、 /2などをつけてクエリを繰り返します：\n\n```\n    curl cht.sh/python/random+string\n    curl cht.sh/python/random+string/1\n    curl cht.sh/python/random+string/2\n```\n\nチートシートは照会されたプログラミング言語のコードとしてフォーマットされています（少なくともこれを行うために最善を尽くしています）。この言語のプログラムに直接貼り付けることができます。 テキストコメントがある場合は、言語構文に従って書式設定されます。\n\n```\n    $ curl cht.sh/lua/table+keys\n    -- lua: retrieve list of keys in a table\n\n    local keyset={}\n    local n=0\n\n    for k,v in pairs(tab) do\n      n=n+1\n      keyset[n]=k\n    end\n\n    --[[\n       [ Note that you cannot guarantee any order in keyset. If you want the\n       [ keys in sorted order, then sort keyset with table.sort(keyset).\n       [ \n       [ [lhf] [so/q/12674345] [cc by-sa 3.0]\n       ]]\n```\n\n答えにテキストコメントが必要ない場合は、特別なオプションを使用してコメントを削除できます?Q ：\n\n```\n    $ curl cht.sh/lua/table+keys?Q\n    local keyset={}\n    local n=0\n\n    for k,v in pairs(tab) do\n      n=n+1\n      keyset[n]=k\n    end\n```\n\n構文強調表示が必要ない場合は、 ?Tを使ってスイッチをオフにし?T 。 オプションを一緒に組み合わせることができます：\n\n```\n    curl cht.sh/go/reverse+a+list?Q\n    curl cht.sh/python/random+list+elements?Q\n    curl cht.sh/js/parse+json?Q\n    curl cht.sh/lua/merge+tables?QT\n    curl cht.sh/clojure/variadic+function?QT\n```\n\n下記および/:help記載されているすべてのオプションの完全なリスト\n\nあなた自身の質問をお試しください。 次のルールに従ってください。\n\n    より具体的になるようにしてください（ /python/append+fileは/python/fileや/python/appendよりも優れてい/python/append ）。\n    可能であれば実践的な質問をする（しかし理論的な質問も可能である）。\n    プログラミング言語に関する質問のみを行います。 セクション名としてプログラミング言語の名前を指定します。\n    空白ではなく+区切ります。\n    とにかく無視される特殊文字は使用しないでください。\n\n以下のプログラミング言語のクエリについての詳細を読む。\nコマンドラインクライアント、cht.sh\n\ncheat.shサービスには独自のコマンドラインクライアント（ cht.sh ）があり、 curlを使ってサービスを直接照会するのに比べ、いくつかの便利な機能があります。\n\n    永続的なクエリコンテキストとreadlineサポートを備えた特別なシェルモード。\n    クエリの履歴。\n    クリップボードの統合。\n    シェルのタブ補完のサポート（bash、fish、zsh）;\n    ステルスモード。\n\nクライアントをインストールするには：\n\n```\n    curl https://cht.sh/:cht.sh > ~/bin/cht.sh\n    chmod +x ~/bin/cht.sh\n```\n\nさて、あなたはcurl代わりにcht.shを使い、より自然な方法であなたのクエリを+代わりにスペースで書くことができます：\n\n```\n    $ cht.sh go reverse a list\n    $ cht.sh python random list elements\n    $ cht.sh js parse json\n```\n\n特別なシェルモードでクライアントを起動する方がさらに便利です：\n\n```\n    $ cht.sh --shell\n    cht.sh> go reverse a list\n```\n\nすべてのクエリがほぼ同じ言語であると想定されている場合は、クエリのコンテキストを変更して、プログラミング言語の名前を繰り返すことができます。\n\n```\n    $ cht.sh --shell\n    cht.sh> cd go\n    cht.sh/go> reverse a list\n```\n\nこのコンテキストでクライアントを起動することさえできます：\n\n```\n    $ cht.sh --shell go\n    cht.sh/go> reverse a list\n    ...\n    cht.sh/go> join a list\n    ...\n```\n\nコンテキストを変更したい場合は、 cdコマンドで行うことができます。あるいは、他の言語のクエリを1つだけ実行する場合は、 /ください：\n\n```\n    $ cht.sh --shell go\n    ...\n    cht.sh/go> /python dictionary comprehension\n    ...\n```\n\n最後の回答をクリップボードにcopyする場合は、 c （ copy ）コマンドまたはC （コメントなしのccopy ）コマンドを使用できます。\n\n```\n    cht.sh/python> append file\n    #  python - How do you append to a file?\n\n    with open(\"test.txt\", \"a\") as myfile:\n        myfile.write(\"appended text\")\n    cht.sh/python> C\n    copy: 2 lines copied to the selection\n```\n\n他の内部cht.shコマンドのhelpを入力してください。\n\n```\n\tcht.sh> help\n\thelp    - show this help\n\thush    - do not show the 'help' string at start anymore\n\tcd LANG - change the language context\n\tcopy    - copy the last answer in the clipboard (aliases: yank, y, c)\n\tccopy   - copy the last answer w/o comments (cut comments; aliases: cc, Y, C)\n\texit    - exit the cheat shell (aliases: quit, ^D)\n\tid [ID] - set/show an unique session id (\"reset\" to reset, \"remove\" to remove)\n\tstealth - stealth mode (automatic queries for selected text)\n\tupdate  - self update (only if the scriptfile is writeable)\n\tversion - show current cht.sh version\n\t/:help  - service help\n\tQUERY   - space separated query staring (examples are below)\n\t\t\t\t  cht.sh> python zip list\n\t\t\t\t  cht.sh/python> zip list\n\t\t\t\t  cht.sh/go> /python zip list\n```\n\ncht.shクライアントの設定ファイルは~/.cht.sh/cht.sh.confます。 これを使用して、各クエリで使用するクエリオプションを指定します。 たとえば、構文の強調表示をオフに切り替えるには、次の内容のファイルを作成します。\n\n```\nQUERY_OPTIONS=\"T\"\n```\n\nまたは、特殊な構文強調表示テーマを使用する場合は、次のようにします。\n\n```\nQUERY_OPTIONS=\"style=native\"\n```\n\n（ curl cht.sh/:styles-demoサポートされているすべてのスタイルが表示されます）。\nタブ補完\n\ncht.shタブ補完のサポートをcht.shにするには、 ~/.bashrc ： :bash_completionスクリプトを追加してください：\n\n    $ curl https://cheat.sh/:bash_completion > ~/.bash.d/cht.sh\n    $ . ~/.bash.d/cht.sh\n    $ # and add . ~/.bash.d/cht.sh to ~/.bashrc\n\nステルスモード\n\n実際のチートシートの重要な特性の1つは、それが完全に気付かれずに使用できるということです。\n\ncheat.shはまったく気付かれずに使えます。 cheat.shクライアント、 cht.shには、 ステルスモードと呼ばれる特別なモードがあります。これは、キーボードに触れてチートシートを開く必要がないことを利用しています。\n\nこのモードでは、マウスでテキストを選択すると（そしてX Window Systemの選択バッファやクリップボードに追加されるとすぐに）、それはcheat.shのクエリ文字列として使用され、特派員のチートシートは自動的に表示されます。\n\nインタビュー担当者が共有文書（Google Docsなど）を使っていくつかの質問をし、そこにコーディング回答を書くことになっているオンラインインタビューをしていることを想像してみましょう。面接官にあなたがそれを正しく聞いたことを示すために）\n\nステルスモードのcht.shを使用しているときは、何らかの質問のためにチートシートを見るために必要なのは、マウスを使って質問を選択することだけです。 答えにテキストを入れたくない場合は、コードだけが必要です。ステルスモードを開始するときには、 Qオプションを使用してください。\n\n```\nYou: Hi!                                            | $ cht.sh --shell python\nShe: Hi!                                            | cht.sh/python> stealth Q\nShe: Are you ready for a small interview?           | stealth: you are in the stealth mode; select any text\nShe: Just a couple of questions                     | stealth: selections longer than 5 words are ignored\nShe: We will talk about python                      | stealth: query arguments: ?Q\nShe: Let's start from something simple.             | stealth: use ^C to leave this mode\nShe: Do you know how to reverse a list in python?   |\nYou: Sure                                           |\nYou: (selecting \"reverse a list\")                   | stealth: reverse a list\n                                                    | reverse_lst = lst[::-1]\nYou: lst[::-1]?                                     |\nShe: Good.                                          |\nShe: Do you know how to chain a list of lists?      |\nYou: (selecting \"chain a list of lists\")            | stealth: chain a list of lists\n                                                    | import itertools\n                                                    | a = [[\"a\",\"b\"], [\"c\"]]\n                                                    | print list(itertools.chain.from_iterable(a))\nYou: May I use external modules?                    |\nShe: What module do you want to use?                |\nYou: itertools                                      |\nShe: Yes, you may use it                            |\nYou: Ok, then:                                      |\nYou: itertools.chain.from_iterable(a)               |\nShe: Good. Let's try something harder.              |\nShe: What about quicksort implementation?           |\nYou: (selecting \"quicksort implementation\")         | stealth: quicksort implementation\nYou: Let me think about it.                         | (some big and clumsy lowlevel implementation shown)\nYou: Well...(starting typing it in)                 | def sort(array=[12,4,5,6,7,3,1,15]):\n                                                    |     less = []\nShe: (seeing your ugly pascal style)                |     equal = []\nShe: Could you write it more concise?               |     greater = []\n                                                    |     if len(array) > 1:\nYou: What do you mean?                              |         pivot = array[0]\n                                                    |         for x in array:\nShe: I mean,                                        |             if x < pivot: less.append(x)\nShe: do you really need all these ifs and fors?     |             if x == pivot: equal.append(x)\nShe: Could you may be just use filter instead?      |             if x > pivot: greater.append(x)\n                                                    |         return sort(less)+equal+sort(greater)\nYou: quicksort with filter?                         |     else:\n                                                    |         return array\nShe: Yes                                            |\nYou: (selecting \"quicksort with filter\")            | stealth: quicksort with filter\nYou: Ok, I will try.                                | return qsort(filter(lt, L[1:]))+[pivot] \\\nYou: Something like this?                           |     +qsort(filter(ge, L[1:]))\nYou: qsort(filter(lt, L[1:]))+[pivot] \\             |\n       + qsort(filter(ge, L[1:]))                   |\n                                                    |\nShe: Yes! Perfect! Exactly what I wanted to see!    |\n                                                    |\n```\n\nもちろん、それはちょうど楽しいことです。あなたが行ったときに何が起こるかを知っているので、コーディングのインタビューで決して欺くべきではありません。\n\nエディターの統合\n\nエディタから直接cheat.shを使うことができます（ VimとEmacsは現在サポートされています）。 あなたのブラウザを開き、グーグルで、スタックオーバーフローをブラウズし、最終的に必要なコードスニペットをクリップボードにコピーして後でエディタに貼り付けるのではなく、エディタを離れずに同じことを達成することができます。\n\nこれはVimのように見えます：\n\n    プログラムの編集中に質問がある場合は、バッファに直接質問を入力して<leader>KKを押してください。 ポケットベルであなたの質問に対する答えが得られます。 （ <leader>KBすると、別のバッファで回答が得られます）。\n\n    答えが気に入ったらバッファやページャから手作業で貼り付けてください。怠け者の場合は<leader>KPを使って質問の下/下に貼り付けることができます。 コメントなしで回答が必要な場合は、 <leader>KCが最後のクエリを再生してそれらを切り替えます。\n\nシンセシス （Vim用）などの静的解析プラグインを使用している場合は、警告とエラーメッセージをcheat.shクエリとして使用できます：カーソルを問題の行に置き、 <leader>KE ：警告の説明を開きます新しいバッファに入れます。\nヴィム\n\n    cheat.sh-vim – Vimのサポート\n\nここにVimの設定例を示します：\n\n```\n\" some configuration above ...\n\nlet mapleader=\" \"\n\ncall vundle#begin()\nBundle 'gmarik/vundle'\nBundle 'scrooloose/syntastic'\nBundle 'dbeniamine/cheat.sh-vim'\ncall vundle#end()\n\nlet g:syntastic_javascript_checkers = [ 'jshint' ]\nlet g:syntastic_ocaml_checkers = ['merlin']\nlet g:syntastic_python_checkers = ['pylint']\nlet g:syntastic_shell_checkers = ['shellcheck']\n\n\" some configuration below ...\n```\n\nこの例では、いくつかのVimプラグインが使用されています：\n\n    gmarik / vundle – Vimプラグインマネージャ\n    scrooloose / syntastic – 構文チェックプラグイン\n    cheat.sh-vim – Vimのサポート\n\nSyntasticは警告とエラー（code analysisツールで見つかった： jshint 、 jshint 、 pylint 、 shellcheckt etc.), and cheat.sh-vim`を表示すると、エディタに書き込まれたプログラミング言語のクエリに関するエラーと警告と回答の説明が表示されます。\n\ncheat.sh Vimプラグインの最も重要な機能が表示されているデモをご覧ください（5分）：\n\nまたは、スクロールしたり一時停止したりする場合は、YouTubeでも同じです：\n\nEmacs\n\n    cheat-sh.el – Emacsのサポート（cheat.sh/：emacsでも利用可能）\n    cheat.sh/：emacs-ivy – ivyユーザーのEmacsサポート\n\n特別ページ\n\nいくつかの特別なページがあり（その名前は常にコロンで始まります）、チートシートではなく特別な意味を持っています。\n\n入門：\n\n```\n    :help               description of all special pages and options\n    :intro              cheat.sh introduction, covering the most important usage questions\n    :list               list all cheat sheets (can be used in a subsection too: /go/:list)\n```\n\nコマンドライン・クライアントcht.shとシェルは次のものをサポートしています。\n\n```\n    :cht.sh             code of the cht.sh client\n    :bash_completion    bash function for tab completion\n    :bash               bash function and tab completion setup\n    :fish               fish function and tab completion setup\n    :zsh                zsh function and tab completion setup\n```\n\nエディターのサポート：\n\n    :vim                cheat.sh support for Vim\n    :emacs              cheat.sh function for Emacs\n    :emacs-ivy          cheat.sh function for Emacs (uses ivy)\n\nその他のページ：\n\n```\n    :post               how to post new cheat sheet\n    :styles             list of color styles\n    :styles-demo        show color styles usage examples\n```\n\nサーチ\n\nキーワードを検索するには、次のクエリを使用します。\n\n```\n    /~keyword\n```\n\nこの場合、検索は再帰的ではなく、指定されたレベルのページでのみ実行されます。 例えば：\n\n```\n    /~snapshot          look for snapshot in the first level cheat sheets\n    /scala/~currying     look for currying in scala cheat sheets\n```\n\nすべてのチートシートで再帰的検索を行うには、二重スラッシュを使用します。\n\n    /~snapshot/r         look for snapshot in all cheat sheets\n\nスラッシュの後に特殊な検索オプションを使用することができます。\n\n    /~shot/bi           case insensitive (i), word boundaries (b)\n\n検索オプションのリスト：\n\n```\n    i   case insensitive search\n    b   word boundaries\n    r   recursive search\n```\n\nプログラミング言語チートシート\n\nプログラミング言語に関連するチートシートは、プログラミング言語に従って名前が付けられた名前空間（サブディレクトリ）に編成されています。\n\nサポートされているプログラミング言語ごとに、独自のsheet、 hello 、 :list 、 :learnいくつかの特別なチートシートがあり:learn 。 それはルアのように見えます：\n\n```\n    lua\n    lua/hello\n    lua/:list\n    lua/:learn\n```\n\nいくつかの言語には、1行のチートシート、1 1line ：\n\n    perl/1line\n\n    helloは、あなたがどのように言語を使い始めることができるかを記述します – 必要に応じてインストールし、プログラムをビルドして実行し、言語で書かれた “Hello world”プログラムを表示します。\n    :listには言語に関連するすべてのトピックが表示されます\n    :learnは、言語を使い始めるのに最適なx-in-minutes言語のチートシートを表示します。\n    1lineはこの言語の1ライナーの集合です\n    weirdnessなことはこの言語の奇妙なものの例の集まりです\n\n現時点では、cheat.shは以下の55のプログラミング言語（アルファベット順にソートされています）をカバーしています：\n接頭辞 \t言語 \t基本 \tワンライナー \t奇妙さ \tスタックオーバーフロー\narduino/ \tArduino \t\t\t\t✓\nassembly/ \tアセンブリ \t\t\t\t✓\nawk/ \tAWK \t✓ \t\t\t✓\nbash/ \tバッシュ \t✓ \t\t\t✓\nbasic/ \tベーシック \t\t\t\t✓\nbf/ \t頭痛 \t✓ \t\t\t✓\nc/ \tC \t✓ \t\t\t✓\nchapel/ \tチャペル \t✓ \t\t\t✓\nclean/ \tクリーン \t\t\t\t✓\nclojure/ \tClojure \t✓ \t\t\t✓\ncoffee/ \tCoffeeScript \t✓ \t\t\t✓\ncpp/ \tC ++ \t✓ \t\t\t✓\ncsharp/ \tC＃ \t✓ \t\t\t✓\nd/ \tD \t✓ \t\t\t✓\ndart/ \tダーツ \t✓ \t\t\t✓\ndelphi/ \tデフ \t\t\t\t✓\ndylan/ \tディラン \t✓ \t\t\t✓\neiffel/ \tエッフェル \t\t\t\t✓\nelixir/ \tエリクシール \t✓ \t\t\t✓\nelisp/ \tELisp \t✓ \t\t\t✓\nelm/ \tエルム \t✓ \t\t\t✓\nerlang/ \tアーラン \t✓ \t\t\t✓\nfactor/ \t因子 \t✓ \t\t\t✓\nfortran/ \tFortran \t✓ \t\t\t✓\nforth/ \t四方 \t✓ \t\t\t✓\nfsharp/ \tF＃ \t✓ \t\t\t✓\ngo/ \t行こう \t✓ \t\t\t✓\ngroovy/ \tGroovy \t✓ \t\t\t✓\nhaskell/ \tハスケル \t✓ \t\t\t✓\njava/ \tJava \t✓ \t\t\t✓\njs/ \tJavaScript \t✓ \t✓ \t✓ \t✓\njulia/ \tジュリア \t✓ \t\t\t✓\nkotlin/ \tコトリン \t✓ \t\t\t✓\nlisp/ \tLisp \t✓ \t\t\t✓\nlua/ \tルア \t✓ \t\t\t✓\nmatlab/ \tMATLAB \t✓ \t\t\t✓\nocaml/ \tOCaml \t✓ \t\t\t✓\nperl/ \tPerl \t✓ \t✓ \t\t✓\nperl6/ \tPerl 6 \t✓ \t✓ \t\t✓\nphp/ \tPHP \t✓ \t\t\t✓\npike/ \tパイク \t\t\t\t✓\npython/ \tPython \t✓ \t\t\t✓\npython3/ \tPython 3 \t✓ \t\t\t✓\nr/ \tR \t✓ \t\t\t✓\nracket/ \tラケット \t✓ \t\t\t✓\nruby/ \tルビー \t✓ \t\t\t✓\nrust/ \t錆 \t✓ \t\t\t✓\nscala/ \tスカラ \t✓ \t\t\t✓\nscheme/ \tスキーム \t✓ \t\t\t✓\nswift/ \t迅速 \t✓ \t\t\t✓\ntcsh/ \tTcsh \t✓ \t\t\t✓\ntcl/ \tTcl \t✓ \t\t\t✓\nobjective-c/ \t目標-C \t✓ \t\t\t✓\nvb/ \tVisualBasic \t✓ \t\t\t✓\nvbnet/ \tVB.Net \t✓ \t\t\t✓\nチートシートのソース\n\nさらに別の平凡なチートシートリポジトリを作成するのではなく、既存のよく開発されたよく管理されたチートシートリポジトリにアクセスする統一メカニズムの作成に力を注いでいます。\n\ncheat.shは世界中の何千ものユーザー、開発者、作者によって管理されている選択されたコミュニティ駆動のチートシートリポジトリと情報ソースを使用します（貢献者のユーザー列数/星数が表示されます）。\nカンニングペーパー \tリポジトリ \tユーザー \t作成日\nUNIX / Linux、プログラミング \tカンニングペーパー \t6/54 \t2017年5月1日\nUNIX / Linuxコマンド \ttldr-pages / tldr \t541/17360 \t2013年12月8日\nUNIX / Linuxコマンド \tクリサンレン/チート \t105/4193 \t2013年7月28日\nプログラミング言語 \tadambard / learnxinyminutes-docs \t1096/5285 \t2013年6月23日\n行こう \ta8m / go-lang-cheat-sheet \t29/3034 \t2014年2月9日\nPerl \tpkrumnis / perl1line.txt \t4/165 \t2011年11月4日\nプログラミング言語 \tスタックオーバーフロー \t9M \t2008年9月15日\n\nチートシートソースの分布を反映するパイダイアグラム（リポジトリから生成されたチート.shのチートシートの数による）：\n\n貢献する方法\nチートシートの編集方法\n\ncheat.shチートシートを編集する場合は、アップストリームレポジトリで編集する必要があります。 チートシートを開くと、ブラウザにソースリポジトリの名前が表示されます。 ページ下部に2つのgithubボタンがあります：2番目のボタンは、現在のチートシートに属するリポジトリのボタンです。\n\nチートシートをブラウザで直接編集できます（githubアカウントが必要です）。 右上に編集ボタンがあります。 それをクリックすると、エディタが開きます。 そこではチートシートを変更します（ボンネットの下：アップストレームリポジトリはフォークされ、変更はフォークされたリポジトリでコミットされ、上流のリポジトリ所有者へのプルリクエストが送信されます）。\n\nチートシートを追加する方法\n\nチートシートを追加する場合は、次のいずれかの方法があります。\n\n    それを外部のチートシートレポジトリの1つに追加します。 自分のチートシートに最適なリポジトリが何であるかを決める必要があります。\n    github（fork、commit、pull request）のローカルcheat.shリポジトリ（ cheat.sheets ）に追加します。\n    curlやウェブブラウザ（ cheat.sh/：post ）を使ってcheat.shに投稿してください。\n\n既存のチートシートを変更したい場合は、元のリポジトリを見つける必要があります（ブラウザでチートシートを開くと、チートシートの下部にリポジトリのgithubボタンが表示されます）、チートシートは、それを変更してください。 しばらくすると、変更はcheat.shで同期されます。\nチートシートリポジトリを追加する方法\n\ncheat.shにチートシートリポジトリを追加する場合は、問題を開いてください：\n\n    新しいリポジトリを追加する\n\nリポジトリの名前を指定し、簡単な説明をしてください。\n\n"
  },
  {
    "path": "doc/standalone.md",
    "content": "\nYou don't need to install anything, to start using *cheat.sh*.\nThe only tool that you need is *curl*, which is typically installed\nin every system. In the rare cases when *curl* is not installed,\nthere should be one of its alternatives in the system: *wget*, *wget2*,\n*httpie*, *ftp* (with HTTP support), *fetch*, etc.\n\nThere are two cases, when you want to install *cheat.sh* locally:\n\n1. You plan to use it off-line, without Internet access;\n2. You want to use your own cheat sheets (additionally, or as a replacement).\n\nIn this case you need to install cheat.sh locally.\n\n## How to install cheat.sh locally\n\nTo use cheat.sh offline, you need to:\n\n1. Install it,\n2. Fetch its data sources.\n\nIf you already have the cht.sh cli client locally,\nyou can use it for the standalone installation.\nOtherwise it must be installed first.\n\n```\n    curl https://cht.sh/:cht.sh > ~/bin/cht.sh\n    chmod +x ~/bin/cht.sh\n```\n\nNow you can install cheat.sh locally:\n\n```\n    cht.sh --standalone-install\n```\n\nDuring the installation process, cheat.sh and its\ndata sources will be installed locally.\n\nBy default `~/.cheat.sh` is used as the installation\ndirectory.\n\n![cheat.sh standalone installation](https://user-images.githubusercontent.com/3875145/57986904-ef3f1b80-7a7a-11e9-9531-ef37ec74b03a.png)\n\nIf you don't plan to use Redis for caching,\nswitch the caching off in the config file:\n\n```\n    $ vim ~/.cheat.sh/etc/config.yaml\n    cache:\n      type:   none\n```\n\nor with the environment variable `CHEATSH_CACHE_TYPE=none`.\n\n## Update cheat sheets\n\nCheat sheets are fetched and installed to `~/.cheat.sh/upstream`.\nTo keep the cheat sheets up to date,\nrun the `cheat.sh` `update-all` command on regular basis.\nIdeally, add it to *cron*:\n\n```\n0 5 0 0 0 $HOME/.cheat.sh/ve/bin/python $HOME/.cheat.sh/lib/fetch.py update-all\n```\n\nIn this example, all information sources will be updated\neach day at 5:00 local time, on regular basis.\n\n## cheat.sh server mode\n\nYour local cheat.sh installation is full-fledged, and it can\nhandle incoming HTTP/HTTPS queries.\n\nTo start cheat.sh in the server mode, run:\n\n```\n$HOME/.cheat.sh/ve/bin/python $HOME/.cheat.sh/bin/srv.py\n```\n\nYou can also use `gunicorn` to start the cheat.sh server.\n\n\n## Docker\n\nYou can deploy cheat.sh as a docker container.\nUse `Dockerfile` in the source root directory, to build the Docker image:\n\n```\ndocker build .\n```\n\n## Limitations\n\nSome cheat sheets not available in the offline mode\nfor the moment. The reason for that is that to process some queries,\ncheat.sh needs to access the Internet itself, because it does not have\nthe necessary data locally. We are working on that how to overcome\nthis limitation, but for the moment it still exists.\n\n## Mac OS X Notes\n\n### Installing Redis\n\nTo install Redis on Mac OS X (using `brew`):\n\n```\n$ brew install redis\n$ ln -sfv /usr/local/opt/redis/*.plist ~/Library/LaunchAgents\n$ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.redis.plist\n$ redis-cli ping\nPONG\n```\n"
  },
  {
    "path": "docker-compose.debug.yml",
    "content": "# Compose override, see https://docs.docker.com/compose/extends/\n#\n# - Run `flask` standalone server with more debug aids instead of `gevent`\n# - Turn on Flask debug mode to print tracebacks and autoreload code\n# - Mounts fresh sources from current dir as volume\n#\n# Usage:\n#   docker-compose -f docker-compose.yml -f docker-compose.debug.yml up\n#\nversion: '2'\nservices:\n  app:\n    environment:\n      FLASK_ENV: development\n      #FLASK_RUN_RELOAD: False\n      FLASK_APP: \"bin/app.py\"\n      FLASK_RUN_HOST: 0.0.0.0\n      FLASK_RUN_PORT: 8002\n    entrypoint: [\"/usr/bin/flask\", \"run\"]\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: '2'\nservices:\n  app:\n    build: .\n    image: cheat.sh\n    container_name: chtsh\n    depends_on:\n      - redis\n    environment:\n      - CHEATSH_CACHE_REDIS_HOST=redis\n    ports:\n      - \"8002:8002\"\n    volumes:\n      - .:/app:Z\n  redis:\n    image: redis:4-alpine\n    volumes:\n      - redis_data:/data\nvolumes:\n  redis_data:\n"
  },
  {
    "path": "etc/config.yaml",
    "content": "server:\n    address: \"0.0.0.0\"\ncache:\n    type:   redis\n"
  },
  {
    "path": "lib/adapter/__init__.py",
    "content": "\"\"\"\nImport all adapters from the current directory\nand make them available for import as\n    adapter_module.AdapterName\n\"\"\"\n\n# pylint: disable=wildcard-import,relative-import\n\nfrom os.path import dirname, basename, isfile, join\nimport glob\n\n__all__ = [\n    basename(f)[:-3]\n    for f in glob.glob(join(dirname(__file__), \"*.py\"))\n    if isfile(f) and not f.endswith(\"__init__.py\")\n]\n\nfrom .adapter import all_adapters\nfrom . import *\n"
  },
  {
    "path": "lib/adapter/adapter.py",
    "content": "\"\"\"\n`Adapter`, base class of the adapters.\n\nConfiguration parameters:\n\n    path.repositories\n\"\"\"\n\nimport abc\nimport os\nfrom six import with_metaclass\nfrom config import CONFIG\n\n\nclass AdapterMC(type):\n    \"\"\"\n    Adapter Metaclass.\n    Defines string representation of adapters\n    \"\"\"\n\n    def __repr__(cls):\n        if hasattr(cls, \"_class_repr\"):\n            return getattr(cls, \"_class_repr\")()\n        return super(AdapterMC, cls).__repr__()\n\n\nclass Adapter(with_metaclass(AdapterMC, object)):\n    \"\"\"\n    An abstract class, defines methods:\n\n    (cheat sheets retrieval)\n    * get_list\n    * is_found\n    * is_cache_needed\n\n    (repositories management)\n    \" fetch\n    * update\n\n    and several properties that have to be set in each adapter subclass.\n\n    \"\"\"\n\n    _adapter_name = None\n    _output_format = \"code\"\n    _cache_needed = False\n    _repository_url = None\n    _local_repository_location = None\n    _cheatsheet_files_prefix = \"\"\n    _cheatsheet_files_extension = \"\"\n    _pages_list = []\n\n    @classmethod\n    def _class_repr(cls):\n        return \"[Adapter: %s (%s)]\" % (cls._adapter_name, cls.__name__)\n\n    def __init__(self):\n        self._list = {None: self._get_list()}\n\n    @classmethod\n    def name(cls):\n        \"\"\"\n        Return name of the adapter\n        \"\"\"\n        return cls._adapter_name\n\n    @abc.abstractmethod\n    def _get_list(self, prefix=None):\n        return self._pages_list\n\n    def get_list(self, prefix=None):\n        \"\"\"\n        Return available pages for `prefix`\n        \"\"\"\n\n        if prefix in self._list:\n            return self._list[prefix]\n\n        self._list[prefix] = set(self._get_list(prefix=prefix))\n        return self._list[prefix]\n\n    def is_found(self, topic):\n        \"\"\"\n        check if `topic` is available\n        CAUTION: only root is checked\n        \"\"\"\n        return topic in self._list[None]\n\n    def is_cache_needed(self):\n        \"\"\"\n        Return True if answers should be cached.\n        Return False if answers should not be cached.\n        \"\"\"\n        return self._cache_needed\n\n    @staticmethod\n    def _format_page(text):\n        \"\"\"\n        Preformatting page hook.\n        Converts `text` (as in the initial repository)\n        to text (as to be displayed).\n        \"\"\"\n\n        return text\n\n    @abc.abstractmethod\n    def _get_page(self, topic, request_options=None):\n        \"\"\"\n        Return page for `topic`\n        \"\"\"\n        pass\n\n    def _get_output_format(self, topic):\n        if \"/\" in topic:\n            subquery = topic.split(\"/\")[-1]\n        else:\n            subquery = topic\n\n        if subquery in [\":list\"]:\n            return \"text\"\n        return self._output_format\n\n    # pylint: disable=unused-argument\n    @staticmethod\n    def _get_filetype(topic):\n        \"\"\"\n        Return language name (filetype) for `topic`\n        \"\"\"\n        return None\n\n    def get_page_dict(self, topic, request_options=None):\n        \"\"\"\n        Return page dict for `topic`\n        \"\"\"\n\n        #\n        # if _get_page() returns a dict, use the dictionary\n        # for the answer. It is possible to specify some\n        # useful properties as the part of the answer\n        # (e.g. \"cache\")\n        # answer by _get_page() always overrides all default properties\n        #\n        answer = self._get_page(topic, request_options=request_options)\n        if not isinstance(answer, dict):\n            answer = {\"answer\": answer}\n\n        answer_dict = {\n            \"topic\": topic,\n            \"topic_type\": self._adapter_name,\n            \"format\": self._get_output_format(topic),\n            \"cache\": self._cache_needed,\n        }\n        answer_dict.update(answer)\n\n        # pylint: disable=assignment-from-none\n        filetype = self._get_filetype(topic)\n        if filetype:\n            answer_dict[\"filetype\"] = filetype\n        return answer_dict\n\n    @classmethod\n    def local_repository_location(cls, cheat_sheets_location=False):\n        \"\"\"\n        Return local repository location.\n        If name `self._repository_url` for the class is not specified, return None\n        It is possible that several adapters has the same repository_url,\n        in this case they should use the same local directory.\n        If for some reason the local repository location should be overridden\n        (e.g. if several different branches of the same repository are used)\n        if should set in `self._local_repository_location` of the adapter.\n        If `cheat_sheets_location` is specified, return path of the cheat sheets\n        directory instead of the repository directory.\n        \"\"\"\n\n        dirname = None\n\n        if cls._local_repository_location:\n            dirname = cls._local_repository_location\n\n        if not dirname and cls._repository_url:\n            dirname = cls._repository_url\n            if dirname.startswith(\"https://\"):\n                dirname = dirname[8:]\n            elif dirname.startswith(\"http://\"):\n                dirname = dirname[7:]\n\n        # if we did not manage to find out dirname up to this point,\n        # that means that neither repository url, not repository location\n        # is specified for the adapter, so it should be skipped\n        if not dirname:\n            return None\n\n        if dirname.startswith(\"/\"):\n            return dirname\n\n        # it is possible that several repositories will\n        # be mapped to the same location name\n        # (because only the last part of the path is used)\n        # in this case provide the name in _local_repository_location\n        # (detected by fetch.py)\n        if \"/\" in dirname:\n            dirname = dirname.split(\"/\")[-1]\n\n        path = os.path.join(CONFIG[\"path.repositories\"], dirname)\n\n        if cheat_sheets_location:\n            path = os.path.join(path, cls._cheatsheet_files_prefix)\n\n        return path\n\n    @classmethod\n    def repository_url(cls):\n        \"\"\"\n        Return URL of the upstream repository\n        \"\"\"\n        return cls._repository_url\n\n    @classmethod\n    def fetch_command(cls):\n        \"\"\"\n        Initial fetch of the repository.\n        Return cmdline that has to be executed to fetch the repository.\n        Skipping if `self._repository_url` is not specified\n        \"\"\"\n        if not cls._repository_url:\n            return None\n\n        # in this case `fetch` has to be implemented\n        # in the distinct adapter subclass\n        raise RuntimeError(\n            \"Do not known how to handle this repository: %s\" % cls._repository_url\n        )\n\n    @classmethod\n    def update_command(cls):\n        \"\"\"\n        Update of the repository.\n        Return cmdline that has to be executed to update the repository\n        inside `local_repository_location()`.\n        \"\"\"\n\n        if not cls._repository_url:\n            return None\n\n        local_repository_dir = cls.local_repository_location()\n        if not local_repository_dir:\n            return None\n\n        # in this case `update` has to be implemented\n        # in the distinct adapter subclass\n        raise RuntimeError(\n            \"Do not known how to handle this repository: %s\" % cls._repository_url\n        )\n\n    @classmethod\n    def current_state_command(cls):\n        \"\"\"\n        Get current state of repository (current revision).\n        This is used to find what cache entries should be invalidated.\n        \"\"\"\n\n        if not cls._repository_url:\n            return None\n\n        local_repository_dir = cls.local_repository_location()\n        if not local_repository_dir:\n            return None\n\n        # in this case `update` has to be implemented\n        # in the distinct adapter subclass\n        raise RuntimeError(\n            \"Do not known how to handle this repository: %s\" % cls._repository_url\n        )\n\n    @classmethod\n    def save_state(cls, state):\n        \"\"\"\n        Save state `state` of the repository.\n        Must be called after the cache clean up.\n        \"\"\"\n        local_repository_dir = cls.local_repository_location()\n        state_filename = os.path.join(local_repository_dir, \".cached_revision\")\n        open(state_filename, \"w\").write(state)\n\n    @classmethod\n    def get_state(cls):\n        \"\"\"\n        Return the saved `state` of the repository.\n        If state cannot be read, return None\n        \"\"\"\n\n        local_repository_dir = cls.local_repository_location()\n        state_filename = os.path.join(local_repository_dir, \".cached_revision\")\n        state = None\n        if os.path.exists(state_filename):\n            state = open(state_filename, \"r\").read()\n        return state\n\n    @classmethod\n    def get_updates_list_command(cls):\n        \"\"\"\n        Return the command to get the list of updates\n        since the last update whose id is saved as the repository state (`cached_state`).\n        The list is used to invalidate the cache.\n        \"\"\"\n        return None\n\n    @classmethod\n    def get_updates_list(cls, updated_files_list):\n        \"\"\"\n        Return the pages that have to be invalidated if the files `updates_files_list`\n        were updated in the repository.\n        \"\"\"\n        if not cls._cheatsheet_files_prefix:\n            return updated_files_list\n\n        answer = []\n        cut_len = len(cls._cheatsheet_files_prefix)\n        for entry in updated_files_list:\n            if entry.startswith(cls._cheatsheet_files_prefix):\n                answer.append(entry[cut_len:])\n            else:\n                answer.append(entry)\n        return answer\n\n\ndef all_adapters(as_dict=False):\n    \"\"\"\n    Return list of all known adapters\n    If `as_dict` is True, return dict {'name': adapter} instead of a list.\n    \"\"\"\n\n    def _all_subclasses(cls):\n        return set(cls.__subclasses__()).union(\n            set([s for c in cls.__subclasses__() for s in _all_subclasses(c)])\n        )\n\n    if as_dict:\n        return {x.name(): x for x in _all_subclasses(Adapter)}\n    return list(_all_subclasses(Adapter))\n\n\ndef adapter_by_name(name):\n    \"\"\"\n    Return adapter having this name,\n    or None if nothing found\n    \"\"\"\n    return all_adapters(as_dict=True).get(name)\n"
  },
  {
    "path": "lib/adapter/cheat_cheat.py",
    "content": "\"\"\"\nAdapter for https://github.com/cheat/cheat\n\nCheatsheets are located in `cheat/cheatsheets/`\nEach cheat sheet is a separate file without extension\n\"\"\"\n\n# pylint: disable=relative-import,abstract-method\n\nfrom .git_adapter import GitRepositoryAdapter\n\n\nclass Cheat(GitRepositoryAdapter):\n    \"\"\"\n    cheat/cheat adapter\n    \"\"\"\n\n    _adapter_name = \"cheat\"\n    _output_format = \"code\"\n    _cache_needed = True\n    _repository_url = \"https://github.com/cheat/cheatsheets\"\n    _cheatsheet_files_prefix = \"\"\n    _cheatsheet_file_mask = \"*\"\n"
  },
  {
    "path": "lib/adapter/cheat_sheets.py",
    "content": "\"\"\"\nImplementation of the adapter for the native cheat.sh cheat sheets repository,\ncheat.sheets.  The cheat sheets repository is hierarchically structured: cheat\nsheets covering programming languages are are located in subdirectories.\n\"\"\"\n\n# pylint: disable=relative-import\n\nimport os\nimport glob\n\nfrom .git_adapter import GitRepositoryAdapter\n\n\ndef _remove_initial_underscore(filename):\n    if filename.startswith(\"_\"):\n        filename = filename[1:]\n    return filename\n\n\ndef _sanitize_dirnames(filename, restore=False):\n    \"\"\"\n    Remove (or add) leading _ in the directories names in `filename`\n    The `restore` param means that the path name should be restored from the queryname,\n    i.e. conversion should be done in the opposite direction\n    \"\"\"\n    parts = filename.split(\"/\")\n    newparts = []\n    for part in parts[:-1]:\n        if restore:\n            newparts.append(\"_\" + part)\n            continue\n        if part.startswith(\"_\"):\n            newparts.append(part[1:])\n        else:\n            newparts.append(part)\n    newparts.append(parts[-1])\n\n    return \"/\".join(newparts)\n\n\nclass CheatSheets(GitRepositoryAdapter):\n    \"\"\"\n    Adapter for the cheat.sheets cheat sheets.\n    \"\"\"\n\n    _adapter_name = \"cheat.sheets\"\n    _output_format = \"code\"\n    _repository_url = \"https://github.com/chubin/cheat.sheets\"\n    _cheatsheet_files_prefix = \"sheets/\"\n\n    def _get_list(self, prefix=None):\n        \"\"\"\n        Return all files on the first and the second level,\n        excluding directories and hidden files\n        \"\"\"\n\n        hidden_files = [\"_info.yaml\"]\n        answer = []\n        prefix = os.path.join(\n            self.local_repository_location(), self._cheatsheet_files_prefix\n        )\n        for mask in [\"*\", \"*/*\"]:\n            template = os.path.join(prefix, mask)\n\n            answer += [\n                _sanitize_dirnames(f_name[len(prefix) :])\n                for f_name in glob.glob(template)\n                if not os.path.isdir(f_name)\n                and os.path.basename(f_name) not in hidden_files\n            ]\n\n        return sorted(answer)\n\n    def _get_page(self, topic, request_options=None):\n\n        filename = os.path.join(\n            self.local_repository_location(),\n            self._cheatsheet_files_prefix,\n            _sanitize_dirnames(topic, restore=True),\n        )\n\n        if os.path.exists(filename):\n            answer = self._format_page(open(filename, \"r\").read())\n        else:\n            # though it should not happen\n            answer = \"%s:%s not found\" % (str(self.__class__), topic)\n\n        return answer\n\n\nclass CheatSheetsDir(CheatSheets):\n    \"\"\"\n    Adapter for the cheat sheets directories.\n    Provides pages named according to subdirectories:\n        _dir => dir/\n\n    (currently only _get_list() is used; _get_page is shadowed\n    by the CheatSheets adapter)\n    \"\"\"\n\n    _adapter_name = \"cheat.sheets dir\"\n    _output_format = \"text\"\n\n    def _get_list(self, prefix=None):\n\n        template = os.path.join(\n            self.local_repository_location(), self._cheatsheet_files_prefix, \"*\"\n        )\n\n        answer = sorted(\n            [\n                _remove_initial_underscore(os.path.basename(f_name)) + \"/\"\n                for f_name in glob.glob(template)\n                if os.path.isdir(f_name)\n            ]\n        )\n\n        return answer\n\n    def _get_page(self, topic, request_options=None):\n        \"\"\"\n        Content of the `topic` dir is the list of the pages in the dir\n        \"\"\"\n\n        template = os.path.join(\n            self.local_repository_location(),\n            self._cheatsheet_files_prefix,\n            topic.rstrip(\"/\"),\n            \"*\",\n        )\n\n        answer = sorted([os.path.basename(f_name) for f_name in glob.glob(template)])\n        return \"\\n\".join(answer) + \"\\n\"\n\n    def is_found(self, topic):\n        return CheatSheets.is_found(self, topic.rstrip(\"/\"))\n"
  },
  {
    "path": "lib/adapter/cmd.py",
    "content": "\"\"\" \"\"\"\n\n# pylint: disable=unused-argument,abstract-method\n\nimport os.path\nimport re\nfrom subprocess import Popen, PIPE\n\nfrom .adapter import Adapter\n\n\ndef _get_abspath(path):\n    \"\"\"Find absolute path of the specified `path`\n    according to its\n    \"\"\"\n\n    if path.startswith(\"/\"):\n        return path\n\n    import __main__\n\n    return os.path.join(os.path.dirname(os.path.dirname(__main__.__file__)), path)\n\n\nclass CommandAdapter(Adapter):\n    \"\"\" \"\"\"\n\n    _command = []\n\n    def _get_command(self, topic, request_options=None):\n        return self._command\n\n    def _get_page(self, topic, request_options=None):\n        cmd = self._get_command(topic, request_options=request_options)\n        if cmd:\n            try:\n                proc = Popen(cmd, stdout=PIPE, stderr=PIPE)\n                answer = proc.communicate()[0].decode(\"utf-8\", \"ignore\")\n            except OSError:\n                return (\n                    'ERROR of the \"%s\" adapter: please create an issue'\n                    % self._adapter_name\n                )\n            return answer\n        return \"\"\n\n\nclass Fosdem(CommandAdapter):\n    \"\"\"\n    Show the output of the `current-fosdem-slide` command,\n    which shows the current slide open in some terminal.\n    This was used during the talk at FOSDEM 2019.\n\n    https://www.youtube.com/watch?v=PmiK0JCdh5A\n\n    `sudo` is used here because the session was running under\n    a different user; to be able to use the command via sudo,\n    the following `/etc/suders` entry was added:\n\n    srv    ALL=(ALL:ALL) NOPASSWD: /usr/local/bin/current-fosdem-slide\n\n    Here `srv` is the user under which the cheat.sh server was running\n    \"\"\"\n\n    _adapter_name = \"fosdem\"\n    _output_format = \"ansi\"\n    _pages_list = [\":fosdem\"]\n    _command = [\"sudo\", \"/usr/local/bin/current-fosdem-slide\"]\n\n\nclass Translation(CommandAdapter):\n    \"\"\" \"\"\"\n\n    _adapter_name = \"translation\"\n    _output_format = \"text\"\n    _cache_needed = True\n\n    def _get_page(self, topic, request_options=None):\n        from_, topic = topic.split(\"/\", 1)\n        to_ = request_options.get(\"lang\", \"en\")\n        if \"-\" in from_:\n            from_, to_ = from_.split(\"-\", 1)\n\n        return [\n            \"/home/igor/cheat.sh/bin/get_translation\",\n            from_,\n            to_,\n            topic.replace(\"+\", \" \"),\n        ]\n\n\nclass AdapterRfc(CommandAdapter):\n    \"\"\"\n    Show RFC by its number.\n    Exported as: \"/rfc/NUMBER\"\n    \"\"\"\n\n    _adapter_name = \"rfc\"\n    _output_format = \"text\"\n    _cache_needed = True\n    _command = [\"share/adapters/rfc.sh\"]\n\n    def _get_command(self, topic, request_options=None):\n        cmd = self._command[:]\n        if not cmd[0].startswith(\"/\"):\n            cmd[0] = _get_abspath(cmd[0])\n\n        # cut rfc/ off\n        if topic.startswith(\"rfc/\"):\n            topic = topic[4:]\n\n        return cmd + [topic]\n\n    def _get_list(self, prefix=None):\n        return list(\"rfc/%s\" % x for x in range(1, 8649))\n\n    def is_found(self, topic):\n        return True\n\n\nclass AdapterOeis(CommandAdapter):\n    \"\"\"\n    Show OEIS by its number.\n    Exported as: \"/oeis/NUMBER\"\n    \"\"\"\n\n    _adapter_name = \"oeis\"\n    _output_format = \"text+code\"\n    _cache_needed = True\n    _command = [\"share/adapters/oeis.sh\"]\n\n    @staticmethod\n    def _get_filetype(topic):\n        if \"/\" in topic:\n            language = topic.split(\"/\")[-1].lower()\n            return language\n        return \"bash\"\n\n    def _get_command(self, topic, request_options=None):\n        cmd = self._command[:]\n        if not cmd[0].startswith(\"/\"):\n            cmd[0] = _get_abspath(cmd[0])\n\n        # cut oeis/ off\n        # Replace all non (alphanumeric, '-', ':') chars with Spaces to delimit args to oeis.sh\n        if topic.startswith(\"oeis/\"):\n            topic = topic[5:]\n\n            suffix = \"\"\n            if topic.endswith(\"/:list\"):\n                suffix = \" :list\"\n                topic = topic[:-6]\n\n            topic = re.sub(\"[^a-zA-Z0-9-:]+\", \" \", topic) + suffix\n\n        return cmd + [topic]\n\n    def is_found(self, topic):\n        return True\n\n\nclass AdapterChmod(CommandAdapter):\n    \"\"\"\n    Show chmod numeric values and strings\n    Exported as: \"/chmod/NUMBER\"\n    \"\"\"\n\n    _adapter_name = \"chmod\"\n    _output_format = \"text\"\n    _cache_needed = True\n    _command = [\"share/adapters/chmod.sh\"]\n\n    def _get_command(self, topic, request_options=None):\n        cmd = self._command[:]\n\n        # cut chmod/ off\n        # remove all non (alphanumeric, '-') chars\n        if topic.startswith(\"chmod/\"):\n            topic = topic[6:]\n            topic = re.sub(\"[^a-zA-Z0-9-]\", \"\", topic)\n\n        return cmd + [topic]\n\n    def is_found(self, topic):\n        return True\n"
  },
  {
    "path": "lib/adapter/common.py",
    "content": "class Adapter(object):\n    pass\n\n\nclass cheatAdapter(Adapter):\n    pass\n"
  },
  {
    "path": "lib/adapter/git_adapter.py",
    "content": "\"\"\"\nImplementation of `GitRepositoryAdapter`, adapter that is used to handle git repositories\n\"\"\"\n\nimport glob\nimport os\n\nfrom .adapter import Adapter  # pylint: disable=relative-import\n\n\ndef _get_filenames(path):\n    return [os.path.split(topic)[1] for topic in glob.glob(path)]\n\n\nclass RepositoryAdapter(Adapter):\n    \"\"\"\n    Implements methods needed to handle standard\n    repository based adapters.\n    \"\"\"\n\n    def _get_list(self, prefix=None):\n        \"\"\"\n        List of files in the cheat sheets directory\n        with the extension removed\n        \"\"\"\n\n        answer = _get_filenames(\n            os.path.join(\n                self.local_repository_location(),\n                self._cheatsheet_files_prefix,\n                \"*\" + self._cheatsheet_files_extension,\n            )\n        )\n\n        ext = self._cheatsheet_files_extension\n        if ext:\n            answer = [\n                filename[: -len(ext)] for filename in answer if filename.endswith(ext)\n            ]\n\n        return answer\n\n    def _get_page(self, topic, request_options=None):\n\n        filename = os.path.join(\n            self.local_repository_location(), self._cheatsheet_files_prefix, topic\n        )\n\n        if os.path.exists(filename) and not os.path.isdir(filename):\n            answer = self._format_page(open(filename, \"r\").read())\n        else:\n            # though it should not happen\n            answer = \"%s:%s not found\" % (str(self.__class__), topic)\n\n        return answer\n\n\nclass GitRepositoryAdapter(RepositoryAdapter):  # pylint: disable=abstract-method\n    \"\"\"\n    Implements all methods needed to handle cache handling\n    for git-repository-based adapters\n    \"\"\"\n\n    @classmethod\n    def fetch_command(cls):\n        \"\"\"\n        Initial fetch of the repository.\n        Return cmdline that has to be executed to fetch the repository.\n        Skipping if `self._repository_url` is not specified\n        \"\"\"\n\n        if not cls._repository_url:\n            return None\n\n        if not cls._repository_url.startswith(\"https://github.com/\"):\n            # in this case `fetch` has to be implemented\n            # in the distinct adapter subclass\n            raise RuntimeError(\n                \"Do not known how to handle this repository: %s\" % cls._repository_url\n            )\n\n        local_repository_dir = cls.local_repository_location()\n        if not local_repository_dir:\n            return None\n\n        return [\"git\", \"clone\", \"--depth=1\", cls._repository_url, local_repository_dir]\n\n    @classmethod\n    def update_command(cls):\n        \"\"\"\n        Update of the repository.\n        Return cmdline that has to be executed to update the repository\n        inside `local_repository_location()`.\n        \"\"\"\n\n        if not cls._repository_url:\n            return None\n\n        local_repository_dir = cls.local_repository_location()\n        if not local_repository_dir:\n            return None\n\n        if not cls._repository_url.startswith(\"https://github.com/\"):\n            # in this case `update` has to be implemented\n            # in the distinct adapter subclass\n            raise RuntimeError(\n                \"Do not known how to handle this repository: %s\" % cls._repository_url\n            )\n\n        return [\"git\", \"pull\"]\n\n    @classmethod\n    def current_state_command(cls):\n        \"\"\"\n        Get current state of repository (current revision).\n        This is used to find what cache entries should be invalidated.\n        \"\"\"\n\n        if not cls._repository_url:\n            return None\n\n        local_repository_dir = cls.local_repository_location()\n        if not local_repository_dir:\n            return None\n\n        if not cls._repository_url.startswith(\"https://github.com/\"):\n            # in this case `update` has to be implemented\n            # in the distinct adapter subclass\n            raise RuntimeError(\n                \"Do not known how to handle this repository: %s\" % cls._repository_url\n            )\n\n        return [\"git\", \"rev-parse\", \"--short\", \"HEAD\", \"--\"]\n\n    @classmethod\n    def save_state(cls, state):\n        \"\"\"\n        Save state `state` of the repository.\n        Must be called after the cache clean up.\n        \"\"\"\n        local_repository_dir = cls.local_repository_location()\n        state_filename = os.path.join(local_repository_dir, \".cached_revision\")\n        open(state_filename, \"wb\").write(state)\n\n    @classmethod\n    def get_state(cls):\n        \"\"\"\n        Return the saved `state` of the repository.\n        If state cannot be read, return None\n        \"\"\"\n\n        local_repository_dir = cls.local_repository_location()\n        state_filename = os.path.join(local_repository_dir, \".cached_revision\")\n        state = None\n        if os.path.exists(state_filename):\n            state = open(state_filename, \"r\").read()\n        return state\n\n    @classmethod\n    def get_updates_list_command(cls):\n        \"\"\"\n        Return list of updates since the last update whose id is saved as the repository state.\n        The list is used to invalidate the cache.\n        \"\"\"\n        current_state = cls.get_state()\n        if not current_state:\n            return [\"git\", \"ls-tree\", \"--full-tree\", \"-r\", \"--name-only\", \"HEAD\", \"--\"]\n        return [\"git\", \"diff\", \"--name-only\", current_state, \"HEAD\", \"--\"]\n"
  },
  {
    "path": "lib/adapter/internal.py",
    "content": "\"\"\"\nConfiguration parameters:\n\n    frontend.styles\n    path.internal.pages\n\"\"\"\n\nimport sys\nimport os\nimport collections\n\ntry:\n    from rapidfuzz import process, fuzz\n\n    _USING_FUZZYWUZZY = False\nexcept ImportError:\n    from fuzzywuzzy import process, fuzz\n\n    _USING_FUZZYWUZZY = True\n\nfrom config import CONFIG\nfrom .adapter import Adapter\nfrom fmt.internal import colorize_internal\n\n_INTERNAL_TOPICS = [\n    \":cht.sh\",\n    \":bash_completion\",\n    \":emacs\",\n    \":emacs-ivy\",\n    \":firstpage\",\n    \":firstpage-v1\",\n    \":firstpage-v2\",\n    \":fish\",\n    \":help\",\n    \":intro\",\n    \":list\",\n    \":post\",\n    \":styles\",\n    \":styles-demo\",\n    \":vim\",\n    \":zsh\",\n]\n\n_COLORIZED_INTERNAL_TOPICS = [\n    \":intro\",\n]\n\n\nclass InternalPages(Adapter):\n\n    _adapter_name = \"internal\"\n    _output_format = \"ansi\"\n\n    def __init__(self, get_topic_type=None, get_topics_list=None):\n        Adapter.__init__(self)\n        self.get_topic_type = get_topic_type\n        self.get_topics_list = get_topics_list\n\n    def _get_stat(self):\n        stat = collections.Counter(\n            [self.get_topic_type(topic) for topic in self.get_topics_list()]\n        )\n\n        answer = \"\"\n        for key, val in stat.items():\n            answer += \"%s %s\\n\" % (key, val)\n        return answer\n\n    @staticmethod\n    def get_list(prefix=None):\n        return _INTERNAL_TOPICS\n\n    def _get_list_answer(self, topic, request_options=None):\n        if \"/\" in topic:\n            topic_type, topic_name = topic.split(\"/\", 1)\n            if topic_name == \":list\":\n                topic_list = [\n                    x[len(topic_type) + 1 :]\n                    for x in self.get_topics_list()\n                    if x.startswith(topic_type + \"/\")\n                ]\n                return \"\\n\".join(topic_list) + \"\\n\"\n\n        answer = \"\"\n        if topic == \":list\":\n            answer = \"\\n\".join(x for x in self.get_topics_list()) + \"\\n\"\n\n        return answer\n\n    def _get_page(self, topic, request_options=None):\n        if topic.endswith(\"/:list\") or topic.lstrip(\"/\") == \":list\":\n            return self._get_list_answer(topic)\n\n        answer = \"\"\n        if topic == \":styles\":\n            answer = \"\\n\".join(CONFIG[\"frontend.styles\"]) + \"\\n\"\n        elif topic == \":stat\":\n            answer = self._get_stat() + \"\\n\"\n        elif topic in _INTERNAL_TOPICS:\n            answer = open(\n                os.path.join(CONFIG[\"path.internal.pages\"], topic[1:] + \".txt\"), \"r\"\n            ).read()\n            if topic in _COLORIZED_INTERNAL_TOPICS:\n                answer = colorize_internal(answer)\n\n        return answer\n\n    def is_found(self, topic):\n        return topic in self.get_list() or topic.endswith(\"/:list\")\n\n\nclass UnknownPages(InternalPages):\n\n    _adapter_name = \"unknown\"\n    _output_format = \"text\"\n\n    @staticmethod\n    def get_list(prefix=None):\n        return []\n\n    @staticmethod\n    def is_found(topic):\n        return True\n\n    def _get_page(self, topic, request_options=None):\n        topics_list = self.get_topics_list()\n        if topic.startswith(\":\"):\n            topics_list = [x for x in topics_list if x.startswith(\":\")]\n        else:\n            topics_list = [x for x in topics_list if not x.startswith(\":\")]\n\n        if _USING_FUZZYWUZZY:\n            possible_topics = process.extract(topic, topics_list, scorer=fuzz.ratio)[:3]\n        else:\n            possible_topics = process.extract(\n                topic, topics_list, limit=3, scorer=fuzz.ratio\n            )\n        possible_topics_text = \"\\n\".join(\n            [(\"    * %s %s\" % (x[0], int(x[1]))) for x in possible_topics]\n        )\n        return (\n            \"\"\"\nUnknown topic.\nDo you mean one of these topics maybe?\n\n%s\n    \"\"\"\n            % possible_topics_text\n        )\n\n\nclass Search(Adapter):\n\n    _adapter_name = \"search\"\n    _output_format = \"text\"\n    _cache_needed = False\n\n    @staticmethod\n    def get_list(prefix=None):\n        return []\n\n    def is_found(self, topic):\n        return False\n"
  },
  {
    "path": "lib/adapter/latenz.py",
    "content": "\"\"\"\nAdapter for the curlable latencies numbers (chubin/late.nz)\nThis module can be an example of a adapter for a python project.\n\nThe adapter exposes one page (\"latencies\") and several its aliases\n(\"latencies\", \"late.nz\", \"latency\")\n\"\"\"\n\n# pylint: disable=relative-import\n\nimport sys\nimport os\nfrom .git_adapter import GitRepositoryAdapter\n\n\nclass Latenz(GitRepositoryAdapter):\n    \"\"\"\n    chubin/late.nz Adapter\n    \"\"\"\n\n    _adapter_name = \"late.nz\"\n    _output_format = \"ansi\"\n    _repository_url = \"https://github.com/chubin/late.nz\"\n\n    def _get_page(self, topic, request_options=None):\n        sys.path.append(os.path.join(self.local_repository_location(), \"bin\"))\n        import latencies\n\n        return latencies.render()\n\n    def _get_list(self, prefix=None):\n        return [\"latencies\"]\n\n    def is_found(self, topic):\n        return topic.lower() in [\"latencies\", \"late.nz\", \"latency\"]\n"
  },
  {
    "path": "lib/adapter/learnxiny.py",
    "content": "\"\"\"\nAdapters for the cheat sheets from the Learn X in Y project\n\nConfiguration parameters:\n\n    log.level\n\"\"\"\n\n# pylint: disable=relative-import\n\nfrom __future__ import print_function\nimport os\nimport re\nfrom config import CONFIG\nfrom .git_adapter import GitRepositoryAdapter\n\n\nclass LearnXinY(GitRepositoryAdapter):\n    \"\"\"\n    Adapter for the LearnXinY project\n    \"\"\"\n\n    _adapter_name = \"learnxiny\"\n    _output_format = \"code\"\n    _cache_needed = True\n    _repository_url = \"https://github.com/adambard/learnxinyminutes-docs\"\n\n    def __init__(self):\n        self.adapters = _ADAPTERS\n        GitRepositoryAdapter.__init__(self)\n\n    def _get_page(self, topic, request_options=None):\n        \"\"\"\n        Return cheat sheet for `topic`\n        or empty string if nothing found\n        \"\"\"\n        lang, topic = topic.split(\"/\", 1)\n        if lang not in self.adapters:\n            return \"\"\n        return self.adapters[lang].get_page(topic)\n\n    def _get_list(self, prefix=None):\n        \"\"\"\n        Return list of all learnxiny topics\n        \"\"\"\n        answer = []\n        for language_adapter in self.adapters.values():\n            answer += language_adapter.get_list(prefix=True)\n        return answer\n\n    def is_found(self, topic):\n        \"\"\"\n        Return whether `topic` is a valid learnxiny topic\n        \"\"\"\n\n        if \"/\" not in topic:\n            return False\n\n        lang, topic = topic.split(\"/\", 1)\n        if lang not in self.adapters:\n            return False\n\n        return self.adapters[lang].is_valid(topic)\n\n\nclass LearnXYAdapter(object):\n    \"\"\"\n    Parent class of all languages adapters\n    \"\"\"\n\n    _learn_xy_path = LearnXinY.local_repository_location()\n    _replace_with = {}\n    _filename = \"\"\n    prefix = \"\"\n    _replace_with = {}\n    _splitted = True\n    _block_cut_start = 2\n    _block_cut_end = 0\n\n    def __init__(self):\n        self._whole_cheatsheet = self._read_cheatsheet()\n        self._blocks = self._extract_blocks()\n\n        self._topics_list = [x for x, _ in self._blocks]\n        if \"Comments\" in self._topics_list:\n            self._topics_list = [x for x in self._topics_list if x != \"Comments\"] + [\n                \"Comments\"\n            ]\n        self._topics_list += [\":learn\", \":list\"]\n        if self._whole_cheatsheet and CONFIG.get(\"log.level\") >= 5:\n            print(self.prefix, self._topics_list)\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(r\"////////*\", before)\n            and re.match(r\"// \", now)\n            and re.match(r\"////////*\", after)\n        ):\n            block_name = re.sub(r\"//\\s*\", \"\", now).replace(\"(\", \"\").replace(\")\", \"\")\n            block_name = \"_\".join(block_name.strip(\", \").split())\n            for character in \"/,\":\n                block_name = block_name.replace(character, \"\")\n            for k in self._replace_with:\n                if k in block_name:\n                    block_name = self._replace_with[k]\n            return block_name\n        return None\n\n    def _cut_block(self, block, start_block=False):\n        if not start_block:\n            answer = block[self._block_cut_start : -self._block_cut_end]\n        if answer == []:\n            return answer\n        if answer[0].strip() == \"\":\n            answer = answer[1:]\n        if answer[-1].strip() == \"\":\n            answer = answer[:1]\n        return answer\n\n    def _read_cheatsheet(self):\n        filename = os.path.join(self._learn_xy_path, self._filename)\n\n        # if cheat sheets are not there (e.g. were not yet fetched),\n        # just skip it\n        if not os.path.exists(filename):\n            return None\n\n        with open(filename) as f_cheat_sheet:\n            code_mode = False\n            answer = []\n            for line in f_cheat_sheet.readlines():\n                if line.startswith(\"```\"):\n                    if not code_mode:\n                        code_mode = True\n                        continue\n                    else:\n                        code_mode = False\n                if code_mode:\n                    answer.append(line.rstrip(\"\\n\"))\n            return answer\n\n    def _extract_blocks(self):\n\n        if not self._splitted:\n            return []\n\n        lines = self._whole_cheatsheet\n        if lines is None:\n            return []\n\n        answer = []\n\n        block = []\n        block_name = \"Comments\"\n        for before, now, after in zip([\"\"] + lines, lines, lines[1:]):\n            new_block_name = self._is_block_separator(before, now, after)\n            if new_block_name:\n                if block_name:\n                    block_text = self._cut_block(block)\n                    if block_text != []:\n                        answer.append((block_name, block_text))\n                block_name = new_block_name\n                block = []\n                continue\n            else:\n                block.append(before)\n\n        answer.append((block_name, self._cut_block(block)))\n        return answer\n\n    def is_valid(self, name):\n        \"\"\"\n        Check whether topic `name` is valid.\n        \"\"\"\n\n        for topic_list in self._topics_list:\n            if topic_list == name:\n                return True\n        return False\n\n    def get_list(self, prefix=None):\n        \"\"\"\n        Get list of topics for `prefix`\n        \"\"\"\n        if prefix:\n            return [\"%s/%s\" % (self.prefix, x) for x in self._topics_list]\n        return self._topics_list\n\n    def get_page(self, name, partial=False):\n        \"\"\"\n        Return specified cheat sheet `name` for the language.\n        If `partial`, cheat sheet name may be shortened\n        \"\"\"\n\n        if name == \":list\":\n            return \"\\n\".join(self.get_list()) + \"\\n\"\n\n        if name == \":learn\":\n            if self._whole_cheatsheet:\n                return \"\\n\".join(self._whole_cheatsheet) + \"\\n\"\n            else:\n                return \"\"\n\n        if partial:\n            possible_names = []\n            for block_name, _ in self._blocks:\n                if block_name.startswith(name):\n                    possible_names.append(block_name)\n            if possible_names == [] or len(possible_names) > 1:\n                return None\n            name = possible_names[0]\n\n        for block_name, block_contents in self._blocks:\n            if block_name == name:\n                return \"\\n\".join(block_contents)\n\n        return None\n\n\n#\n# Specific programming languages LearnXY cheat sheets configurations\n# Contains much code for the moment; should contain data only\n# ideally should be replaced with YAML\n#\n\n\nclass LearnAwkAdapter(LearnXYAdapter):\n    \"Learn AWK in Y Minutes\"\n\n    prefix = \"awk\"\n    _filename = \"awk.html.markdown\"\n    _splitted = False\n\n\nclass LearnBashAdapter(LearnXYAdapter):\n    \"Learn Bash in Y Minutes\"\n\n    prefix = \"bash\"\n    _filename = \"bash.html.markdown\"\n    _splitted = False\n\n\nclass LearnBfAdapter(LearnXYAdapter):\n    \"Learn Brainfuck in Y Minutes\"\n\n    prefix = \"bf\"\n    _filename = \"bf.html.markdown\"\n    _splitted = False\n\n\nclass LearnCAdapter(LearnXYAdapter):\n    \"Learn C in Y Minutes\"\n\n    prefix = \"c\"\n    _filename = \"c.html.markdown\"\n    _splitted = False\n\n\nclass LearnChapelAdapter(LearnXYAdapter):\n    \"Learn Chapel in Y Minutes\"\n\n    prefix = \"chapel\"\n    _filename = \"chapel.html.markdown\"\n    _splitted = False\n\n\nclass LearnClojureAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn Clojure in Y Minutes\n    \"\"\"\n\n    prefix = \"clojure\"\n    _filename = \"clojure.html.markdown\"\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(r\"\\s*$\", before)\n            and re.match(r\";\\s*\", now)\n            and re.match(r\";;;;;;+\", after)\n        ):\n            block_name = re.sub(r\";\\s*\", \"\", now)\n            block_name = \"_\".join(\n                [x.strip(\",&:\") for x in block_name.strip(\", \").split()]\n            )\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        if not start_block:\n            answer = block[2:]\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnCoffeeScriptAdapter(LearnXYAdapter):\n    \"Learn coffeescript in Y Minutes\"\n\n    prefix = \"coffee\"\n    _filename = \"coffeescript.html.markdown\"\n    _splitted = False\n\n\nclass LearnCppAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn C++ in Y Minutes\n    \"\"\"\n\n    prefix = \"cpp\"\n    _filename = \"c++.html.markdown\"\n    _replace_with = {\n        \"More_about_Objects\": \"Prototypes\",\n    }\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(r\"////////*\", before)\n            and re.match(r\"// \", now)\n            and re.match(r\"////////*\", after)\n        ):\n            block_name = re.sub(r\"//\\s*\", \"\", now).replace(\"(\", \"\").replace(\")\", \"\")\n            block_name = \"_\".join(block_name.strip(\", \").split())\n            for character in \"/,\":\n                block_name = block_name.replace(character, \"\")\n            for k in self._replace_with:\n                if k in block_name:\n                    block_name = self._replace_with[k]\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        answer = block[2:-1]\n        if answer == []:\n            return answer\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnCsharpAdapter(LearnXYAdapter):\n    \"Learn C# in Y Minutes\"\n\n    prefix = \"csharp\"\n    _filename = \"csharp.html.markdown\"\n    _splitted = False\n\n\nclass LearnDAdapter(LearnXYAdapter):\n    \"Learn D in Y Minutes\"\n\n    prefix = \"d\"\n    _filename = \"d.html.markdown\"\n    _splitted = False\n\n\nclass LearnDartAdapter(LearnXYAdapter):\n    \"Learn Dart in Y Minutes\"\n\n    prefix = \"dart\"\n    _filename = \"dart.html.markdown\"\n    _splitted = False\n\n\nclass LearnFactorAdapter(LearnXYAdapter):\n    \"Learn Factor in Y Minutes\"\n\n    prefix = \"factor\"\n    _filename = \"factor.html.markdown\"\n    _splitted = False\n\n\nclass LearnForthAdapter(LearnXYAdapter):\n    \"Learn Forth in Y Minutes\"\n\n    prefix = \"forth\"\n    _filename = \"forth.html.markdown\"\n    _splitted = False\n\n\nclass LearnFsharpAdapter(LearnXYAdapter):\n    \"Learn F# in Y Minutes\"\n\n    prefix = \"fsharp\"\n    _filename = \"fsharp.html.markdown\"\n    _splitted = False\n\n\nclass LearnElispAdapter(LearnXYAdapter):\n    \"Learn Elisp in Y Minutes\"\n\n    prefix = \"elisp\"\n    _filename = \"elisp.html.markdown\"\n    _splitted = False\n\n\nclass LearnElixirAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn Elixir in Y Minutes\n    \"\"\"\n\n    prefix = \"elixir\"\n    _filename = \"elixir.html.markdown\"\n    _replace_with = {\n        \"More_about_Objects\": \"Prototypes\",\n    }\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(r\"## ---*\", before)\n            and re.match(r\"## --\", now)\n            and re.match(r\"## ---*\", after)\n        ):\n            block_name = re.sub(r\"## --\\s*\", \"\", now)\n            block_name = \"_\".join(block_name.strip(\", \").split())\n            for character in \"/,\":\n                block_name = block_name.replace(character, \"\")\n            for k in self._replace_with:\n                if k in block_name:\n                    block_name = self._replace_with[k]\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        answer = block[2:-1]\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnElmAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn Elm in Y Minutes\n    \"\"\"\n\n    prefix = \"elm\"\n    _filename = \"elm.html.markdown\"\n    _replace_with = {\n        \"More_about_Objects\": \"Prototypes\",\n    }\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(r\"\\s*\", before)\n            and re.match(r\"\\{--.*--\\}\", now)\n            and re.match(r\"\\s*\", after)\n        ):\n            block_name = re.sub(r\"\\{--+\\s*\", \"\", now)\n            block_name = re.sub(r\"--\\}\", \"\", block_name)\n            block_name = \"_\".join(block_name.strip(\", \").split())\n            for character in \"/,\":\n                block_name = block_name.replace(character, \"\")\n            for k in self._replace_with:\n                if k in block_name:\n                    block_name = self._replace_with[k]\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        answer = block[2:-1]\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnErlangAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn Erlang in Y Minutes\n    \"\"\"\n\n    prefix = \"erlang\"\n    _filename = \"erlang.html.markdown\"\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(\"%%%%%%+\", before)\n            and re.match(r\"%%\\s+[0-9]+\\.\", now)\n            and re.match(\"%%%%%%+\", after)\n        ):\n            block_name = re.sub(r\"%%+\\s+[0-9]+\\.\\s*\", \"\", now)\n            block_name = \"_\".join(block_name.strip(\".\").strip().split())\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        answer = block[2:-1]\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnFortranAdapter(LearnXYAdapter):\n    \"Learn Fortran in Y Minutes\"\n\n    prefix = \"fortran\"\n    _filename = \"fortran95.html.markdown\"\n    _splitted = False\n\n\nclass LearnGoAdapter(LearnXYAdapter):\n    \"Learn Go in Y Minutes\"\n\n    prefix = \"go\"\n    _filename = \"go.html.markdown\"\n    _splitted = False\n\n\nclass LearnGroovyAdapter(LearnXYAdapter):\n    \"Learn Groovy in Y Minutes\"\n\n    prefix = \"groovy\"\n    _filename = \"groovy.html.markdown\"\n    _splitted = False\n\n\nclass LearnJavaAdapter(LearnXYAdapter):\n    \"Learn Java in Y Minutes\"\n\n    prefix = \"java\"\n    _filename = \"java.html.markdown\"\n    _splitted = False\n\n\nclass LearnJavaScriptAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn JavaScript in Y Minutes\n    \"\"\"\n\n    prefix = \"js\"\n    _filename = \"javascript.html.markdown\"\n    _replace_with = {\n        \"More_about_Objects\": \"Prototypes\",\n    }\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(\"//////+\", before)\n            and re.match(r\"//+\\s+[0-9]+\\.\", now)\n            and re.match(r\"\\s*\", after)\n        ):\n            block_name = re.sub(r\"//+\\s+[0-9]+\\.\\s*\", \"\", now)\n            block_name = \"_\".join(block_name.strip(\", \").split())\n            for k in self._replace_with:\n                if k in block_name:\n                    block_name = self._replace_with[k]\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        answer = block[2:-1]\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnJuliaAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn Julia in Y Minutes\n    \"\"\"\n\n    prefix = \"julia\"\n    _filename = \"julia.html.markdown\"\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(\"####+\", before)\n            and re.match(r\"##\\s*\", now)\n            and re.match(\"####+\", after)\n        ):\n            block_name = re.sub(r\"##\\s+[0-9]+\\.\\s*\", \"\", now)\n            block_name = \"_\".join(block_name.strip(\", \").split())\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        answer = block[2:-1]\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnHaskellAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn Haskell in Y Minutes\n    \"\"\"\n\n    prefix = \"haskell\"\n    _filename = \"haskell.html.markdown\"\n    _replace_with = {\n        \"More_about_Objects\": \"Prototypes\",\n    }\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(\"------+\", before)\n            and re.match(r\"--+\\s+[0-9]+\\.\", now)\n            and re.match(\"------+\", after)\n        ):\n            block_name = re.sub(r\"--+\\s+[0-9]+\\.\\s*\", \"\", now)\n            block_name = \"_\".join(block_name.strip(\", \").split())\n            for k in self._replace_with:\n                if k in block_name:\n                    block_name = self._replace_with[k]\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        answer = block[2:-1]\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnLispAdapter(LearnXYAdapter):\n    \"Learn Lisp in Y Minutes\"\n\n    prefix = \"lisp\"\n    _filename = \"common-lisp.html.markdown\"\n    _splitted = False\n\n\nclass LearnLuaAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn Lua in Y Minutes\n    \"\"\"\n\n    prefix = \"lua\"\n    _filename = \"lua.html.markdown\"\n    _replace_with = {\n        \"1_Metatables_and_metamethods\": \"Metatables\",\n        \"2_Class-like_tables_and_inheritance\": \"Class-like_tables\",\n        \"Variables_and_flow_control\": \"Flow_control\",\n    }\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(\"-----+\", before)\n            and re.match(\"-------+\", after)\n            and re.match(r\"--\\s+[0-9]+\\.\", now)\n        ):\n            block_name = re.sub(r\"--+\\s+[0-9]+\\.\\s*\", \"\", now)\n            block_name = \"_\".join(block_name.strip(\".\").strip().split())\n            if block_name in self._replace_with:\n                block_name = self._replace_with[block_name]\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        answer = block[2:-1]\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnMathematicaAdapter(LearnXYAdapter):\n    \"Learn Mathematica in Y Minutes\"\n\n    prefix = \"mathematica\"\n    _filename = \"wolfram.html.markdown\"\n    _splitted = False\n\n\nclass LearnMatlabAdapter(LearnXYAdapter):\n    \"Learn Matlab in Y Minutes\"\n\n    prefix = \"matlab\"\n    _filename = \"matlab.html.markdown\"\n    _splitted = False\n\n\nclass LearnOctaveAdapter(LearnXYAdapter):\n    \"Learn Octave in Y Minutes\"\n\n    prefix = \"octave\"\n    _filename = \"matlab.html.markdown\"\n    _splitted = False\n\n\nclass LearnKotlinAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn Kotlin in Y Minutes\n    \"\"\"\n\n    prefix = \"kotlin\"\n    _filename = \"kotlin.html.markdown\"\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(\"#######+\", before)\n            and re.match(\"#######+\", after)\n            and re.match(r\"#+\\s+[0-9]+\\.\", now)\n        ):\n            block_name = re.sub(r\"#+\\s+[0-9]+\\.\\s*\", \"\", now)\n            block_name = \"_\".join(block_name.strip().split())\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        answer = block[2:-1]\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnObjectiveCAdapter(LearnXYAdapter):\n    \"Learn Objective C in Y Minutes\"\n\n    prefix = \"objective-c\"\n    _filename = \"objective-c.html.markdown\"\n    _splitted = False\n\n\nclass LearnOCamlAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn OCaml in Y Minutes\n    \"\"\"\n\n    prefix = \"ocaml\"\n    _filename = \"ocaml.html.markdown\"\n    _replace_with = {\n        \"More_about_Objects\": \"Prototypes\",\n    }\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(r\"\\s*\", before)\n            and re.match(r\"\\(\\*\\*\\*+\", now)\n            and re.match(r\"\\s*\", after)\n        ):\n            block_name = re.sub(r\"\\(\\*\\*\\*+\\s*\", \"\", now)\n            block_name = re.sub(r\"\\s*\\*\\*\\*\\)\", \"\", block_name)\n            block_name = \"_\".join(block_name.strip(\", \").split())\n            for k in self._replace_with:\n                if k in block_name:\n                    block_name = self._replace_with[k]\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        answer = block[2:-1]\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnPerlAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn Perl in Y Minutes\n    \"\"\"\n\n    prefix = \"perl\"\n    _filename = \"perl.html.markdown\"\n    _replace_with = {\n        \"Conditional_and_looping_constructs\": \"Control_Flow\",\n        \"Perl_variable_types\": \"Types\",\n        \"Files_and_I/O\": \"Files\",\n        \"Writing_subroutines\": \"Subroutines\",\n    }\n\n    def _is_block_separator(self, before, now, after):\n        if re.match(r\"####+\\s+\", now):\n            block_name = re.sub(r\"#+\\s\", \"\", now)\n            block_name = \"_\".join(block_name.strip().split())\n            if block_name in self._replace_with:\n                block_name = self._replace_with[block_name]\n            return block_name\n        else:\n            return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        if not start_block:\n            answer = block[2:]\n        if answer == []:\n            return answer\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnPerl6Adapter(LearnXYAdapter):\n    \"Learn Perl 6 in Y Minutes\"\n\n    prefix = \"perl6\"\n    _filename = \"perl6.html.markdown\"\n    _splitted = False\n\n\nclass LearnPHPAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn PHP in Y Minutes\n    \"\"\"\n\n    prefix = \"php\"\n    _filename = \"php.html.markdown\"\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(r\"/\\*\\*\\*\\*\\*+\", before)\n            and re.match(r\"\\s*\\*/\", after)\n            and re.match(r\"\\s*\\*\\s*\", now)\n        ):\n            block_name = re.sub(r\"\\s*\\*\\s*\", \"\", now)\n            block_name = re.sub(r\"&\", \"\", block_name)\n            block_name = \"_\".join(block_name.strip().split())\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        return block[2:]\n\n\nclass LearnPythonAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn Python in Y Minutes\n    \"\"\"\n\n    prefix = \"python\"\n    _filename = \"python.html.markdown\"\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(\"#######+\", before)\n            and re.match(\"#######+\", after)\n            and re.match(r\"#+\\s+[0-9]+\\.\", now)\n        ):\n            block_name = re.sub(r\"#+\\s+[0-9]+\\.\\s*\", \"\", now)\n            block_name = \"_\".join(block_name.strip().split())\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        answer = block[2:-1]\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnPython3Adapter(LearnXYAdapter):\n    \"Learn Python 3 in Y Minutes\"\n\n    prefix = \"python3\"\n    _filename = \"python3.html.markdown\"\n    _splitted = False\n\n\nclass LearnRAdapter(LearnXYAdapter):\n    \"Learn R in Y Minutes\"\n\n    prefix = \"r\"\n    _filename = \"r.html.markdown\"\n    _splitted = False\n\n\nclass LearnRacketAdapter(LearnXYAdapter):\n    \"Learn Racket in Y Minutes\"\n\n    prefix = \"racket\"\n    _filename = \"racket.html.markdown\"\n    _splitted = False\n\n\nclass LearnRubyAdapter(LearnXYAdapter):\n    \"\"\"\n    Learn Ruby in Y Minutes\n\n    Format of the file was changed, so we have to fix the function too.\n    This case is a good case for health check:\n    if number of extracted cheat sheets is suddenly became 1,\n    one should check the markup\n    \"\"\"\n\n    prefix = \"ruby\"\n    _filename = \"ruby.html.markdown\"\n\n    def _is_block_separator(self, before, now, after):\n        if (\n            re.match(\"#######+\", before)\n            and re.match(\"#######+\", after)\n            and re.match(r\"#+\\s+[0-9]+\\.\", now)\n        ):\n            block_name = re.sub(r\"#+\\s+[0-9]+\\.\\s*\", \"\", now)\n            block_name = \"_\".join(block_name.strip().split())\n            return block_name\n        return None\n\n    @staticmethod\n    def _cut_block(block, start_block=False):\n        answer = block[2:-1]\n        if answer[0].split() == \"\":\n            answer = answer[1:]\n        if answer[-1].split() == \"\":\n            answer = answer[:1]\n        return answer\n\n\nclass LearnRustAdapter(LearnXYAdapter):\n    \"Learn Rust in Y Minutes\"\n\n    prefix = \"rust\"\n    _filename = \"rust.html.markdown\"\n    _splitted = False\n\n\nclass LearnSolidityAdapter(LearnXYAdapter):\n    \"Learn Solidity in Y Minutes\"\n\n    prefix = \"solidity\"\n    _filename = \"solidity.html.markdown\"\n    _splitted = False\n\n\nclass LearnSwiftAdapter(LearnXYAdapter):\n    \"Learn Swift in Y Minutes\"\n\n    prefix = \"swift\"\n    _filename = \"swift.html.markdown\"\n    _splitted = False\n\n\nclass LearnTclAdapter(LearnXYAdapter):\n    \"Learn Tcl in Y Minutes\"\n\n    prefix = \"tcl\"\n    _filename = \"tcl.html.markdown\"\n    _splitted = False\n\n\nclass LearnTcshAdapter(LearnXYAdapter):\n    \"Learn Tcsh in Y Minutes\"\n\n    prefix = \"tcsh\"\n    _filename = \"tcsh.html.markdown\"\n    _splitted = False\n\n\nclass LearnVisualBasicAdapter(LearnXYAdapter):\n    \"Learn Visual Basic in Y Minutes\"\n\n    prefix = \"vb\"\n    _filename = \"visualbasic.html.markdown\"\n    _splitted = False\n\n\nclass LearnCMakeAdapter(LearnXYAdapter):\n    \"Learn CMake in Y Minutes\"\n\n    prefix = \"cmake\"\n    _filename = \"cmake.html.markdown\"\n    _splitted = False\n\n\nclass LearnNimAdapter(LearnXYAdapter):\n    \"Learn Nim in Y Minutes\"\n\n    prefix = \"nim\"\n    _filename = \"nim.html.markdown\"\n    _splitted = False\n\n\nclass LearnGitAdapter(LearnXYAdapter):\n    \"Learn Git in Y Minutes\"\n\n    prefix = \"git\"\n    _filename = \"git.html.markdown\"\n    _splitted = False\n\n\nclass LearnLatexAdapter(LearnXYAdapter):\n    \"Learn Nim in Y Minutes\"\n\n    prefix = \"latex\"\n    _filename = \"latex.html.markdown\"\n    _splitted = False\n\n\n_ADAPTERS = {cls.prefix: cls() for cls in vars()[\"LearnXYAdapter\"].__subclasses__()}\n"
  },
  {
    "path": "lib/adapter/question.py",
    "content": "\"\"\"\nConfiguration parameters:\n\n    path.internal.bin.upstream\n\"\"\"\n\n# pylint: disable=relative-import\n\nfrom __future__ import print_function\n\nimport os\nimport re\nfrom subprocess import Popen, PIPE\n\nfrom polyglot.detect import Detector\nfrom polyglot.detect.base import UnknownLanguage\n\nfrom config import CONFIG\nfrom languages_data import SO_NAME\nfrom .upstream import UpstreamAdapter\n\nNOT_FOUND_MESSAGE = \"\"\"404 NOT FOUND\n\nUnknown cheat sheet. Please try to reformulate your query.\nQuery format:\n\n    /LANG/QUESTION\n\nExamples:\n\n    /python/read+json\n    /golang/run+external+program\n    /js/regex+search\n\nSee /:help for more info.\n\nIf the problem persists, file a GitHub issue at\ngithub.com/chubin/cheat.sh or ping @igor_chubin\n\"\"\"\n\n\nclass Question(UpstreamAdapter):\n    \"\"\"\n    Answer to a programming language question, using Stackoverflow\n    as the main data source. Heavy lifting is done by an external\n    program `CONFIG[\"path.internal.bin.upstream\"]`.\n\n    If the program is not found, fallback to the superclass `UpstreamAdapter`,\n    which queries the upstream server (by default https://cheat.sh/)\n    for the answer\n    \"\"\"\n\n    _adapter_name = \"question\"\n    _output_format = \"text+code\"\n    _cache_needed = True\n\n    def _get_page(self, topic, request_options=None):\n        \"\"\"\n        Find answer for the `topic` question.\n        \"\"\"\n\n        if not os.path.exists(CONFIG[\"path.internal.bin.upstream\"]):\n            # if the upstream program is not found, use normal upstream adapter\n            self._output_format = \"ansi\"\n            return UpstreamAdapter._get_page(\n                self, topic, request_options=request_options\n            )\n\n        topic = topic.replace(\"+\", \" \")\n\n        # if there is a language name in the section name,\n        # cut it off (de:python => python)\n        if \"/\" in topic:\n            section_name, topic = topic.split(\"/\", 1)\n            if \":\" in section_name:\n                _, section_name = section_name.split(\":\", 1)\n            section_name = SO_NAME.get(section_name, section_name)\n            topic = \"%s/%s\" % (section_name, topic)\n\n        # some clients send queries with - instead of + so we have to rewrite them to\n        topic = re.sub(r\"(?<!-)-\", \" \", topic)\n\n        topic_words = topic.split()\n\n        topic = \" \".join(topic_words)\n\n        lang = \"en\"\n        try:\n            query_text = topic  # \" \".join(topic)\n            query_text = re.sub(\"^[^/]*/+\", \"\", query_text.rstrip(\"/\"))\n            query_text = re.sub(\"/[0-9]+$\", \"\", query_text)\n            query_text = re.sub(\"/[0-9]+$\", \"\", query_text)\n            detector = Detector(query_text)\n            supposed_lang = detector.languages[0].code\n            if len(topic_words) > 2 or supposed_lang in [\n                \"az\",\n                \"ru\",\n                \"uk\",\n                \"de\",\n                \"fr\",\n                \"es\",\n                \"it\",\n                \"nl\",\n            ]:\n                lang = supposed_lang\n            if supposed_lang.startswith(\"zh_\") or supposed_lang == \"zh\":\n                lang = \"zh\"\n            elif supposed_lang.startswith(\"pt_\"):\n                lang = \"pt\"\n            if supposed_lang in [\"ja\", \"ko\"]:\n                lang = supposed_lang\n\n        except UnknownLanguage:\n            print(\"Unknown language (%s)\" % query_text)\n\n        if lang != \"en\":\n            topic = [\"--human-language\", lang, topic]\n        else:\n            topic = [topic]\n\n        cmd = [CONFIG[\"path.internal.bin.upstream\"]] + topic\n        proc = Popen(cmd, stdin=open(os.devnull, \"r\"), stdout=PIPE, stderr=PIPE)\n        answer = proc.communicate()[0].decode(\"utf-8\")\n\n        if not answer:\n            return NOT_FOUND_MESSAGE\n\n        return answer\n\n    def get_list(self, prefix=None):\n        return []\n\n    def is_found(self, topic):\n        return True\n"
  },
  {
    "path": "lib/adapter/rosetta.py",
    "content": "\"\"\"\nImplementation of RosettaCode Adapter.\n\nExports:\n\n    Rosetta(GitRepositoryAdapter)\n\"\"\"\n\n# pylint: disable=relative-import\n\nimport os\nimport glob\nimport yaml\n\nfrom .git_adapter import GitRepositoryAdapter\nfrom .cheat_sheets import CheatSheets\n\n\nclass Rosetta(GitRepositoryAdapter):\n    \"\"\"\n    Adapter for RosettaCode\n    \"\"\"\n\n    _adapter_name = \"rosetta\"\n    _output_format = \"code\"\n    _local_repository_location = \"RosettaCodeData\"\n    _repository_url = \"https://github.com/acmeism/RosettaCodeData\"\n\n    __section_name = \"rosetta\"\n\n    def __init__(self):\n        GitRepositoryAdapter.__init__(self)\n        self._rosetta_code_name = self._load_rosetta_code_names()\n\n    @staticmethod\n    def _load_rosetta_code_names():\n        answer = {}\n\n        lang_files_location = CheatSheets.local_repository_location(\n            cheat_sheets_location=True\n        )\n        for filename in glob.glob(os.path.join(lang_files_location, \"*/_info.yaml\")):\n            text = open(filename, \"r\").read()\n            data = yaml.load(text, Loader=yaml.SafeLoader)\n            if data is None:\n                continue\n            lang = os.path.basename(os.path.dirname(filename))\n            if lang.startswith(\"_\"):\n                lang = lang[1:]\n            if \"rosetta\" in data:\n                answer[lang] = data[\"rosetta\"]\n        return answer\n\n    def _rosetta_get_list(self, query, task=None):\n        if query not in self._rosetta_code_name:\n            return []\n\n        lang = self._rosetta_code_name[query]\n        answer = []\n        if task:\n            glob_path = os.path.join(\n                self.local_repository_location(), \"Lang\", lang, task, \"*\"\n            )\n        else:\n            glob_path = os.path.join(\n                self.local_repository_location(), \"Lang\", lang, \"*\"\n            )\n        for filename in glob.glob(glob_path):\n            taskname = os.path.basename(filename)\n            answer.append(taskname)\n\n        answer = \"\".join(\"%s\\n\" % x for x in sorted(answer))\n        return answer\n\n    @staticmethod\n    def _parse_query(query):\n        if \"/\" in query:\n            task, subquery = query.split(\"/\", 1)\n        else:\n            task, subquery = query, None\n        return task, subquery\n\n    def _get_task(self, lang, query):\n        if lang not in self._rosetta_code_name:\n            return \"\"\n\n        task, subquery = self._parse_query(query)\n\n        if task == \":list\":\n            return self._rosetta_get_list(lang)\n        if subquery == \":list\":\n            return self._rosetta_get_list(lang, task=task)\n\n        # if it is not a number or the number is too big, just ignore it\n        index = 1\n        if subquery:\n            try:\n                index = int(subquery)\n            except ValueError:\n                pass\n\n        lang_name = self._rosetta_code_name[lang]\n\n        tasks = sorted(\n            glob.glob(\n                os.path.join(\n                    self.local_repository_location(), \"Lang\", lang_name, task, \"*\"\n                )\n            )\n        )\n        if not tasks:\n            return \"\"\n\n        if len(tasks) < index or index < 1:\n            index = 1\n\n        answer_filename = tasks[index - 1]\n        answer = open(answer_filename, \"r\").read()\n\n        return answer\n\n    def _starting_page(self, query):\n        number_of_pages = self._rosetta_get_list(query)\n        answer = (\"# %s pages available\\n\" \"# use /:list to list\") % number_of_pages\n        return answer\n\n    def _get_page(self, topic, request_options=None):\n\n        if \"/\" not in topic:\n            return self._rosetta_get_list(topic)\n\n        lang, topic = topic.split(\"/\", 1)\n\n        # this part should be generalized\n        # currently we just remove the name of the adapter from the path\n        if topic == self.__section_name:\n            return self._starting_page(topic)\n\n        if topic.startswith(self.__section_name + \"/\"):\n            topic = topic[len(self.__section_name + \"/\") :]\n\n        return self._get_task(lang, topic)\n\n    def _get_list(self, prefix=None):\n        return []\n\n    def get_list(self, prefix=None):\n        answer = [self.__section_name]\n        for i in self._rosetta_code_name:\n            answer.append(\"%s/%s/\" % (i, self.__section_name))\n        return answer\n\n    def is_found(self, _):\n        return True\n"
  },
  {
    "path": "lib/adapter/tldr.py",
    "content": "\"\"\"\nAdapter for https://github.com/cheat/cheat\n\nCheatsheets are located in `pages/*/`\nEach cheat sheet is a separate file with extension .md\n\nThe pages are formatted with a markdown dialect\n\"\"\"\n\n# pylint: disable=relative-import,abstract-method\n\nimport re\nimport os\n\nfrom .git_adapter import GitRepositoryAdapter\n\n\nclass Tldr(GitRepositoryAdapter):\n    \"\"\"\n    tldr-pages/tldr adapter\n    \"\"\"\n\n    _adapter_name = \"tldr\"\n    _output_format = \"code\"\n    _cache_needed = True\n    _repository_url = \"https://github.com/tldr-pages/tldr\"\n    _cheatsheet_files_prefix = \"pages/*/\"\n    _cheatsheet_files_extension = \".md\"\n\n    @staticmethod\n    def _format_page(text):\n        \"\"\"\n        Trivial tldr Markdown implementation.\n\n        * Header goes until the first empty line after > prefixed lines.\n        * code surrounded with `` => code\n        * {{var}} => var\n        \"\"\"\n\n        answer = []\n        skip_empty = False\n        header = 2\n        for line in text.splitlines():\n            if line.strip() == \"\":\n                if skip_empty and not header:\n                    continue\n                if header == 1:\n                    header = 0\n                if header:\n                    continue\n            else:\n                skip_empty = False\n\n            if line.startswith(\"-\"):\n                line = \"# \" + line[2:]\n                skip_empty = True\n            elif line.startswith(\"> \"):\n                if header == 2:\n                    header = 1\n                line = \"# \" + line[2:]\n                skip_empty = True\n            elif line.startswith(\"`\") and line.endswith(\"`\"):\n                line = line[1:-1]\n                line = re.sub(r\"{{(.*?)}}\", r\"\\1\", line)\n\n            answer.append(line)\n\n        return \"\\n\".join(answer)\n\n    def _get_page(self, topic, request_options=None):\n        \"\"\"\n        Go through pages/{common,linux,osx,sunos,windows}/\n        and as soon as anything is found, format and return it.\n        \"\"\"\n\n        search_order = [\"common\", \"linux\", \"osx\", \"sunos\", \"windows\", \"android\"]\n        local_rep = self.local_repository_location()\n        ext = self._cheatsheet_files_extension\n\n        filename = None\n        for subdir in search_order:\n            _filename = os.path.join(local_rep, \"pages\", subdir, \"%s%s\" % (topic, ext))\n            if os.path.exists(_filename):\n                filename = _filename\n                break\n\n        if filename:\n            answer = self._format_page(open(filename, \"r\").read())\n        else:\n            # though it should not happen\n            answer = \"\"\n\n        return answer\n\n    @classmethod\n    def get_updates_list(cls, updated_files_list):\n        \"\"\"\n        If a .md file was updated, invalidate cache\n        entry with the name of this file\n        \"\"\"\n        answer = []\n        ext = cls._cheatsheet_files_extension\n\n        for entry in updated_files_list:\n            if entry.endswith(ext):\n                answer.append(entry.split(\"/\")[-1][: -len(ext)])\n        return answer\n"
  },
  {
    "path": "lib/adapter/upstream.py",
    "content": "\"\"\"\nAdapter for an external cheat sheets service (i.e. for cheat.sh)\n\nConfiguration parameters:\n\n    upstream.url\n    upstream.timeout\n\"\"\"\n\n# pylint: disable=relative-import\n\nimport textwrap\nimport requests\n\nfrom config import CONFIG\nfrom .adapter import Adapter\n\n\ndef _are_you_offline():\n    return textwrap.dedent(\n        \"\"\"\n         .\n                         Are you offline?\n            _________________\n           | | ___________ |o|   Though it could be theoretically possible\n           | | ___________ | |   to use cheat.sh fully offline,\n           | | ___________ | |   and for *the programming languages questions* too,\n           | | ___________ | |   this very feature is not yet implemented.\n           | |_____________| |\n           |     _______     |   If you find it useful, please visit\n           |    |       |   ||   https://github.com/chubin/issues/140\n           | DD |       |   V|   and drop a couple of lines to encourage\n           |____|_______|____|   the authors to develop it as soon as possible\n\n         .\n            \"\"\"\n    )\n\n\nclass UpstreamAdapter(Adapter):\n    \"\"\"\n    Connect to the upstream server `CONFIG[\"upstream.url\"]` and fetch\n    response from it. The response is supposed to have the \"ansi\" format.\n    If the server does not respond within `CONFIG[\"upstream.timeout\"]` seconds,\n    or if a connection error occurs, the \"are you offline\" banner is displayed.\n\n    Answers are by default cached; the failure answer is marked with the no-cache\n    property (\"cache\": False).\n    \"\"\"\n\n    _adapter_name = \"upstream\"\n    _output_format = \"ansi\"\n    _cache_needed = False\n\n    def _get_page(self, topic, request_options=None):\n\n        options_string = \"&\".join(\n            [\"%s=%s\" % (x, y) for (x, y) in request_options.items()]\n        )\n        url = (\n            CONFIG[\"upstream.url\"].rstrip(\"/\")\n            + \"/\"\n            + topic.lstrip(\"/\")\n            + \"?\"\n            + options_string\n        )\n        try:\n            response = requests.get(url, timeout=CONFIG[\"upstream.timeout\"])\n            answer = {\"cache\": False, \"answer\": response.text}\n        except requests.exceptions.ConnectionError:\n            answer = {\"cache\": False, \"answer\": _are_you_offline()}\n        return answer\n\n    def _get_list(self, prefix=None):\n        return []\n"
  },
  {
    "path": "lib/buttons.py",
    "content": "TWITTER_BUTTON = \"\"\"\n<a href=\"https://twitter.com/igor_chubin\" class=\"twitter-follow-button\" data-show-count=\"false\" data-button=\"grey\">Follow @igor_chubin</a>\n<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>\n\"\"\"\n\nGITHUB_BUTTON = \"\"\"\n<!-- Place this tag where you want the button to render. -->\n<a aria-label=\"Star chubin/wttr.in on GitHub\" data-count-aria-label=\"# stargazers on GitHub\" data-count-api=\"/repos/chubin/cheat.sh#stargazers_count\" data-count-href=\"/chubin/cheat.sh/stargazers\" data-icon=\"octicon-star\" href=\"https://github.com/chubin/cheat.sh\" class=\"github-button\">cheat.sh</a>\n\"\"\"\n\nGITHUB_BUTTON_2 = \"\"\"\n<!-- Place this tag where you want the button to render. -->\n<a aria-label=\"Star chubin/cheat.sheets on GitHub\" data-count-aria-label=\"# stargazers on GitHub\" data-count-api=\"/repos/chubin/cheat.sheets#stargazers_count\" data-count-href=\"/chubin/cheat.sheets/stargazers\" data-icon=\"octicon-star\" href=\"https://github.com/chubin/cheat.sheets\" class=\"github-button\">cheat.sheets</a>\n\"\"\"\n\nGITHUB_BUTTON_FOOTER = \"\"\"\n<!-- Place this tag right after the last button or just before your close body tag. -->\n<script async defer id=\"github-bjs\" src=\"https://buttons.github.io/buttons.js\"></script>\n\"\"\"\n"
  },
  {
    "path": "lib/cache.py",
    "content": "\"\"\"\nCache implementation.\nCurrently only two types of cache are allowed:\n    * \"none\"    cache switched off\n    * \"redis\"   use redis for cache\n\nConfiguration parameters:\n\n    cache.type = redis | none\n    cache.redis.db\n    cache.redis.host\n    cache.redis.port\n\"\"\"\n\nimport os\nimport json\nfrom config import CONFIG\n\n_REDIS = None\nif CONFIG[\"cache.type\"] == \"redis\":\n    import redis\n\n    _REDIS = redis.Redis(\n        host=CONFIG[\"cache.redis.host\"],\n        port=CONFIG[\"cache.redis.port\"],\n        db=CONFIG[\"cache.redis.db\"],\n    )\n\n_REDIS_PREFIX = \"\"\nif CONFIG.get(\"cache.redis.prefix\", \"\"):\n    _REDIS_PREFIX = CONFIG[\"cache.redis.prefix\"] + \":\"\n\n\ndef put(key, value):\n    \"\"\"\n    Save `value` with `key`, and serialize it if needed\n    \"\"\"\n\n    if _REDIS_PREFIX:\n        key = _REDIS_PREFIX + key\n\n    if CONFIG[\"cache.type\"] == \"redis\" and _REDIS:\n        if isinstance(value, (dict, list)):\n            value = json.dumps(value)\n\n        _REDIS.set(key, value)\n\n\ndef get(key):\n    \"\"\"\n    Read `value` by `key`, and deserialize it if needed\n    \"\"\"\n\n    if _REDIS_PREFIX:\n        key = _REDIS_PREFIX + key\n\n    if CONFIG[\"cache.type\"] == \"redis\" and _REDIS:\n        value = _REDIS.get(key)\n        try:\n            value = json.loads(value)\n        except (ValueError, TypeError):\n            pass\n        return value\n    return None\n\n\ndef delete(key):\n    \"\"\"\n    Remove `key` from the database\n    \"\"\"\n\n    if _REDIS:\n        if _REDIS_PREFIX:\n            key = _REDIS_PREFIX + key\n\n        _REDIS.delete(key)\n\n    return None\n"
  },
  {
    "path": "lib/cheat_wrapper.py",
    "content": "\"\"\"\nMain cheat.sh wrapper.\nParse the query, get answers from getters (using get_answer),\nvisualize it using frontends and return the result.\n\nExports:\n\n    cheat_wrapper()\n\"\"\"\n\nimport re\nimport json\n\nfrom routing import get_answers, get_topics_list\nfrom search import find_answers_by_keyword\nfrom languages_data import LANGUAGE_ALIAS, rewrite_editor_section_name\nimport postprocessing\n\nimport frontend.html\nimport frontend.ansi\n\n\ndef _add_section_name(query):\n    # temporary solution before we don't find a fixed one\n    if \" \" not in query and \"+\" not in query:\n        return query\n    if \"/\" in query:\n        return query\n    if \" \" in query:\n        return re.sub(r\" +\", \"/\", query, count=1)\n    if \"+\" in query:\n        # replace only single + to avoid catching g++ and friends\n        return re.sub(r\"([^\\+])\\+([^\\+])\", r\"\\1/\\2\", query, count=1)\n\n\ndef cheat_wrapper(query, request_options=None, output_format=\"ansi\"):\n    \"\"\"\n    Function that delivers cheat sheet for `query`.\n    If `html` is True, the answer is formatted as HTML.\n    Additional request options specified in `request_options`.\n    \"\"\"\n\n    def _rewrite_aliases(word):\n        if word == \":bash.completion\":\n            return \":bash_completion\"\n        return word\n\n    def _rewrite_section_name(query):\n        \"\"\"\n        Rewriting special section names:\n        * EDITOR:NAME => emacs:go-mode\n        \"\"\"\n\n        if \"/\" not in query:\n            return query\n\n        section_name, rest = query.split(\"/\", 1)\n\n        if \":\" in section_name:\n            section_name = rewrite_editor_section_name(section_name)\n        section_name = LANGUAGE_ALIAS.get(section_name, section_name)\n\n        return \"%s/%s\" % (section_name, rest)\n\n    def _sanitize_query(query):\n        return re.sub('[<>\"]', \"\", query)\n\n    def _strip_hyperlink(query):\n        return re.sub(\"(,[0-9]+)+$\", \"\", query)\n\n    def _parse_query(query):\n        topic = query\n        keyword = None\n        search_options = \"\"\n\n        keyword = None\n        if \"~\" in query:\n            topic = query\n            pos = topic.index(\"~\")\n            keyword = topic[pos + 1 :]\n            topic = topic[:pos]\n\n            if \"/\" in keyword:\n                search_options = keyword[::-1]\n                search_options = search_options[: search_options.index(\"/\")]\n                keyword = keyword[: -len(search_options) - 1]\n\n        return topic, keyword, search_options\n\n    query = _sanitize_query(query)\n    query = _add_section_name(query)\n    query = _rewrite_aliases(query)\n    query = _rewrite_section_name(query)\n\n    # at the moment, we just remove trailing slashes\n    # so queries python/ and python are equal\n    # query = _strip_hyperlink(query.rstrip('/'))\n    topic, keyword, search_options = _parse_query(query)\n\n    if keyword:\n        answers = find_answers_by_keyword(\n            topic, keyword, options=search_options, request_options=request_options\n        )\n    else:\n        answers = get_answers(topic, request_options=request_options)\n\n    answers = [\n        postprocessing.postprocess(\n            answer, keyword, search_options, request_options=request_options\n        )\n        for answer in answers\n    ]\n\n    answer_data = {\n        \"query\": query,\n        \"keyword\": keyword,\n        \"answers\": answers,\n    }\n\n    if output_format == \"html\":\n        answer_data[\"topics_list\"] = get_topics_list()\n        return frontend.html.visualize(answer_data, request_options)\n    elif output_format == \"json\":\n        return json.dumps(answer_data, indent=4)\n    return frontend.ansi.visualize(answer_data, request_options)\n"
  },
  {
    "path": "lib/cheat_wrapper_test.py",
    "content": "from cheat_wrapper import _add_section_name\n\nunchanged = \"\"\"\npython/:list\nls\n+\ng++\ng/+\nclang++\nbtrfs~volume\n:intro\n:cht.sh\npython/copy+file\npython/rosetta/:list\nemacs:go-mode/:list\ng++g++\n\"\"\"\n\nsplit = \"\"\"\npython copy file\npython/copy file\n\npython  file\npython/file\n\npython+file\npython/file\n\ng++ -O1\ng++/-O1\n\"\"\"\n\n\ndef test_header_split():\n    for inp in unchanged.strip().splitlines():\n        assert inp == _add_section_name(inp)\n\n    for test in split.strip().split(\"\\n\\n\"):\n        inp, outp = test.split(\"\\n\")\n        assert outp == _add_section_name(inp)\n"
  },
  {
    "path": "lib/config.py",
    "content": "\"\"\"\nGlobal configuration of the project.\n\nAll configurable parameters are stored in the global variable CONFIG,\nthe only variable which is exported from the module.\n\nDefault values of all configuration parameters are specified\nin the `_CONFIG` dictionary. Those parameters can be overridden\nby three means:\n    * config file `etc/config.yaml` located in the work dir\n    * config file `etc/config.yaml` located in the project dir\n      (if the work dir and the project dir are not the same)\n    * environment variables prefixed with `CHEATSH_`\n\nConfiguration placement priorities, from high to low:\n    * environment variables;\n    * configuration file in the workdir\n    * configuration file in the project dir\n    * default values specified in the `_CONFIG` dictionary\n\nIf the work dir and the project dir are not the same, we do not\nrecommend that you use the config file located in the project dir,\nexcept the cases when you use your own cheat.sh fork, and thus\nconfiguration is a part of the project repository.\nIn all other cases `WORKDIR/etc/config.yaml` should be preferred.\nLocation of this config file can be overridden by the `CHEATSH_PATH_CONFIG`\nenvironment variable.\n\nConfiguration parameters set by environment variables are mapped\nin this way:\n    * CHEATSH_ prefix is trimmed\n    * _ replaced with .\n    * the string is lowercased\n\nFor instance, an environment variable named `CHEATSH_SERVER_PORT`\nspecifies the value for the `server.port` configuration parameter.\n\nOnly parameters that imply scalar values (integer or string)\ncan be set using environment variables, for the rest config files\nshould be used. If a parameter implies an integer, and the value\nspecified by an environment variable is not an integer, it is ignored.\n\"\"\"\n\nfrom __future__ import print_function\nimport os\n\nfrom pygments.styles import get_all_styles\n\n# def get_all_styles():\n#    return []\n\n_ENV_VAR_PREFIX = \"CHEATSH\"\n\n_MYDIR = os.path.abspath(os.path.join(__file__, \"..\", \"..\"))\n\n\ndef _config_locations():\n    \"\"\"\n    Return three possible config locations\n    where configuration can be found:\n    * `_WORKDIR`, `_CONF_FILE_WORKDIR`, `_CONF_FILE_MYDIR`\n    \"\"\"\n\n    var = _ENV_VAR_PREFIX + \"_PATH_WORKDIR\"\n    workdir = (\n        os.environ[var]\n        if var in os.environ\n        else os.path.join(os.environ[\"HOME\"], \".cheat.sh\")\n    )\n\n    var = _ENV_VAR_PREFIX + \"_CONFIG\"\n    conf_file_workdir = (\n        os.environ[var]\n        if var in os.environ\n        else os.path.join(workdir, \"etc/config.yaml\")\n    )\n\n    conf_file_mydir = os.path.join(_MYDIR, \"etc/config.yaml\")\n    return workdir, conf_file_workdir, conf_file_mydir\n\n\n_WORKDIR, _CONF_FILE_WORKDIR, _CONF_FILE_MYDIR = _config_locations()\n\n_CONFIG = {\n    \"adapters.active\": [\n        \"tldr\",\n        \"cheat\",\n        \"fosdem\",\n        \"translation\",\n        \"rosetta\",\n        \"late.nz\",\n        \"question\",\n        \"cheat.sheets\",\n        \"cheat.sheets dir\",\n        \"learnxiny\",\n        \"rfc\",\n        \"oeis\",\n        \"chmod\",\n    ],\n    \"adapters.mandatory\": [\n        \"search\",\n    ],\n    \"cache.redis.db\": 0,\n    \"cache.redis.host\": \"localhost\",\n    \"cache.redis.port\": 6379,\n    \"cache.redis.prefix\": \"\",\n    \"cache.type\": \"redis\",\n    \"frontend.styles\": sorted(list(get_all_styles())),\n    \"log.level\": 4,\n    \"path.internal.ansi2html\": os.path.join(_MYDIR, \"share/ansi2html.sh\"),\n    \"path.internal.bin\": os.path.join(_MYDIR, \"bin\"),\n    \"path.internal.bin.upstream\": os.path.join(_MYDIR, \"bin\", \"upstream\"),\n    \"path.internal.malformed\": os.path.join(\n        _MYDIR, \"share/static/malformed-response.html\"\n    ),\n    \"path.internal.pages\": os.path.join(_MYDIR, \"share\"),\n    \"path.internal.static\": os.path.join(_MYDIR, \"share/static\"),\n    \"path.internal.templates\": os.path.join(_MYDIR, \"share/templates\"),\n    \"path.internal.vim\": os.path.join(_MYDIR, \"share/vim\"),\n    \"path.log.main\": \"log/main.log\",\n    \"path.log.queries\": \"log/queries.log\",\n    \"path.log.fetch\": \"log/fetch.log\",\n    \"path.repositories\": \"upstream\",\n    \"path.spool\": \"spool\",\n    \"path.workdir\": _WORKDIR,\n    \"routing.pre\": [\n        (\"^$\", \"search\"),\n        (\"^[^/]*/rosetta(/|$)\", \"rosetta\"),\n        (\"^rfc/\", \"rfc\"),\n        (\"^oeis/\", \"oeis\"),\n        (\"^chmod/\", \"chmod\"),\n        (\"^:\", \"internal\"),\n        (\"/:list$\", \"internal\"),\n        (\"/$\", \"cheat.sheets dir\"),\n    ],\n    \"routing.main\": [\n        (\"\", \"cheat.sheets\"),\n        (\"\", \"cheat\"),\n        (\"\", \"tldr\"),\n        (\"\", \"late.nz\"),\n        (\"\", \"fosdem\"),\n        (\"\", \"learnxiny\"),\n    ],\n    \"routing.post\": [\n        (\"^[^/ +]*$\", \"unknown\"),\n        (\"^[a-z][a-z]-[a-z][a-z]$\", \"translation\"),\n    ],\n    \"routing.default\": \"question\",\n    \"upstream.url\": \"https://cheat.sh\",\n    \"upstream.timeout\": 5,\n    \"search.limit\": 20,\n    \"server.bind\": \"0.0.0.0\",\n    \"server.port\": 8002,\n}\n\n\nclass Config(dict):\n    \"\"\"\n    configuration dictionary that handles relative\n    paths properly (making them relative to path.workdir)\n    \"\"\"\n\n    def _absolute_path(self, val):\n        if val.startswith(\"/\"):\n            return val\n        return os.path.join(self[\"path.workdir\"], val)\n\n    def __init__(self, *args, **kwargs):\n        dict.__init__(self)\n        self.update(*args, **kwargs)\n\n    def __setitem__(self, key, val):\n        if key.startswith(\"path.\") and not val.startswith(\"/\"):\n            val = self._absolute_path(val)\n        dict.__setitem__(self, key, val)\n\n    def update(self, *args, **kwargs):\n        \"\"\"\n        the built-in __init__ doesn't call update,\n        and the built-in update doesn't call __setitem__,\n        so `update` should be overridden\n        \"\"\"\n\n        newdict = dict(*args, **kwargs)\n        if \"path.workdir\" in newdict:\n            self[\"path.workdir\"] = newdict[\"path.workdir\"]\n\n        for key, val in newdict.items():\n            self[key] = val\n\n\ndef _load_config_from_environ(config):\n\n    update = {}\n    for key, val in config.items():\n        if not isinstance(val, str) or isinstance(val, int):\n            continue\n\n        env_var = _ENV_VAR_PREFIX + \"_\" + key.replace(\".\", \"_\").upper()\n        if not env_var in os.environ:\n            continue\n\n        env_val = os.environ[env_var]\n        if isinstance(val, int):\n            try:\n                env_val = int(env_val)\n            except (ValueError, TypeError):\n                continue\n\n        update[key] = env_val\n\n    return update\n\n\ndef _get_nested(data, key):\n    \"\"\"\n    Return value for a hierrachical key (like a.b.c).\n    Return None if nothing found.\n    If there is a key with . in the name, and a subdictionary,\n    the former is preferred:\n\n    >>> print(_get_nested({'a.b': 10, 'a':{'b': 20}}, 'a.b'))\n    10\n    >>> print(_get_nested({'a': {'b': 20}}, 'a.b'))\n    20\n    >>> print(_get_nested({'a': {'b': {'c': 30}}}, 'a.b.c'))\n    30\n    \"\"\"\n\n    if not data or not isinstance(data, dict):\n        return None\n    if \".\" not in key:\n        return data.get(key)\n    if key in data:\n        return data[key]\n\n    parts = key.split(\".\")\n    for i in range(len(parts))[::-1]:\n        prefix = \".\".join(parts[:i])\n        if prefix in data:\n            return _get_nested(data[prefix], \".\".join(parts[i:]))\n\n    return None\n\n\ndef _load_config_from_file(default_config, filename):\n    import yaml\n\n    update = {}\n    if not os.path.exists(filename):\n        return update\n\n    with open(filename) as f:\n        newconfig = yaml.load(f.read(), Loader=yaml.SafeLoader)\n    for key, val in default_config.items():\n        newval = _get_nested(newconfig, key)\n        if newval is None:\n            continue\n\n        if isinstance(val, int):\n            try:\n                newval = int(newval)\n            except (ValueError, TypeError):\n                continue\n\n        update[key] = newval\n\n    return update\n\n\nCONFIG = Config()\nCONFIG.update(_CONFIG)\nCONFIG.update(_load_config_from_file(_CONFIG, _CONF_FILE_MYDIR))\nif _CONF_FILE_WORKDIR != _CONF_FILE_MYDIR:\n    CONFIG.update(_load_config_from_file(_CONFIG, _CONF_FILE_WORKDIR))\nCONFIG.update(_load_config_from_environ(_CONFIG))\n\nif __name__ == \"__main__\":\n    import doctest\n\n    doctest.testmod()\n"
  },
  {
    "path": "lib/fetch.py",
    "content": "\"\"\"\nRepositories fetch and update\n\nThis module makes real network and OS interaction,\nand the adapters only say how exctly this interaction\nshould be done.\n\nConfiguration parameters:\n\n    * path.log.fetch\n\"\"\"\n\nfrom __future__ import print_function\n\nimport sys\nimport logging\nimport os\nimport subprocess\nimport textwrap\n\nfrom globals import fatal\nimport adapter\nimport cache\n\nfrom config import CONFIG\n\n\ndef _log(*message):\n    logging.info(*message)\n    if len(message) > 1:\n        message = message[0].rstrip(\"\\n\") % tuple(message[1:])\n    else:\n        message = message[0].rstrip(\"\\n\")\n\n    sys.stdout.write(message + \"\\n\")\n\n\ndef _run_cmd(cmd):\n    shell = isinstance(cmd, str)\n    process = subprocess.Popen(\n        cmd, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.STDOUT\n    )\n    output = process.communicate()[0]\n    return process.returncode, output\n\n\ndef fetch_all(skip_existing=True):\n    \"\"\"\n    Fetch all known repositories mentioned in the adapters\n    \"\"\"\n\n    def _fetch_locations(known_location):\n        for location, adptr in known_location.items():\n            if location in existing_locations:\n                continue\n\n            cmd = adptr.fetch_command()\n            if not cmd:\n                continue\n\n            sys.stdout.write(\"Fetching %s...\" % (adptr))\n            sys.stdout.flush()\n            try:\n                process = subprocess.Popen(\n                    cmd,\n                    stdout=subprocess.PIPE,\n                    stderr=subprocess.STDOUT,\n                    universal_newlines=True,\n                )\n            except OSError:\n                print(\"\\nERROR: %s\" % cmd)\n                raise\n            output = process.communicate()[0]\n            if process.returncode != 0:\n                sys.stdout.write(\"\\nERROR:\\n---\\n\" + output)\n                fatal(\"---\\nCould not fetch %s\" % adptr)\n            else:\n                print(\"Done\")\n\n    # Searching for location duplicates for different repositories\n    known_location = {}\n    for adptr in adapter.adapter.all_adapters():\n        location = adptr.local_repository_location()\n        if not location:\n            continue\n        if (\n            location in known_location\n            and adptr.repository_url() != known_location[location].repository_url()\n        ):\n            fatal(\n                \"Duplicate location: %s for %s and %s\"\n                % (location, adptr, known_location[location])\n            )\n        known_location[location] = adptr\n\n    # Parent directories creation\n    # target subdirectories will be create during the checkout process,\n    # but the parent directories should be created explicitly.\n    # Also we should make sure, that the target directory does not exist\n    existing_locations = []\n    for location in known_location:\n        if os.path.exists(location):\n            if skip_existing:\n                existing_locations.append(location)\n                print(\"Already exists %s\" % (location))\n            else:\n                fatal(\"%s already exists\" % location)\n\n        parent = os.path.dirname(location)\n        if os.path.exists(parent):\n            continue\n\n        os.makedirs(parent)\n\n    known_location = {\n        k: v for k, v in known_location.items() if k not in existing_locations\n    }\n    _fetch_locations(known_location)\n\n\ndef _update_adapter(adptr):\n    \"\"\"\n    Update implementation.\n\n    If `adptr` returns no update_command(), it is being ignored.\n    \"\"\"\n    os.chdir(adptr.local_repository_location())\n\n    cmd = adptr.update_command()\n    if not cmd:\n        return True\n\n    errorcode, output = _run_cmd(cmd)\n    if errorcode:\n        _log(\n            \"\\nERROR:\\n---%s\\n\" % output.decode(\"utf-8\")\n            + \"\\n---\\nCould not update %s\" % adptr\n        )\n        return False\n\n    # Getting current repository state\n    # This state will be saved after the update procedure is finished\n    # (all cache entries invalidated)\n    cmd = adptr.current_state_command()\n    state = None\n    if cmd:\n        errorcode, state = _run_cmd(cmd)\n        if errorcode:\n            _log(\n                \"\\nERROR:\\n---\\n\"\n                + state\n                + \"\\n---\\nCould not get repository state: %s\" % adptr\n            )\n            return False\n        state = state.strip()\n\n    # Getting list of files that were changed\n    # that will be later converted to the list of the pages to be invalidated\n    cmd = adptr.get_updates_list_command()\n    updates = []\n    if cmd:\n        errorcode, output = _run_cmd(cmd)\n        output = output.decode(\"utf-8\")\n        if errorcode:\n            _log(\n                \"\\nERROR:\\n---\\n\"\n                + output\n                + \"\\n---\\nCould not get list of pages to be updated: %s\" % adptr\n            )\n            return False\n        updates = output.splitlines()\n\n    entries = adptr.get_updates_list(updates)\n    if entries:\n        _log(\"%s Entries to be updated: %s\", adptr, len(entries))\n\n    name = adptr.name()\n    for entry in entries:\n        cache_name = name + \":\" + entry\n        _log(\"+ invalidating %s\", cache_name)\n        cache.delete(cache_name)\n\n    if entries:\n        _log(\"Done\")\n\n    adptr.save_state(state)\n    return True\n\n\ndef update_all():\n    \"\"\"\n    Update all known repositories, mentioned in the adapters\n    and fetched locally.\n    If repository is not fetched, it is skipped.\n    \"\"\"\n\n    for adptr in adapter.adapter.all_adapters():\n        location = adptr.local_repository_location()\n        if not location:\n            continue\n        if not os.path.exists(location):\n            continue\n\n        _update_adapter(adptr)\n\n\ndef update_by_name(name):\n    \"\"\"\n    Find adapter by its `name` and update only it.\n    \"\"\"\n    pass\n\n\ndef _show_usage():\n    sys.stdout.write(\n        textwrap.dedent(\n            \"\"\"\n        Usage:\n\n            python lib/fetch.py [command]\n        \n        Commands:\n        \n            update-all      -- update all configured repositories\n            update [name]   -- update repository of the adapter `name`\n            fetch-all       -- fetch all configured repositories\n\n    \"\"\"\n        )\n    )\n\n\ndef main(args):\n    \"\"\"\n    function for the initial repositories fetch and manual repositories updates\n    \"\"\"\n\n    if not args:\n        _show_usage()\n        sys.exit(0)\n\n    logdir = os.path.dirname(CONFIG[\"path.log.fetch\"])\n    if not os.path.exists(logdir):\n        os.makedirs(logdir)\n\n    logging.basicConfig(\n        filename=CONFIG[\"path.log.fetch\"],\n        level=logging.DEBUG,\n        format=\"%(asctime)s %(message)s\",\n    )\n\n    if args[0] == \"fetch-all\":\n        fetch_all()\n    elif args[0] == \"update\":\n        update_by_name(sys.argv[1])\n    elif args[0] == \"update-all\":\n        update_all()\n    else:\n        _show_usage()\n        sys.exit(0)\n\n\nif __name__ == \"__main__\":\n    main(sys.argv[1:])\n"
  },
  {
    "path": "lib/fmt/__init__.py",
    "content": ""
  },
  {
    "path": "lib/fmt/comments.py",
    "content": "\"\"\"\nExtract text from the text-code stream and comment it.\n\nSupports three modes of normalization and commenting:\n\n    1. Don't add any comments\n    2. Add comments\n    3. Remove text, leave code only\n\nSince several operations are quite expensive,\nit actively uses caching.\n\nExported functions:\n\n    beautify(text, lang, options)\n    code_blocks(text)\n\nConfiguration parameters:\n\"\"\"\n\nfrom __future__ import print_function\n\nimport sys\nimport os\nimport textwrap\nimport hashlib\nimport re\nfrom itertools import groupby, chain\nfrom subprocess import Popen\nfrom tempfile import NamedTemporaryFile\n\nfrom config import CONFIG\nfrom languages_data import VIM_NAME\nimport cache\n\nFNULL = open(os.devnull, \"w\")\nTEXT = 0\nCODE = 1\nUNDEFINED = -1\nCODE_WHITESPACE = -2\n\n\ndef _language_name(name):\n    return VIM_NAME.get(name, name)\n\n\ndef _remove_empty_lines_from_beginning(lines):\n    start = 0\n    while start < len(lines) and lines[start].strip() == \"\":\n        start += 1\n    lines = lines[start:]\n    return lines\n\n\ndef _remove_empty_lines_from_end(lines):\n    end = len(lines) - 1\n    while end >= 0 and lines[end].strip() == \"\":\n        end -= 1\n    lines = lines[: end + 1]\n    return lines\n\n\ndef _cleanup_lines(lines):\n    \"\"\"\n    Cleanup `lines` a little bit: remove empty lines at the beginning\n    and at the end; remove too many empty lines in between.\n    \"\"\"\n    lines = _remove_empty_lines_from_beginning(lines)\n    lines = _remove_empty_lines_from_end(lines)\n    if lines == []:\n        return lines\n    # remove repeating empty lines\n    lines = list(\n        chain.from_iterable(\n            [\n                (list(x[1]) if x[0] else [\"\"])\n                for x in groupby(lines, key=lambda x: x.strip() != \"\")\n            ]\n        )\n    )\n\n    return lines\n\n\ndef _line_type(line):\n    \"\"\"\n    Classify each line and say which of them\n    are text (0) and which of them are code (1).\n\n    A line is considered to be code,\n    if it starts with four spaces.\n\n    A line is considerer to be text if it is not\n    empty and is not code.\n\n    If line is empty, it is considered to be\n    code if it surrounded but two other code lines,\n    or if it is the first/last line and it has\n    code on the other side.\n    \"\"\"\n    if line.strip() == \"\":\n        return UNDEFINED\n\n    # some line may start with spaces but still be not code.\n    # we need some heuristics here, but for the moment just\n    # whitelist such cases:\n    if line.strip().startswith(\"* \") or re.match(r\"[0-9]+\\.\", line.strip()):\n        return TEXT\n\n    if line.startswith(\"   \"):\n        return CODE\n    return TEXT\n\n\ndef _classify_lines(lines):\n    line_types = [_line_type(line) for line in lines]\n\n    # pass 2:\n    # adding empty code lines to the code\n    for i in range(len(line_types) - 1):\n        if line_types[i] == CODE and line_types[i + 1] == UNDEFINED:\n            line_types[i + 1] = CODE_WHITESPACE\n            changed = True\n\n    for i in range(len(line_types) - 1)[::-1]:\n        if line_types[i] == UNDEFINED and line_types[i + 1] == CODE:\n            line_types[i] = CODE_WHITESPACE\n            changed = True\n    line_types = [CODE if x == CODE_WHITESPACE else x for x in line_types]\n\n    # pass 3:\n    # fixing undefined line types (-1)\n    changed = True\n    while changed:\n        changed = False\n\n        # changing all lines types that are near the text\n\n        for i in range(len(line_types) - 1):\n            if line_types[i] == TEXT and line_types[i + 1] == UNDEFINED:\n                line_types[i + 1] = TEXT\n                changed = True\n\n        for i in range(len(line_types) - 1)[::-1]:\n            if line_types[i] == UNDEFINED and line_types[i + 1] == TEXT:\n                line_types[i] = TEXT\n                changed = True\n\n    # everything what is still undefined, change to code type\n    line_types = [CODE if x == UNDEFINED else x for x in line_types]\n    return line_types\n\n\ndef _unindent_code(line, shift=0):\n    if shift == -1 and line != \"\":\n        return \" \" + line\n\n    if shift > 0 and line.startswith(\" \" * shift):\n        return line[shift:]\n\n    return line\n\n\ndef _wrap_lines(lines_classes, unindent_code=False):\n    \"\"\"\n    Wrap classified lines. Add the split lines to the stream.\n    If `unindent_code` is True, remove leading four spaces.\n    \"\"\"\n\n    result = []\n    for line_type, line_content in lines_classes:\n        if line_type == CODE:\n\n            shift = 3 if unindent_code else -1\n            result.append((line_type, _unindent_code(line_content, shift=shift)))\n        else:\n            if line_content.strip() == \"\":\n                result.append((line_type, \"\"))\n            for line in textwrap.fill(line_content).splitlines():\n                result.append((line_type, line))\n\n    return result\n\n\ndef _run_vim_script(script_lines, text_lines):\n    \"\"\"\n    Apply `script_lines` to `lines_classes`\n    and returns the result\n    \"\"\"\n\n    script_vim = NamedTemporaryFile(delete=True)\n    textfile = NamedTemporaryFile(delete=True)\n\n    open(script_vim.name, \"w\").write(\"\\n\".join(script_lines))\n    open(textfile.name, \"w\").write(\"\\n\".join(text_lines))\n\n    script_vim.file.close()\n    textfile.file.close()\n\n    my_env = os.environ.copy()\n    my_env[\"HOME\"] = CONFIG[\"path.internal.vim\"]\n\n    cmd = [\"script\", \"-q\", \"-c\", \"vim -S %s %s\" % (script_vim.name, textfile.name)]\n\n    Popen(\n        cmd,\n        shell=False,\n        stdin=open(os.devnull, \"r\"),\n        stdout=FNULL,\n        stderr=FNULL,\n        env=my_env,\n    ).communicate()\n\n    return open(textfile.name, \"r\").read()\n\n\ndef _commenting_script(lines_blocks, filetype):\n    script_lines = []\n    block_start = 1\n    for block in lines_blocks:\n        lines = list(block[1])\n\n        block_end = block_start + len(lines) - 1\n\n        if block[0] == 0:\n            comment_type = \"sexy\"\n            if block_end - block_start < 1 or filetype == \"ruby\":\n                comment_type = \"comment\"\n\n            script_lines.insert(\n                0,\n                \"%s,%s call NERDComment(1, '%s')\"\n                % (block_start, block_end, comment_type),\n            )\n            script_lines.insert(\n                0, \"%s,%s call NERDComment(1, 'uncomment')\" % (block_start, block_end)\n            )\n\n        block_start = block_end + 1\n\n    script_lines.insert(0, \"set ft=%s\" % _language_name(filetype))\n    script_lines.append(\"wq\")\n\n    return script_lines\n\n\ndef _beautify(text, filetype, add_comments=False, remove_text=False):\n    \"\"\"\n    Main function that actually does the whole beautification job.\n    \"\"\"\n\n    # We shift the code if and only if we either convert the text into comments\n    # or remove the text completely. Otherwise the code has to remain aligned\n    unindent_code = add_comments or remove_text\n\n    lines = [x.decode(\"utf-8\").rstrip(\"\\n\") for x in text.splitlines()]\n    lines = _cleanup_lines(lines)\n    lines_classes = zip(_classify_lines(lines), lines)\n    lines_classes = _wrap_lines(lines_classes, unindent_code=unindent_code)\n\n    if remove_text:\n        lines = [line[1] for line in lines_classes if line[0] == 1]\n        lines = _cleanup_lines(lines)\n        output = \"\\n\".join(lines)\n        if not output.endswith(\"\\n\"):\n            output += \"\\n\"\n    elif not add_comments:\n        output = \"\\n\".join(line[1] for line in lines_classes)\n    else:\n        lines_blocks = groupby(lines_classes, key=lambda x: x[0])\n        script_lines = _commenting_script(lines_blocks, filetype)\n        output = _run_vim_script(script_lines, [line for (_, line) in lines_classes])\n\n    return output\n\n\ndef code_blocks(text, wrap_lines=False, unindent_code=False):\n    \"\"\"\n    Split `text` into blocks of text and code.\n    Return list of tuples TYPE, TEXT\n    \"\"\"\n    text = text.encode(\"utf-8\")\n\n    lines = [x.rstrip(\"\\n\") for x in text.splitlines()]\n    lines_classes = zip(_classify_lines(lines), lines)\n\n    if wrap_lines:\n        lines_classes = _wrap_lines(lines_classes, unindent_code=unindent_code)\n\n    lines_blocks = groupby(lines_classes, key=lambda x: x[0])\n    answer = [(x[0], \"\\n\".join([y[1] for y in x[1]]) + \"\\n\") for x in lines_blocks]\n    return answer\n\n\ndef beautify(text, lang, options):\n    \"\"\"\n    Process input `text` according to the specified `mode`.\n    Adds comments if needed, according to the `lang` rules.\n    Caches the results.\n    The whole work (except caching) is done by _beautify().\n    \"\"\"\n\n    options = options or {}\n    beauty_options = dict(\n        (k, v) for k, v in options.items() if k in [\"add_comments\", \"remove_text\"]\n    )\n\n    mode = \"\"\n    if beauty_options.get(\"add_comments\"):\n        mode += \"c\"\n    if beauty_options.get(\"remove_text\"):\n        mode += \"q\"\n\n    if beauty_options == {}:\n        # if mode is unknown, just don't transform the text at all\n        return text\n\n    if isinstance(text, str):\n        text = text.encode(\"utf-8\")\n    digest = \"t:%s:%s:%s\" % (hashlib.md5(text).hexdigest(), lang, mode)\n\n    # temporary added line that removes invalid cache entries\n    # that used wrong commenting methods\n    if lang in [\"git\", \"django\", \"flask\", \"cmake\"]:\n        cache.delete(digest)\n\n    answer = cache.get(digest)\n    if answer:\n        return answer\n    answer = _beautify(text, lang, **beauty_options)\n    cache.put(digest, answer)\n\n    return answer\n\n\ndef __main__():\n    text = sys.stdin.read()\n    filetype = sys.argv[1]\n    options = {\n        \"\": {},\n        \"c\": dict(add_comments=True),\n        \"C\": dict(add_comments=False),\n        \"q\": dict(remove_text=True),\n    }[sys.argv[2]]\n    result = beautify(text, filetype, options)\n    sys.stdout.write(result)\n\n\nif __name__ == \"__main__\":\n    __main__()\n"
  },
  {
    "path": "lib/fmt/internal.py",
    "content": "\"\"\"\nColorize internal cheat sheets.\nWill be merged with panela later.\n\"\"\"\n\nimport re\n\nfrom colorama import Fore, Back, Style\nimport colored\n\nPALETTES = {\n    0: {\n        1: Fore.WHITE,\n        2: Style.DIM,\n    },\n    1: {\n        1: Fore.CYAN,\n        2: Fore.GREEN,\n        3: colored.fg(\"orange_3\"),\n        4: Style.DIM,\n        5: Style.DIM,\n    },\n    2: {\n        1: Fore.RED,\n        2: Style.DIM,\n    },\n}\n\n\ndef _reverse_palette(code):\n    return {1: Fore.BLACK + _back_color(code), 2: Style.DIM}\n\n\ndef _back_color(code):\n    if code == 0 or (isinstance(code, str) and code.lower() == \"white\"):\n        return Back.WHITE\n    if code == 1 or (isinstance(code, str) and code.lower() == \"cyan\"):\n        return Back.CYAN\n    if code == 2 or (isinstance(code, str) and code.lower() == \"red\"):\n        return Back.RED\n\n    return Back.WHITE\n\n\ndef colorize_internal(text, palette_number=1):\n    \"\"\"\n    Colorize `text`, use `palette`\n    \"\"\"\n\n    palette = PALETTES[palette_number]\n    palette_reverse = _reverse_palette(palette_number)\n\n    def _process_text(text):\n        text = text.group()[1:-1]\n        factor = 1\n        if text.startswith(\"-\"):\n            text = text[1:]\n            factor = -1\n        stripped = text.lstrip(\"0123456789\")\n        return (text, stripped, factor)\n\n    def _extract_color_number(text, stripped, factor=1):\n        return int(text[: len(text) - len(stripped)]) * factor\n\n    def _colorize_curlies_block(text):\n        text, stripped, factor = _process_text(text)\n        color_number = _extract_color_number(text, stripped, factor)\n\n        if stripped.startswith(\"=\"):\n            stripped = stripped[1:]\n\n        reverse = color_number < 0\n        if reverse:\n            color_number = -color_number\n\n        if reverse:\n            stripped = palette_reverse[color_number] + stripped + Style.RESET_ALL\n        else:\n            stripped = palette[color_number] + stripped + Style.RESET_ALL\n\n        return stripped\n\n    def _colorize_headers(text):\n        if text.group(0).endswith(\"\\n\"):\n            newline = \"\\n\"\n        else:\n            newline = \"\"\n\n        color_number = 3\n        return palette[color_number] + text.group(0).strip() + Style.RESET_ALL + newline\n\n    text = re.sub(\"{.*?}\", _colorize_curlies_block, text)\n    text = re.sub(\"#(.*?)\\n\", _colorize_headers, text)\n    return text\n\n\ndef colorize_internal_firstpage_v1(answer):\n    \"\"\"\n    Colorize \"/:firstpage-v1\".\n    Legacy.\n    \"\"\"\n\n    def _colorize_line(line):\n        if line.startswith(\"T\"):\n            line = colored.fg(\"grey_62\") + line + colored.attr(\"reset\")\n            line = re.sub(\n                r\"\\{(.*?)\\}\",\n                colored.fg(\"orange_3\") + r\"\\1\" + colored.fg(\"grey_35\"),\n                line,\n            )\n            return line\n\n        line = re.sub(\n            r\"\\[(F.*?)\\]\",\n            colored.bg(\"black\") + colored.fg(\"cyan\") + r\"[\\1]\" + colored.attr(\"reset\"),\n            line,\n        )\n        line = re.sub(\n            r\"\\[(g.*?)\\]\",\n            colored.bg(\"dark_gray\")\n            + colored.fg(\"grey_0\")\n            + r\"[\\1]\"\n            + colored.attr(\"reset\"),\n            line,\n        )\n        line = re.sub(\n            r\"\\{(.*?)\\}\", colored.fg(\"orange_3\") + r\"\\1\" + colored.attr(\"reset\"), line\n        )\n        line = re.sub(\n            r\"<(.*?)>\", colored.fg(\"cyan\") + r\"\\1\" + colored.attr(\"reset\"), line\n        )\n        return line\n\n    lines = answer.splitlines()\n    answer_lines = lines[:9]\n    answer_lines.append(colored.fg(\"grey_35\") + lines[9] + colored.attr(\"reset\"))\n    for line in lines[10:]:\n        answer_lines.append(_colorize_line(line))\n    answer = \"\\n\".join(answer_lines) + \"\\n\"\n\n    return answer\n"
  },
  {
    "path": "lib/fmt/markdown.py",
    "content": "\"\"\"\nMarkdown support.\n\nExports:\n    format_text(text, config=None, highlighter=None):\n\nUses external pygments formatters for highlighting (passed as an argument).\n\"\"\"\n\nimport re\nimport ansiwrap\nimport colored\n\n\ndef format_text(text, config=None, highlighter=None):\n    \"\"\"\n    Renders `text` according to markdown rules.\n    Uses `highlighter` for syntax highlighting.\n    Returns a dictionary with \"output\" and \"links\".\n    \"\"\"\n    return _format_section(text, config=config, highlighter=highlighter)\n\n\ndef _split_into_paragraphs(text):\n    return re.split(\"\\n\\n+\", text)\n\n\ndef _colorize(text):\n    return re.sub(\n        r\"`(.*?)`\",\n        colored.bg(\"dark_gray\")\n        + colored.fg(\"white\")\n        + \" \"\n        + r\"\\1\"\n        + \" \"\n        + colored.attr(\"reset\"),\n        re.sub(\n            r\"\\*\\*(.*?)\\*\\*\",\n            colored.attr(\"bold\") + colored.fg(\"white\") + r\"\\1\" + colored.attr(\"reset\"),\n            text,\n        ),\n    )\n\n\ndef _format_section(section_text, config=None, highlighter=None):\n\n    answer = \"\"\n\n    # cut code blocks\n    block_number = 0\n    while True:\n        section_text, replacements = re.subn(\n            \"^```.*?^```\",\n            \"MULTILINE_BLOCK_%s\" % block_number,\n            section_text,\n            1,\n            flags=re.S | re.MULTILINE,\n        )\n        block_number += 1\n        if not replacements:\n            break\n\n    # cut links\n    links = []\n    while True:\n        regexp = re.compile(r\"\\[(.*?)\\]\\((.*?)\\)\")\n        match = regexp.search(section_text)\n        if match:\n            links.append(match.group(0))\n            text = match.group(1)\n            # links are not yet supported\n            #\n            text = \"\\x1b]8;;%s\\x1b\\\\\\\\%s\\x1b]8;;\\x1b\\\\\\\\\" % (\n                match.group(2),\n                match.group(1),\n            )\n        else:\n            break\n\n        section_text, replacements = regexp.subn(\n            text, section_text, 1  # 'LINK_%s' % len(links),\n        )\n        block_number += 1\n        if not replacements:\n            break\n\n    for paragraph in _split_into_paragraphs(section_text):\n        answer += (\n            \"\\n\".join(\n                ansiwrap.fill(_colorize(line)) + \"\\n\" for line in paragraph.splitlines()\n            )\n            + \"\\n\"\n        )\n\n    return {\"ansi\": answer, \"links\": links}\n"
  },
  {
    "path": "lib/frontend/__init__.py",
    "content": ""
  },
  {
    "path": "lib/frontend/ansi.py",
    "content": "\"\"\"\nANSI frontend.\n\nExports:\n    visualize(answer_data, request_options)\n\nFormat:\n    answer_data = {\n        'answers': '...',}\n\n    answers = [answer,...]\n\n    answer = {\n        'topic':        '...',\n        'topic_type':   '...',\n        'answer':       '...',\n        'format':       'ansi|code|markdown|text...',\n    }\n\nConfiguration parameters:\n\n    frontend.styles\n\"\"\"\n\nimport os\nimport sys\nimport re\n\nimport colored\nfrom pygments import highlight as pygments_highlight\nfrom pygments.formatters import (\n    Terminal256Formatter,\n)  # pylint: disable=no-name-in-module\n\n# pylint: disable=wrong-import-position\nsys.path.append(os.path.abspath(os.path.join(__file__, \"..\")))\nfrom config import CONFIG\nimport languages_data  # pylint: enable=wrong-import-position\n\nimport fmt.internal\nimport fmt.comments\n\n\ndef visualize(answer_data, request_options):\n    \"\"\"\n    Renders `answer_data` as ANSI output.\n    \"\"\"\n    answers = answer_data[\"answers\"]\n    return _visualize(\n        answers, request_options, search_mode=bool(answer_data[\"keyword\"])\n    )\n\n\nANSI_ESCAPE = re.compile(r\"(\\x9B|\\x1B\\[)[0-?]*[ -\\/]*[@-~]\")\n\n\ndef remove_ansi(sometext):\n    \"\"\"\n    Remove ANSI sequences from `sometext` and convert it into plaintext.\n    \"\"\"\n    return ANSI_ESCAPE.sub(\"\", sometext)\n\n\ndef _limited_answer(answer):\n    return (\n        colored.bg(\"dark_goldenrod\")\n        + colored.fg(\"yellow_1\")\n        + \" \"\n        + answer\n        + \" \"\n        + colored.attr(\"reset\")\n        + \"\\n\"\n    )\n\n\ndef _colorize_ansi_answer(\n    topic,\n    answer,\n    color_style,  # pylint: disable=too-many-arguments\n    highlight_all=True,\n    highlight_code=False,\n    unindent_code=False,\n    language=None,\n):\n\n    color_style = color_style or \"native\"\n    lexer_class = languages_data.LEXER[\"bash\"]\n    if \"/\" in topic:\n        if language is None:\n            section_name = topic.split(\"/\", 1)[0].lower()\n        else:\n            section_name = language\n        section_name = languages_data.get_lexer_name(section_name)\n        lexer_class = languages_data.LEXER.get(section_name, lexer_class)\n        if section_name == \"php\":\n            answer = \"<?\\n%s?>\\n\" % answer\n\n    if highlight_all:\n        highlight = (\n            lambda answer: pygments_highlight(\n                answer, lexer_class(), Terminal256Formatter(style=color_style)\n            ).strip(\"\\n\")\n            + \"\\n\"\n        )\n    else:\n        highlight = lambda x: x\n\n    if highlight_code:\n        blocks = fmt.comments.code_blocks(\n            answer, wrap_lines=True, unindent_code=(4 if unindent_code else False)\n        )\n        highlighted_blocks = []\n        for block in blocks:\n            if block[0] == 1:\n                this_block = highlight(block[1])\n            else:\n                this_block = block[1].strip(\"\\n\") + \"\\n\"\n            highlighted_blocks.append(this_block)\n\n        result = \"\\n\".join(highlighted_blocks)\n    else:\n        result = highlight(answer).lstrip(\"\\n\")\n    return result\n\n\ndef _visualize(answers, request_options, search_mode=False):\n\n    highlight = not bool(request_options and request_options.get(\"no-terminal\"))\n    color_style = (request_options or {}).get(\"style\", \"\")\n    if color_style not in CONFIG[\"frontend.styles\"]:\n        color_style = \"\"\n\n    # if there is more than one answer,\n    # show the source of the answer\n    multiple_answers = len(answers) > 1\n\n    found = True\n    result = \"\"\n    for answer_dict in answers:\n        topic = answer_dict[\"topic\"]\n        topic_type = answer_dict[\"topic_type\"]\n        answer = answer_dict[\"answer\"]\n        found = found and not topic_type == \"unknown\"\n\n        if multiple_answers and topic != \"LIMITED\":\n            section_name = f\"{topic_type}:{topic}\"\n\n            if not highlight:\n                result += f\"#[{section_name}]\\n\"\n            else:\n                result += \"\".join(\n                    [\n                        \"\\n\",\n                        colored.bg(\"dark_gray\"),\n                        colored.attr(\"res_underlined\"),\n                        f\" {section_name} \",\n                        colored.attr(\"res_underlined\"),\n                        colored.attr(\"reset\"),\n                        \"\\n\",\n                    ]\n                )\n\n        if answer_dict[\"format\"] in [\"ansi\", \"text\"]:\n            result += answer\n        elif topic == \":firstpage-v1\":\n            result += fmt.internal.colorize_internal_firstpage_v1(answer)\n        elif topic == \"LIMITED\":\n            result += _limited_answer(topic)\n        else:\n            result += _colorize_ansi_answer(\n                topic,\n                answer,\n                color_style,\n                highlight_all=highlight,\n                highlight_code=(\n                    topic_type == \"question\"\n                    and not request_options.get(\"add_comments\")\n                    and not request_options.get(\"remove_text\")\n                ),\n                language=answer_dict.get(\"filetype\"),\n            )\n\n    if request_options.get(\"no-terminal\"):\n        result = remove_ansi(result)\n\n    result = result.strip(\"\\n\") + \"\\n\"\n    return result, found\n"
  },
  {
    "path": "lib/frontend/html.py",
    "content": "\"\"\"\n\nConfiguration parameters:\n\n    path.internal.ansi2html\n\"\"\"\n\nimport sys\nimport os\nimport re\nfrom subprocess import Popen, PIPE\n\nMYDIR = os.path.abspath(os.path.join(__file__, \"..\", \"..\"))\nsys.path.append(\"%s/lib/\" % MYDIR)\n\n# pylint: disable=wrong-import-position\nfrom config import CONFIG\nfrom globals import error\nfrom buttons import TWITTER_BUTTON, GITHUB_BUTTON, GITHUB_BUTTON_FOOTER\nimport frontend.ansi\n\n# temporary having it here, but actually we have the same data\n# in the adapter module\nGITHUB_REPOSITORY = {\n    \"late.nz\": \"chubin/late.nz\",\n    \"cheat.sheets\": \"chubin/cheat.sheets\",\n    \"cheat.sheets dir\": \"chubin/cheat.sheets\",\n    \"tldr\": \"tldr-pages/tldr\",\n    \"cheat\": \"chrisallenlane/cheat\",\n    \"learnxiny\": \"adambard/learnxinyminutes-docs\",\n    \"internal\": \"\",\n    \"search\": \"\",\n    \"unknown\": \"\",\n}\n\n\ndef visualize(answer_data, request_options):\n    query = answer_data[\"query\"]\n    answers = answer_data[\"answers\"]\n    topics_list = answer_data[\"topics_list\"]\n    editable = len(answers) == 1 and answers[0][\"topic_type\"] == \"cheat.sheets\"\n\n    repository_button = \"\"\n    if len(answers) == 1:\n        repository_button = _github_button(answers[0][\"topic_type\"])\n\n    result, found = frontend.ansi.visualize(answer_data, request_options)\n    return (\n        _render_html(\n            query, result, editable, repository_button, topics_list, request_options\n        ),\n        found,\n    )\n\n\ndef _github_button(topic_type):\n\n    full_name = GITHUB_REPOSITORY.get(topic_type, \"\")\n    if not full_name:\n        return \"\"\n\n    short_name = full_name.split(\"/\", 1)[1]  # pylint: disable=unused-variable\n\n    button = (\n        \"<!-- Place this tag where you want the button to render. -->\"\n        '<a aria-label=\"Star %(full_name)s on GitHub\"'\n        ' data-count-aria-label=\"# stargazers on GitHub\"'\n        ' data-count-api=\"/repos/%(full_name)s#stargazers_count\"'\n        ' data-count-href=\"/%(full_name)s/stargazers\"'\n        ' data-icon=\"octicon-star\"'\n        ' href=\"https://github.com/%(full_name)s\"'\n        '  class=\"github-button\">%(short_name)s</a>'\n    ) % locals()\n    return button\n\n\ndef _render_html(\n    query, result, editable, repository_button, topics_list, request_options\n):\n\n    def _html_wrapper(data):\n        \"\"\"\n        Convert ANSI text `data` to HTML\n        \"\"\"\n        cmd = [\n            \"bash\",\n            CONFIG[\"path.internal.ansi2html\"],\n            \"--palette=solarized\",\n            \"--bg=dark\",\n        ]\n        try:\n            proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)\n        except FileNotFoundError:\n            print(\"ERROR: %s\" % cmd)\n            raise\n        data = data.encode(\"utf-8\")\n        stdout, stderr = proc.communicate(data)\n        if proc.returncode != 0:\n            error((stdout + stderr).decode(\"utf-8\"))\n        return stdout.decode(\"utf-8\")\n\n    result = result + \"\\n$\"\n    result = _html_wrapper(result)\n    title = \"<title>cheat.sh/%s</title>\" % query\n    submit_button = (\n        '<input type=\"submit\" style=\"position: absolute;'\n        ' left: -9999px; width: 1px; height: 1px;\" tabindex=\"-1\" />'\n    )\n    topic_list = '<datalist id=\"topics\">%s</datalist>' % (\n        \"\\n\".join(\"<option value='%s'></option>\" % x for x in topics_list)\n    )\n\n    curl_line = \"<span class='pre'>$ curl cheat.sh/</span>\"\n    if query == \":firstpage\":\n        query = \"\"\n    form_html = (\n        '<form action=\"/\" method=\"GET\">'\n        \"%s%s\"\n        \"<input\"\n        ' type=\"text\" value=\"%s\" name=\"topic\"'\n        ' list=\"topics\" autofocus autocomplete=\"off\"/>'\n        \"%s\"\n        \"</form>\"\n    ) % (submit_button, curl_line, query, topic_list)\n\n    edit_button = \"\"\n    if editable:\n        # It's possible that topic directory starts with omitted underscore\n        if \"/\" in query:\n            query = \"_\" + query\n        edit_page_link = (\n            \"https://github.com/chubin/cheat.sheets/edit/master/sheets/\" + query\n        )\n        edit_button = (\n            '<pre style=\"position:absolute;padding-left:40em;overflow:visible;height:0;\">'\n            '[<a href=\"%s\" style=\"color:cyan\">edit</a>]'\n            \"</pre>\"\n        ) % edit_page_link\n    result = re.sub(\"<pre>\", edit_button + form_html + \"<pre>\", result)\n    result = re.sub(\"<head>\", \"<head>\" + title, result)\n    if not request_options.get(\"quiet\"):\n        result = result.replace(\n            \"</body>\",\n            TWITTER_BUTTON\n            + GITHUB_BUTTON\n            + repository_button\n            + GITHUB_BUTTON_FOOTER\n            + \"</body>\",\n        )\n    return result\n"
  },
  {
    "path": "lib/globals.py",
    "content": "\"\"\"\nGlobal functions that our used everywhere in the project.\nPlease, no global variables here.\nFor the configuration related things see `config.py`\n\"\"\"\n\nfrom __future__ import print_function\n\nimport sys\nimport logging\n\n\ndef fatal(text):\n    \"\"\"\n    Fatal error function.\n\n    The function is being used in the standalone mode only\n    \"\"\"\n    sys.stderr.write(\"ERROR: %s\\n\" % text)\n    sys.exit(1)\n\n\ndef error(text):\n    \"\"\"\n    Log error `text` and produce a RuntimeError exception\n    \"\"\"\n    if not text.startswith(\"Too many queries\"):\n        print(text)\n    logging.error(\"ERROR %s\", text)\n    raise RuntimeError(text)\n\n\ndef log(text):\n    \"\"\"\n    Log error `text` (if it does not start with 'Too many queries')\n    \"\"\"\n    if not text.startswith(\"Too many queries\"):\n        print(text)\n        logging.info(text)\n"
  },
  {
    "path": "lib/languages_data.py",
    "content": "\"\"\"\n\nProgramming languages information.\nWill be (probably) moved to a separate file/directory\nfrom the project tree.\n\n\"\"\"\n\nimport pygments.lexers\n\nLEXER = {\n    \"assembly\": pygments.lexers.NasmLexer,\n    \"awk\": pygments.lexers.AwkLexer,\n    \"bash\": pygments.lexers.BashLexer,\n    \"basic\": pygments.lexers.QBasicLexer,\n    \"bf\": pygments.lexers.BrainfuckLexer,\n    \"chapel\": pygments.lexers.ChapelLexer,\n    \"clojure\": pygments.lexers.ClojureLexer,\n    \"coffee\": pygments.lexers.CoffeeScriptLexer,\n    \"cpp\": pygments.lexers.CppLexer,\n    \"c\": pygments.lexers.CLexer,\n    \"csharp\": pygments.lexers.CSharpLexer,\n    \"d\": pygments.lexers.DLexer,\n    \"dart\": pygments.lexers.DartLexer,\n    \"delphi\": pygments.lexers.DelphiLexer,\n    \"elisp\": pygments.lexers.EmacsLispLexer,\n    \"elixir\": pygments.lexers.ElixirLexer,\n    \"elm\": pygments.lexers.ElmLexer,\n    \"erlang\": pygments.lexers.ErlangLexer,\n    \"factor\": pygments.lexers.FactorLexer,\n    \"forth\": pygments.lexers.ForthLexer,\n    \"fortran\": pygments.lexers.FortranLexer,\n    \"fsharp\": pygments.lexers.FSharpLexer,\n    \"git\": pygments.lexers.BashLexer,\n    \"go\": pygments.lexers.GoLexer,\n    \"groovy\": pygments.lexers.GroovyLexer,\n    \"haskell\": pygments.lexers.HaskellLexer,\n    \"java\": pygments.lexers.JavaLexer,\n    \"js\": pygments.lexers.JavascriptLexer,\n    \"julia\": pygments.lexers.JuliaLexer,\n    \"kotlin\": pygments.lexers.KotlinLexer,\n    \"latex\": pygments.lexers.TexLexer,\n    \"lisp\": pygments.lexers.CommonLispLexer,\n    \"lua\": pygments.lexers.LuaLexer,\n    \"mathematica\": pygments.lexers.MathematicaLexer,\n    \"matlab\": pygments.lexers.MatlabLexer,\n    \"mongo\": pygments.lexers.JavascriptLexer,\n    \"nim\": pygments.lexers.NimrodLexer,\n    \"objective-c\": pygments.lexers.ObjectiveCppLexer,\n    \"ocaml\": pygments.lexers.OcamlLexer,\n    \"octave\": pygments.lexers.OctaveLexer,\n    \"perl\": pygments.lexers.PerlLexer,\n    \"perl6\": pygments.lexers.Perl6Lexer,\n    \"php\": pygments.lexers.PhpLexer,\n    \"psql\": pygments.lexers.PostgresLexer,\n    \"python\": pygments.lexers.PythonLexer,\n    \"python3\": pygments.lexers.Python3Lexer,\n    \"r\": pygments.lexers.SLexer,\n    \"racket\": pygments.lexers.RacketLexer,\n    \"ruby\": pygments.lexers.RubyLexer,\n    \"rust\": pygments.lexers.RustLexer,\n    \"solidity\": pygments.lexers.JavascriptLexer,\n    \"scala\": pygments.lexers.ScalaLexer,\n    \"scheme\": pygments.lexers.SchemeLexer,\n    \"psql\": pygments.lexers.SqlLexer,\n    \"sql\": pygments.lexers.SqlLexer,\n    \"swift\": pygments.lexers.SwiftLexer,\n    \"tcl\": pygments.lexers.TclLexer,\n    \"tcsh\": pygments.lexers.TcshLexer,\n    \"vb\": pygments.lexers.VbNetLexer,\n    \"vbnet\": pygments.lexers.VbNetLexer,\n    \"vim\": pygments.lexers.VimLexer,\n    # experimental\n    \"arduino\": pygments.lexers.ArduinoLexer,\n    \"pike\": pygments.lexers.PikeLexer,\n    \"eiffel\": pygments.lexers.EiffelLexer,\n    \"clean\": pygments.lexers.CleanLexer,\n    \"dylan\": pygments.lexers.DylanLexer,\n    # not languages\n    \"cmake\": pygments.lexers.CMakeLexer,\n    \"django\": pygments.lexers.PythonLexer,\n    \"flask\": pygments.lexers.PythonLexer,\n}\n\n# canonical names are on the right side\nLANGUAGE_ALIAS = {\n    \"asm\": \"assembly\",\n    \"assembler\": \"assembly\",\n    \"c++\": \"cpp\",\n    \"c#\": \"csharp\",\n    \"clisp\": \"lisp\",\n    \"coffeescript\": \"coffee\",\n    \"cplusplus\": \"cpp\",\n    \"dlang\": \"d\",\n    \"f#\": \"fsharp\",\n    \"golang\": \"go\",\n    \"javascript\": \"js\",\n    \"objc\": \"objective-c\",\n    \"p6\": \"perl6\",\n    \"sh\": \"bash\",\n    \"visualbasic\": \"vb\",\n    \"vba\": \"vb\",\n    \"wolfram\": \"mathematica\",\n    \"mma\": \"mathematica\",\n    \"wolfram-mathematica\": \"mathematica\",\n    \"m\": \"octave\",\n}\n\nVIM_NAME = {\n    \"assembly\": \"asm\",\n    \"bash\": \"sh\",\n    \"coffeescript\": \"coffee\",\n    \"csharp\": \"cs\",\n    \"delphi\": \"pascal\",\n    \"dlang\": \"d\",\n    \"elisp\": \"newlisp\",\n    \"latex\": \"tex\",\n    \"forth\": \"fs\",\n    \"nim\": \"nimrod\",\n    \"perl6\": \"perl\",\n    \"python3\": \"python\",\n    \"python-3.x\": \"python\",\n    \"tcsh\": \"sh\",\n    \"solidity\": \"js\",\n    \"mathematica\": \"mma\",\n    \"wolfram-mathematica\": \"mma\",\n    \"psql\": \"sql\",\n    # not languages\n    \"cmake\": \"sh\",\n    \"git\": \"sh\",\n    \"django\": \"python\",\n    \"flask\": \"python\",\n}\n\nSO_NAME = {\n    \"coffee\": \"coffeescript\",\n    \"js\": \"javascript\",\n    \"python3\": \"python-3.x\",\n    \"vb\": \"vba\",\n    \"mathematica\": \"wolfram-mathematica\",\n}\n\n\n#\n# conversion of internal programmin language names\n# into canonical cheat.sh names\n#\n\nATOM_FT_NAME = {}\n\nEMACS_FT_NAME = {\n    \"asm-mode\": \"asm\",\n    \"awk-mode\": \"awk\",\n    \"sh-mode\": \"bash\",\n    # basic\n    \"brainfuck-mode\": \"bf\",\n    # chapel\n    \"clojure-mode\": \"clojure\",\n    \"coffee-mode\": \"coffee\",\n    \"c++-mode\": \"cpp\",\n    \"c-mode\": \"c\",\n    \"csharp-mode\": \"csharp\",\n    \"d-mode\": \"d\",\n    \"dart-mode\": \"dart\",\n    \"dylan-mode\": \"dylan\",\n    \"delphi-mode\": \"delphi\",\n    \"emacs-lisp-mode\": \"elisp\",\n    # elixir\n    \"elm-mode\": \"elm\",\n    \"erlang-mode\": \"erlang\",\n    # factor\n    \"forth-mode\": \"forth\",\n    \"fortran-mode\": \"fortran\",\n    \"fsharp-mode\": \"fsharp\",\n    \"go-mode\": \"go\",\n    \"groovy-mode\": \"groovy\",\n    \"haskell-mode\": \"haskell\",\n    # \"hy-mode\"\n    \"java-mode\": \"java\",\n    \"js-jsx-mode\": \"js\",\n    \"js-mode\": \"js\",\n    \"js2-jsx-mode\": \"js\",\n    \"js2-mode\": \"js\",\n    \"julia-mode\": \"julia\",\n    \"kotlin-mode\": \"kotlin\",\n    \"lisp-interaction-mode\": \"lisp\",\n    \"lisp-mode\": \"lisp\",\n    \"lua-mode\": \"lua\",\n    # mathematica\n    \"matlab-mode\": \"matlab\",\n    # mongo\n    \"objc-mode\": \"objective-c\",\n    # ocaml\n    \"perl-mode\": \"perl\",\n    \"perl6-mode\": \"perl6\",\n    \"php-mode\": \"php\",\n    # psql\n    \"python-mode\": \"python\",\n    # python3\n    # r -- ess looks it, but I don't know the mode name off hand\n    \"racket-mode\": \"racket\",\n    \"ruby-mode\": \"ruby\",\n    \"rust-mode\": \"rust\",\n    \"solidity-mode\": \"solidity\",\n    \"scala-mode\": \"scala\",\n    \"scheme-mode\": \"scheme\",\n    \"sql-mode\": \"sql\",\n    \"swift-mode\": \"swift\",\n    \"tcl-mode\": \"tcl\",\n    # tcsh\n    \"visual-basic-mode\": \"vb\",\n    # vbnet\n    # vim\n}\n\nSUBLIME_FT_NAME = {}\n\nVIM_FT_NAME = {\n    \"asm\": \"assembler\",\n    \"javascript\": \"js\",\n    \"octave\": \"matlab\",\n}\n\nVSCODE_FT_NAME = {}\n\n\ndef rewrite_editor_section_name(section_name):\n    \"\"\"\n    section name cen be specified in form \"editor:editor-filetype\"\n    and it will be rewritten into form \"filetype\"\n    basing on the editor filetypes names data.\n    If editor name is unknown, it is just cut off:  notepad:js => js\n\n    Known editors:\n        * atom\n        * vim\n        * emacs\n        * sublime\n        * vscode\n\n    >>> rewrite_editor_section_name('js')\n    'js'\n    >>> rewrite_editor_section_name('vscode:js')\n    'js'\n    \"\"\"\n    if \":\" not in section_name:\n        return section_name\n\n    editor_name, section_name = section_name.split(\":\", 1)\n    editor_name_mapping = {\n        \"atom\": ATOM_FT_NAME,\n        \"emacs\": EMACS_FT_NAME,\n        \"sublime\": SUBLIME_FT_NAME,\n        \"vim\": VIM_FT_NAME,\n        \"vscode\": VSCODE_FT_NAME,\n    }\n    if editor_name not in editor_name_mapping:\n        return section_name\n    return editor_name_mapping[editor_name].get(section_name, section_name)\n\n\ndef get_lexer_name(section_name):\n    \"\"\"\n    Rewrite `section_name` for the further lexer search (for syntax highlighting)\n    \"\"\"\n    if \":\" in section_name:\n        section_name = rewrite_editor_section_name(section_name)\n    return LANGUAGE_ALIAS.get(section_name, section_name)\n\n\nif __name__ == \"__main__\":\n    import doctest\n\n    doctest.testmod()\n"
  },
  {
    "path": "lib/limits.py",
    "content": "\"\"\"\nConnection limitation.\n\nNumber of connections from one IP is limited.\nWe have nothing against scripting and automated queries.\nEven the opposite, we encourage them. But there are some\nconnection limits that even we can't handle.\nCurrently the limits are quite restrictive, but they will be relaxed\nin the future.\n\nUsage:\n\n        limits = Limits()\n        not_allowed = limits.check_ip(ip_address)\n        if not_allowed:\n            return \"ERROR: %s\" % not_allowed\n\"\"\"\n\nimport time\nfrom globals import log\n\n_WHITELIST = [\"5.9.243.177\"]\n\n\ndef _time_caps(minutes, hours, days):\n    return {\n        \"min\": minutes,\n        \"hour\": hours,\n        \"day\": days,\n    }\n\n\nclass Limits(object):\n    \"\"\"\n    Queries limitation (by IP).\n\n    Exports:\n\n        check_ip(ip_address)\n    \"\"\"\n\n    def __init__(self):\n        self.intervals = [\"min\", \"hour\", \"day\"]\n\n        self.divisor = _time_caps(60, 3600, 86400)\n        self.limit = _time_caps(30, 600, 1000)\n        self.last_update = _time_caps(0, 0, 0)\n\n        self.counter = {\n            \"min\": {},\n            \"hour\": {},\n            \"day\": {},\n        }\n\n        self._clear_counters_if_needed()\n\n    def _log_visit(self, interval, ip_address):\n        if ip_address not in self.counter[interval]:\n            self.counter[interval][ip_address] = 0\n        self.counter[interval][ip_address] += 1\n\n    def _limit_exceeded(self, interval, ip_address):\n        visits = self.counter[interval][ip_address]\n        limit = self._get_limit(interval)\n        return visits > limit\n\n    def _get_limit(self, interval):\n        return self.limit[interval]\n\n    def _report_excessive_visits(self, interval, ip_address):\n        log(\n            \"%s LIMITED [%s for %s]\" % (ip_address, self._get_limit(interval), interval)\n        )\n\n    def check_ip(self, ip_address):\n        \"\"\"\n        Check if `ip_address` is allowed, and if not raise an RuntimeError exception.\n        Return True otherwise\n        \"\"\"\n        if ip_address in _WHITELIST:\n            return None\n        self._clear_counters_if_needed()\n        for interval in self.intervals:\n            self._log_visit(interval, ip_address)\n            if self._limit_exceeded(interval, ip_address):\n                self._report_excessive_visits(interval, ip_address)\n                return \"Not so fast! Number of queries per %s is limited to %s\" % (\n                    interval,\n                    self._get_limit(interval),\n                )\n        return None\n\n    def reset(self):\n        \"\"\"\n        Reset all counters for all IPs\n        \"\"\"\n        for interval in self.intervals:\n            self.counter[interval] = {}\n\n    def _clear_counters_if_needed(self):\n        current_time = int(time.time())\n        for interval in self.intervals:\n            if current_time // self.divisor[interval] != self.last_update[interval]:\n                self.counter[interval] = {}\n                self.last_update[interval] = current_time / self.divisor[interval]\n"
  },
  {
    "path": "lib/options.py",
    "content": "\"\"\"\nParse query arguments.\n\"\"\"\n\n\ndef parse_args(args):\n    \"\"\"\n    Parse arguments and options.\n    Replace short options with their long counterparts.\n    \"\"\"\n    result = {\n        \"add_comments\": True,\n    }\n\n    query = \"\"\n    newargs = {}\n    for key, val in args.items():\n        if val == \"\" or val == [] or val == [\"\"]:\n            query += key\n            continue\n        if val == \"True\":\n            val = True\n        if val == \"False\":\n            val = False\n        newargs[key] = val\n\n    options_meaning = {\n        \"c\": dict(add_comments=False, unindent_code=False),\n        \"C\": dict(add_comments=False, unindent_code=True),\n        \"Q\": dict(remove_text=True),\n        \"q\": dict(quiet=True),\n        \"T\": {\"no-terminal\": True},\n    }\n    for option, meaning in options_meaning.items():\n        if option in query:\n            result.update(meaning)\n\n    result.update(newargs)\n\n    return result\n"
  },
  {
    "path": "lib/panela/colors.json",
    "content": "[{\"colorId\":0,\"hexString\":\"#000000\",\"rgb\":{\"r\":0,\"g\":0,\"b\":0},\"hsl\":{\"h\":0,\"s\":0,\"l\":0},\"name\":\"Black\"},{\"colorId\":1,\"hexString\":\"#800000\",\"rgb\":{\"r\":128,\"g\":0,\"b\":0},\"hsl\":{\"h\":0,\"s\":100,\"l\":25},\"name\":\"Maroon\"},{\"colorId\":2,\"hexString\":\"#008000\",\"rgb\":{\"r\":0,\"g\":128,\"b\":0},\"hsl\":{\"h\":120,\"s\":100,\"l\":25},\"name\":\"Green\"},{\"colorId\":3,\"hexString\":\"#808000\",\"rgb\":{\"r\":128,\"g\":128,\"b\":0},\"hsl\":{\"h\":60,\"s\":100,\"l\":25},\"name\":\"Olive\"},{\"colorId\":4,\"hexString\":\"#000080\",\"rgb\":{\"r\":0,\"g\":0,\"b\":128},\"hsl\":{\"h\":240,\"s\":100,\"l\":25},\"name\":\"Navy\"},{\"colorId\":5,\"hexString\":\"#800080\",\"rgb\":{\"r\":128,\"g\":0,\"b\":128},\"hsl\":{\"h\":300,\"s\":100,\"l\":25},\"name\":\"Purple\"},{\"colorId\":6,\"hexString\":\"#008080\",\"rgb\":{\"r\":0,\"g\":128,\"b\":128},\"hsl\":{\"h\":180,\"s\":100,\"l\":25},\"name\":\"Teal\"},{\"colorId\":7,\"hexString\":\"#c0c0c0\",\"rgb\":{\"r\":192,\"g\":192,\"b\":192},\"hsl\":{\"h\":0,\"s\":0,\"l\":75},\"name\":\"Silver\"},{\"colorId\":8,\"hexString\":\"#808080\",\"rgb\":{\"r\":128,\"g\":128,\"b\":128},\"hsl\":{\"h\":0,\"s\":0,\"l\":50},\"name\":\"Grey\"},{\"colorId\":9,\"hexString\":\"#ff0000\",\"rgb\":{\"r\":255,\"g\":0,\"b\":0},\"hsl\":{\"h\":0,\"s\":100,\"l\":50},\"name\":\"Red\"},{\"colorId\":10,\"hexString\":\"#00ff00\",\"rgb\":{\"r\":0,\"g\":255,\"b\":0},\"hsl\":{\"h\":120,\"s\":100,\"l\":50},\"name\":\"Lime\"},{\"colorId\":11,\"hexString\":\"#ffff00\",\"rgb\":{\"r\":255,\"g\":255,\"b\":0},\"hsl\":{\"h\":60,\"s\":100,\"l\":50},\"name\":\"Yellow\"},{\"colorId\":12,\"hexString\":\"#0000ff\",\"rgb\":{\"r\":0,\"g\":0,\"b\":255},\"hsl\":{\"h\":240,\"s\":100,\"l\":50},\"name\":\"Blue\"},{\"colorId\":13,\"hexString\":\"#ff00ff\",\"rgb\":{\"r\":255,\"g\":0,\"b\":255},\"hsl\":{\"h\":300,\"s\":100,\"l\":50},\"name\":\"Fuchsia\"},{\"colorId\":14,\"hexString\":\"#00ffff\",\"rgb\":{\"r\":0,\"g\":255,\"b\":255},\"hsl\":{\"h\":180,\"s\":100,\"l\":50},\"name\":\"Aqua\"},{\"colorId\":15,\"hexString\":\"#ffffff\",\"rgb\":{\"r\":255,\"g\":255,\"b\":255},\"hsl\":{\"h\":0,\"s\":0,\"l\":100},\"name\":\"White\"},{\"colorId\":16,\"hexString\":\"#000000\",\"rgb\":{\"r\":0,\"g\":0,\"b\":0},\"hsl\":{\"h\":0,\"s\":0,\"l\":0},\"name\":\"Grey0\"},{\"colorId\":17,\"hexString\":\"#00005f\",\"rgb\":{\"r\":0,\"g\":0,\"b\":95},\"hsl\":{\"h\":240,\"s\":100,\"l\":18},\"name\":\"NavyBlue\"},{\"colorId\":18,\"hexString\":\"#000087\",\"rgb\":{\"r\":0,\"g\":0,\"b\":135},\"hsl\":{\"h\":240,\"s\":100,\"l\":26},\"name\":\"DarkBlue\"},{\"colorId\":19,\"hexString\":\"#0000af\",\"rgb\":{\"r\":0,\"g\":0,\"b\":175},\"hsl\":{\"h\":240,\"s\":100,\"l\":34},\"name\":\"Blue3\"},{\"colorId\":20,\"hexString\":\"#0000d7\",\"rgb\":{\"r\":0,\"g\":0,\"b\":215},\"hsl\":{\"h\":240,\"s\":100,\"l\":42},\"name\":\"Blue3\"},{\"colorId\":21,\"hexString\":\"#0000ff\",\"rgb\":{\"r\":0,\"g\":0,\"b\":255},\"hsl\":{\"h\":240,\"s\":100,\"l\":50},\"name\":\"Blue1\"},{\"colorId\":22,\"hexString\":\"#005f00\",\"rgb\":{\"r\":0,\"g\":95,\"b\":0},\"hsl\":{\"h\":120,\"s\":100,\"l\":18},\"name\":\"DarkGreen\"},{\"colorId\":23,\"hexString\":\"#005f5f\",\"rgb\":{\"r\":0,\"g\":95,\"b\":95},\"hsl\":{\"h\":180,\"s\":100,\"l\":18},\"name\":\"DeepSkyBlue4\"},{\"colorId\":24,\"hexString\":\"#005f87\",\"rgb\":{\"r\":0,\"g\":95,\"b\":135},\"hsl\":{\"h\":197.777777777778,\"s\":100,\"l\":26},\"name\":\"DeepSkyBlue4\"},{\"colorId\":25,\"hexString\":\"#005faf\",\"rgb\":{\"r\":0,\"g\":95,\"b\":175},\"hsl\":{\"h\":207.428571428571,\"s\":100,\"l\":34},\"name\":\"DeepSkyBlue4\"},{\"colorId\":26,\"hexString\":\"#005fd7\",\"rgb\":{\"r\":0,\"g\":95,\"b\":215},\"hsl\":{\"h\":213.488372093023,\"s\":100,\"l\":42},\"name\":\"DodgerBlue3\"},{\"colorId\":27,\"hexString\":\"#005fff\",\"rgb\":{\"r\":0,\"g\":95,\"b\":255},\"hsl\":{\"h\":217.647058823529,\"s\":100,\"l\":50},\"name\":\"DodgerBlue2\"},{\"colorId\":28,\"hexString\":\"#008700\",\"rgb\":{\"r\":0,\"g\":135,\"b\":0},\"hsl\":{\"h\":120,\"s\":100,\"l\":26},\"name\":\"Green4\"},{\"colorId\":29,\"hexString\":\"#00875f\",\"rgb\":{\"r\":0,\"g\":135,\"b\":95},\"hsl\":{\"h\":162.222222222222,\"s\":100,\"l\":26},\"name\":\"SpringGreen4\"},{\"colorId\":30,\"hexString\":\"#008787\",\"rgb\":{\"r\":0,\"g\":135,\"b\":135},\"hsl\":{\"h\":180,\"s\":100,\"l\":26},\"name\":\"Turquoise4\"},{\"colorId\":31,\"hexString\":\"#0087af\",\"rgb\":{\"r\":0,\"g\":135,\"b\":175},\"hsl\":{\"h\":193.714285714286,\"s\":100,\"l\":34},\"name\":\"DeepSkyBlue3\"},{\"colorId\":32,\"hexString\":\"#0087d7\",\"rgb\":{\"r\":0,\"g\":135,\"b\":215},\"hsl\":{\"h\":202.325581395349,\"s\":100,\"l\":42},\"name\":\"DeepSkyBlue3\"},{\"colorId\":33,\"hexString\":\"#0087ff\",\"rgb\":{\"r\":0,\"g\":135,\"b\":255},\"hsl\":{\"h\":208.235294117647,\"s\":100,\"l\":50},\"name\":\"DodgerBlue1\"},{\"colorId\":34,\"hexString\":\"#00af00\",\"rgb\":{\"r\":0,\"g\":175,\"b\":0},\"hsl\":{\"h\":120,\"s\":100,\"l\":34},\"name\":\"Green3\"},{\"colorId\":35,\"hexString\":\"#00af5f\",\"rgb\":{\"r\":0,\"g\":175,\"b\":95},\"hsl\":{\"h\":152.571428571429,\"s\":100,\"l\":34},\"name\":\"SpringGreen3\"},{\"colorId\":36,\"hexString\":\"#00af87\",\"rgb\":{\"r\":0,\"g\":175,\"b\":135},\"hsl\":{\"h\":166.285714285714,\"s\":100,\"l\":34},\"name\":\"DarkCyan\"},{\"colorId\":37,\"hexString\":\"#00afaf\",\"rgb\":{\"r\":0,\"g\":175,\"b\":175},\"hsl\":{\"h\":180,\"s\":100,\"l\":34},\"name\":\"LightSeaGreen\"},{\"colorId\":38,\"hexString\":\"#00afd7\",\"rgb\":{\"r\":0,\"g\":175,\"b\":215},\"hsl\":{\"h\":191.162790697674,\"s\":100,\"l\":42},\"name\":\"DeepSkyBlue2\"},{\"colorId\":39,\"hexString\":\"#00afff\",\"rgb\":{\"r\":0,\"g\":175,\"b\":255},\"hsl\":{\"h\":198.823529411765,\"s\":100,\"l\":50},\"name\":\"DeepSkyBlue1\"},{\"colorId\":40,\"hexString\":\"#00d700\",\"rgb\":{\"r\":0,\"g\":215,\"b\":0},\"hsl\":{\"h\":120,\"s\":100,\"l\":42},\"name\":\"Green3\"},{\"colorId\":41,\"hexString\":\"#00d75f\",\"rgb\":{\"r\":0,\"g\":215,\"b\":95},\"hsl\":{\"h\":146.511627906977,\"s\":100,\"l\":42},\"name\":\"SpringGreen3\"},{\"colorId\":42,\"hexString\":\"#00d787\",\"rgb\":{\"r\":0,\"g\":215,\"b\":135},\"hsl\":{\"h\":157.674418604651,\"s\":100,\"l\":42},\"name\":\"SpringGreen2\"},{\"colorId\":43,\"hexString\":\"#00d7af\",\"rgb\":{\"r\":0,\"g\":215,\"b\":175},\"hsl\":{\"h\":168.837209302326,\"s\":100,\"l\":42},\"name\":\"Cyan3\"},{\"colorId\":44,\"hexString\":\"#00d7d7\",\"rgb\":{\"r\":0,\"g\":215,\"b\":215},\"hsl\":{\"h\":180,\"s\":100,\"l\":42},\"name\":\"DarkTurquoise\"},{\"colorId\":45,\"hexString\":\"#00d7ff\",\"rgb\":{\"r\":0,\"g\":215,\"b\":255},\"hsl\":{\"h\":189.411764705882,\"s\":100,\"l\":50},\"name\":\"Turquoise2\"},{\"colorId\":46,\"hexString\":\"#00ff00\",\"rgb\":{\"r\":0,\"g\":255,\"b\":0},\"hsl\":{\"h\":120,\"s\":100,\"l\":50},\"name\":\"Green1\"},{\"colorId\":47,\"hexString\":\"#00ff5f\",\"rgb\":{\"r\":0,\"g\":255,\"b\":95},\"hsl\":{\"h\":142.352941176471,\"s\":100,\"l\":50},\"name\":\"SpringGreen2\"},{\"colorId\":48,\"hexString\":\"#00ff87\",\"rgb\":{\"r\":0,\"g\":255,\"b\":135},\"hsl\":{\"h\":151.764705882353,\"s\":100,\"l\":50},\"name\":\"SpringGreen1\"},{\"colorId\":49,\"hexString\":\"#00ffaf\",\"rgb\":{\"r\":0,\"g\":255,\"b\":175},\"hsl\":{\"h\":161.176470588235,\"s\":100,\"l\":50},\"name\":\"MediumSpringGreen\"},{\"colorId\":50,\"hexString\":\"#00ffd7\",\"rgb\":{\"r\":0,\"g\":255,\"b\":215},\"hsl\":{\"h\":170.588235294118,\"s\":100,\"l\":50},\"name\":\"Cyan2\"},{\"colorId\":51,\"hexString\":\"#00ffff\",\"rgb\":{\"r\":0,\"g\":255,\"b\":255},\"hsl\":{\"h\":180,\"s\":100,\"l\":50},\"name\":\"Cyan1\"},{\"colorId\":52,\"hexString\":\"#5f0000\",\"rgb\":{\"r\":95,\"g\":0,\"b\":0},\"hsl\":{\"h\":0,\"s\":100,\"l\":18},\"name\":\"DarkRed\"},{\"colorId\":53,\"hexString\":\"#5f005f\",\"rgb\":{\"r\":95,\"g\":0,\"b\":95},\"hsl\":{\"h\":300,\"s\":100,\"l\":18},\"name\":\"DeepPink4\"},{\"colorId\":54,\"hexString\":\"#5f0087\",\"rgb\":{\"r\":95,\"g\":0,\"b\":135},\"hsl\":{\"h\":282.222222222222,\"s\":100,\"l\":26},\"name\":\"Purple4\"},{\"colorId\":55,\"hexString\":\"#5f00af\",\"rgb\":{\"r\":95,\"g\":0,\"b\":175},\"hsl\":{\"h\":272.571428571429,\"s\":100,\"l\":34},\"name\":\"Purple4\"},{\"colorId\":56,\"hexString\":\"#5f00d7\",\"rgb\":{\"r\":95,\"g\":0,\"b\":215},\"hsl\":{\"h\":266.511627906977,\"s\":100,\"l\":42},\"name\":\"Purple3\"},{\"colorId\":57,\"hexString\":\"#5f00ff\",\"rgb\":{\"r\":95,\"g\":0,\"b\":255},\"hsl\":{\"h\":262.352941176471,\"s\":100,\"l\":50},\"name\":\"BlueViolet\"},{\"colorId\":58,\"hexString\":\"#5f5f00\",\"rgb\":{\"r\":95,\"g\":95,\"b\":0},\"hsl\":{\"h\":60,\"s\":100,\"l\":18},\"name\":\"Orange4\"},{\"colorId\":59,\"hexString\":\"#5f5f5f\",\"rgb\":{\"r\":95,\"g\":95,\"b\":95},\"hsl\":{\"h\":0,\"s\":0,\"l\":37},\"name\":\"Grey37\"},{\"colorId\":60,\"hexString\":\"#5f5f87\",\"rgb\":{\"r\":95,\"g\":95,\"b\":135},\"hsl\":{\"h\":240,\"s\":17,\"l\":45},\"name\":\"MediumPurple4\"},{\"colorId\":61,\"hexString\":\"#5f5faf\",\"rgb\":{\"r\":95,\"g\":95,\"b\":175},\"hsl\":{\"h\":240,\"s\":33,\"l\":52},\"name\":\"SlateBlue3\"},{\"colorId\":62,\"hexString\":\"#5f5fd7\",\"rgb\":{\"r\":95,\"g\":95,\"b\":215},\"hsl\":{\"h\":240,\"s\":60,\"l\":60},\"name\":\"SlateBlue3\"},{\"colorId\":63,\"hexString\":\"#5f5fff\",\"rgb\":{\"r\":95,\"g\":95,\"b\":255},\"hsl\":{\"h\":240,\"s\":100,\"l\":68},\"name\":\"RoyalBlue1\"},{\"colorId\":64,\"hexString\":\"#5f8700\",\"rgb\":{\"r\":95,\"g\":135,\"b\":0},\"hsl\":{\"h\":77.7777777777778,\"s\":100,\"l\":26},\"name\":\"Chartreuse4\"},{\"colorId\":65,\"hexString\":\"#5f875f\",\"rgb\":{\"r\":95,\"g\":135,\"b\":95},\"hsl\":{\"h\":120,\"s\":17,\"l\":45},\"name\":\"DarkSeaGreen4\"},{\"colorId\":66,\"hexString\":\"#5f8787\",\"rgb\":{\"r\":95,\"g\":135,\"b\":135},\"hsl\":{\"h\":180,\"s\":17,\"l\":45},\"name\":\"PaleTurquoise4\"},{\"colorId\":67,\"hexString\":\"#5f87af\",\"rgb\":{\"r\":95,\"g\":135,\"b\":175},\"hsl\":{\"h\":210,\"s\":33,\"l\":52},\"name\":\"SteelBlue\"},{\"colorId\":68,\"hexString\":\"#5f87d7\",\"rgb\":{\"r\":95,\"g\":135,\"b\":215},\"hsl\":{\"h\":220,\"s\":60,\"l\":60},\"name\":\"SteelBlue3\"},{\"colorId\":69,\"hexString\":\"#5f87ff\",\"rgb\":{\"r\":95,\"g\":135,\"b\":255},\"hsl\":{\"h\":225,\"s\":100,\"l\":68},\"name\":\"CornflowerBlue\"},{\"colorId\":70,\"hexString\":\"#5faf00\",\"rgb\":{\"r\":95,\"g\":175,\"b\":0},\"hsl\":{\"h\":87.4285714285714,\"s\":100,\"l\":34},\"name\":\"Chartreuse3\"},{\"colorId\":71,\"hexString\":\"#5faf5f\",\"rgb\":{\"r\":95,\"g\":175,\"b\":95},\"hsl\":{\"h\":120,\"s\":33,\"l\":52},\"name\":\"DarkSeaGreen4\"},{\"colorId\":72,\"hexString\":\"#5faf87\",\"rgb\":{\"r\":95,\"g\":175,\"b\":135},\"hsl\":{\"h\":150,\"s\":33,\"l\":52},\"name\":\"CadetBlue\"},{\"colorId\":73,\"hexString\":\"#5fafaf\",\"rgb\":{\"r\":95,\"g\":175,\"b\":175},\"hsl\":{\"h\":180,\"s\":33,\"l\":52},\"name\":\"CadetBlue\"},{\"colorId\":74,\"hexString\":\"#5fafd7\",\"rgb\":{\"r\":95,\"g\":175,\"b\":215},\"hsl\":{\"h\":200,\"s\":60,\"l\":60},\"name\":\"SkyBlue3\"},{\"colorId\":75,\"hexString\":\"#5fafff\",\"rgb\":{\"r\":95,\"g\":175,\"b\":255},\"hsl\":{\"h\":210,\"s\":100,\"l\":68},\"name\":\"SteelBlue1\"},{\"colorId\":76,\"hexString\":\"#5fd700\",\"rgb\":{\"r\":95,\"g\":215,\"b\":0},\"hsl\":{\"h\":93.4883720930233,\"s\":100,\"l\":42},\"name\":\"Chartreuse3\"},{\"colorId\":77,\"hexString\":\"#5fd75f\",\"rgb\":{\"r\":95,\"g\":215,\"b\":95},\"hsl\":{\"h\":120,\"s\":60,\"l\":60},\"name\":\"PaleGreen3\"},{\"colorId\":78,\"hexString\":\"#5fd787\",\"rgb\":{\"r\":95,\"g\":215,\"b\":135},\"hsl\":{\"h\":140,\"s\":60,\"l\":60},\"name\":\"SeaGreen3\"},{\"colorId\":79,\"hexString\":\"#5fd7af\",\"rgb\":{\"r\":95,\"g\":215,\"b\":175},\"hsl\":{\"h\":160,\"s\":60,\"l\":60},\"name\":\"Aquamarine3\"},{\"colorId\":80,\"hexString\":\"#5fd7d7\",\"rgb\":{\"r\":95,\"g\":215,\"b\":215},\"hsl\":{\"h\":180,\"s\":60,\"l\":60},\"name\":\"MediumTurquoise\"},{\"colorId\":81,\"hexString\":\"#5fd7ff\",\"rgb\":{\"r\":95,\"g\":215,\"b\":255},\"hsl\":{\"h\":195,\"s\":100,\"l\":68},\"name\":\"SteelBlue1\"},{\"colorId\":82,\"hexString\":\"#5fff00\",\"rgb\":{\"r\":95,\"g\":255,\"b\":0},\"hsl\":{\"h\":97.6470588235294,\"s\":100,\"l\":50},\"name\":\"Chartreuse2\"},{\"colorId\":83,\"hexString\":\"#5fff5f\",\"rgb\":{\"r\":95,\"g\":255,\"b\":95},\"hsl\":{\"h\":120,\"s\":100,\"l\":68},\"name\":\"SeaGreen2\"},{\"colorId\":84,\"hexString\":\"#5fff87\",\"rgb\":{\"r\":95,\"g\":255,\"b\":135},\"hsl\":{\"h\":135,\"s\":100,\"l\":68},\"name\":\"SeaGreen1\"},{\"colorId\":85,\"hexString\":\"#5fffaf\",\"rgb\":{\"r\":95,\"g\":255,\"b\":175},\"hsl\":{\"h\":150,\"s\":100,\"l\":68},\"name\":\"SeaGreen1\"},{\"colorId\":86,\"hexString\":\"#5fffd7\",\"rgb\":{\"r\":95,\"g\":255,\"b\":215},\"hsl\":{\"h\":165,\"s\":100,\"l\":68},\"name\":\"Aquamarine1\"},{\"colorId\":87,\"hexString\":\"#5fffff\",\"rgb\":{\"r\":95,\"g\":255,\"b\":255},\"hsl\":{\"h\":180,\"s\":100,\"l\":68},\"name\":\"DarkSlateGray2\"},{\"colorId\":88,\"hexString\":\"#870000\",\"rgb\":{\"r\":135,\"g\":0,\"b\":0},\"hsl\":{\"h\":0,\"s\":100,\"l\":26},\"name\":\"DarkRed\"},{\"colorId\":89,\"hexString\":\"#87005f\",\"rgb\":{\"r\":135,\"g\":0,\"b\":95},\"hsl\":{\"h\":317.777777777778,\"s\":100,\"l\":26},\"name\":\"DeepPink4\"},{\"colorId\":90,\"hexString\":\"#870087\",\"rgb\":{\"r\":135,\"g\":0,\"b\":135},\"hsl\":{\"h\":300,\"s\":100,\"l\":26},\"name\":\"DarkMagenta\"},{\"colorId\":91,\"hexString\":\"#8700af\",\"rgb\":{\"r\":135,\"g\":0,\"b\":175},\"hsl\":{\"h\":286.285714285714,\"s\":100,\"l\":34},\"name\":\"DarkMagenta\"},{\"colorId\":92,\"hexString\":\"#8700d7\",\"rgb\":{\"r\":135,\"g\":0,\"b\":215},\"hsl\":{\"h\":277.674418604651,\"s\":100,\"l\":42},\"name\":\"DarkViolet\"},{\"colorId\":93,\"hexString\":\"#8700ff\",\"rgb\":{\"r\":135,\"g\":0,\"b\":255},\"hsl\":{\"h\":271.764705882353,\"s\":100,\"l\":50},\"name\":\"Purple\"},{\"colorId\":94,\"hexString\":\"#875f00\",\"rgb\":{\"r\":135,\"g\":95,\"b\":0},\"hsl\":{\"h\":42.2222222222222,\"s\":100,\"l\":26},\"name\":\"Orange4\"},{\"colorId\":95,\"hexString\":\"#875f5f\",\"rgb\":{\"r\":135,\"g\":95,\"b\":95},\"hsl\":{\"h\":0,\"s\":17,\"l\":45},\"name\":\"LightPink4\"},{\"colorId\":96,\"hexString\":\"#875f87\",\"rgb\":{\"r\":135,\"g\":95,\"b\":135},\"hsl\":{\"h\":300,\"s\":17,\"l\":45},\"name\":\"Plum4\"},{\"colorId\":97,\"hexString\":\"#875faf\",\"rgb\":{\"r\":135,\"g\":95,\"b\":175},\"hsl\":{\"h\":270,\"s\":33,\"l\":52},\"name\":\"MediumPurple3\"},{\"colorId\":98,\"hexString\":\"#875fd7\",\"rgb\":{\"r\":135,\"g\":95,\"b\":215},\"hsl\":{\"h\":260,\"s\":60,\"l\":60},\"name\":\"MediumPurple3\"},{\"colorId\":99,\"hexString\":\"#875fff\",\"rgb\":{\"r\":135,\"g\":95,\"b\":255},\"hsl\":{\"h\":255,\"s\":100,\"l\":68},\"name\":\"SlateBlue1\"},{\"colorId\":100,\"hexString\":\"#878700\",\"rgb\":{\"r\":135,\"g\":135,\"b\":0},\"hsl\":{\"h\":60,\"s\":100,\"l\":26},\"name\":\"Yellow4\"},{\"colorId\":101,\"hexString\":\"#87875f\",\"rgb\":{\"r\":135,\"g\":135,\"b\":95},\"hsl\":{\"h\":60,\"s\":17,\"l\":45},\"name\":\"Wheat4\"},{\"colorId\":102,\"hexString\":\"#878787\",\"rgb\":{\"r\":135,\"g\":135,\"b\":135},\"hsl\":{\"h\":0,\"s\":0,\"l\":52},\"name\":\"Grey53\"},{\"colorId\":103,\"hexString\":\"#8787af\",\"rgb\":{\"r\":135,\"g\":135,\"b\":175},\"hsl\":{\"h\":240,\"s\":20,\"l\":60},\"name\":\"LightSlateGrey\"},{\"colorId\":104,\"hexString\":\"#8787d7\",\"rgb\":{\"r\":135,\"g\":135,\"b\":215},\"hsl\":{\"h\":240,\"s\":50,\"l\":68},\"name\":\"MediumPurple\"},{\"colorId\":105,\"hexString\":\"#8787ff\",\"rgb\":{\"r\":135,\"g\":135,\"b\":255},\"hsl\":{\"h\":240,\"s\":100,\"l\":76},\"name\":\"LightSlateBlue\"},{\"colorId\":106,\"hexString\":\"#87af00\",\"rgb\":{\"r\":135,\"g\":175,\"b\":0},\"hsl\":{\"h\":73.7142857142857,\"s\":100,\"l\":34},\"name\":\"Yellow4\"},{\"colorId\":107,\"hexString\":\"#87af5f\",\"rgb\":{\"r\":135,\"g\":175,\"b\":95},\"hsl\":{\"h\":90,\"s\":33,\"l\":52},\"name\":\"DarkOliveGreen3\"},{\"colorId\":108,\"hexString\":\"#87af87\",\"rgb\":{\"r\":135,\"g\":175,\"b\":135},\"hsl\":{\"h\":120,\"s\":20,\"l\":60},\"name\":\"DarkSeaGreen\"},{\"colorId\":109,\"hexString\":\"#87afaf\",\"rgb\":{\"r\":135,\"g\":175,\"b\":175},\"hsl\":{\"h\":180,\"s\":20,\"l\":60},\"name\":\"LightSkyBlue3\"},{\"colorId\":110,\"hexString\":\"#87afd7\",\"rgb\":{\"r\":135,\"g\":175,\"b\":215},\"hsl\":{\"h\":210,\"s\":50,\"l\":68},\"name\":\"LightSkyBlue3\"},{\"colorId\":111,\"hexString\":\"#87afff\",\"rgb\":{\"r\":135,\"g\":175,\"b\":255},\"hsl\":{\"h\":220,\"s\":100,\"l\":76},\"name\":\"SkyBlue2\"},{\"colorId\":112,\"hexString\":\"#87d700\",\"rgb\":{\"r\":135,\"g\":215,\"b\":0},\"hsl\":{\"h\":82.3255813953488,\"s\":100,\"l\":42},\"name\":\"Chartreuse2\"},{\"colorId\":113,\"hexString\":\"#87d75f\",\"rgb\":{\"r\":135,\"g\":215,\"b\":95},\"hsl\":{\"h\":100,\"s\":60,\"l\":60},\"name\":\"DarkOliveGreen3\"},{\"colorId\":114,\"hexString\":\"#87d787\",\"rgb\":{\"r\":135,\"g\":215,\"b\":135},\"hsl\":{\"h\":120,\"s\":50,\"l\":68},\"name\":\"PaleGreen3\"},{\"colorId\":115,\"hexString\":\"#87d7af\",\"rgb\":{\"r\":135,\"g\":215,\"b\":175},\"hsl\":{\"h\":150,\"s\":50,\"l\":68},\"name\":\"DarkSeaGreen3\"},{\"colorId\":116,\"hexString\":\"#87d7d7\",\"rgb\":{\"r\":135,\"g\":215,\"b\":215},\"hsl\":{\"h\":180,\"s\":50,\"l\":68},\"name\":\"DarkSlateGray3\"},{\"colorId\":117,\"hexString\":\"#87d7ff\",\"rgb\":{\"r\":135,\"g\":215,\"b\":255},\"hsl\":{\"h\":200,\"s\":100,\"l\":76},\"name\":\"SkyBlue1\"},{\"colorId\":118,\"hexString\":\"#87ff00\",\"rgb\":{\"r\":135,\"g\":255,\"b\":0},\"hsl\":{\"h\":88.2352941176471,\"s\":100,\"l\":50},\"name\":\"Chartreuse1\"},{\"colorId\":119,\"hexString\":\"#87ff5f\",\"rgb\":{\"r\":135,\"g\":255,\"b\":95},\"hsl\":{\"h\":105,\"s\":100,\"l\":68},\"name\":\"LightGreen\"},{\"colorId\":120,\"hexString\":\"#87ff87\",\"rgb\":{\"r\":135,\"g\":255,\"b\":135},\"hsl\":{\"h\":120,\"s\":100,\"l\":76},\"name\":\"LightGreen\"},{\"colorId\":121,\"hexString\":\"#87ffaf\",\"rgb\":{\"r\":135,\"g\":255,\"b\":175},\"hsl\":{\"h\":140,\"s\":100,\"l\":76},\"name\":\"PaleGreen1\"},{\"colorId\":122,\"hexString\":\"#87ffd7\",\"rgb\":{\"r\":135,\"g\":255,\"b\":215},\"hsl\":{\"h\":160,\"s\":100,\"l\":76},\"name\":\"Aquamarine1\"},{\"colorId\":123,\"hexString\":\"#87ffff\",\"rgb\":{\"r\":135,\"g\":255,\"b\":255},\"hsl\":{\"h\":180,\"s\":100,\"l\":76},\"name\":\"DarkSlateGray1\"},{\"colorId\":124,\"hexString\":\"#af0000\",\"rgb\":{\"r\":175,\"g\":0,\"b\":0},\"hsl\":{\"h\":0,\"s\":100,\"l\":34},\"name\":\"Red3\"},{\"colorId\":125,\"hexString\":\"#af005f\",\"rgb\":{\"r\":175,\"g\":0,\"b\":95},\"hsl\":{\"h\":327.428571428571,\"s\":100,\"l\":34},\"name\":\"DeepPink4\"},{\"colorId\":126,\"hexString\":\"#af0087\",\"rgb\":{\"r\":175,\"g\":0,\"b\":135},\"hsl\":{\"h\":313.714285714286,\"s\":100,\"l\":34},\"name\":\"MediumVioletRed\"},{\"colorId\":127,\"hexString\":\"#af00af\",\"rgb\":{\"r\":175,\"g\":0,\"b\":175},\"hsl\":{\"h\":300,\"s\":100,\"l\":34},\"name\":\"Magenta3\"},{\"colorId\":128,\"hexString\":\"#af00d7\",\"rgb\":{\"r\":175,\"g\":0,\"b\":215},\"hsl\":{\"h\":288.837209302326,\"s\":100,\"l\":42},\"name\":\"DarkViolet\"},{\"colorId\":129,\"hexString\":\"#af00ff\",\"rgb\":{\"r\":175,\"g\":0,\"b\":255},\"hsl\":{\"h\":281.176470588235,\"s\":100,\"l\":50},\"name\":\"Purple\"},{\"colorId\":130,\"hexString\":\"#af5f00\",\"rgb\":{\"r\":175,\"g\":95,\"b\":0},\"hsl\":{\"h\":32.5714285714286,\"s\":100,\"l\":34},\"name\":\"DarkOrange3\"},{\"colorId\":131,\"hexString\":\"#af5f5f\",\"rgb\":{\"r\":175,\"g\":95,\"b\":95},\"hsl\":{\"h\":0,\"s\":33,\"l\":52},\"name\":\"IndianRed\"},{\"colorId\":132,\"hexString\":\"#af5f87\",\"rgb\":{\"r\":175,\"g\":95,\"b\":135},\"hsl\":{\"h\":330,\"s\":33,\"l\":52},\"name\":\"HotPink3\"},{\"colorId\":133,\"hexString\":\"#af5faf\",\"rgb\":{\"r\":175,\"g\":95,\"b\":175},\"hsl\":{\"h\":300,\"s\":33,\"l\":52},\"name\":\"MediumOrchid3\"},{\"colorId\":134,\"hexString\":\"#af5fd7\",\"rgb\":{\"r\":175,\"g\":95,\"b\":215},\"hsl\":{\"h\":280,\"s\":60,\"l\":60},\"name\":\"MediumOrchid\"},{\"colorId\":135,\"hexString\":\"#af5fff\",\"rgb\":{\"r\":175,\"g\":95,\"b\":255},\"hsl\":{\"h\":270,\"s\":100,\"l\":68},\"name\":\"MediumPurple2\"},{\"colorId\":136,\"hexString\":\"#af8700\",\"rgb\":{\"r\":175,\"g\":135,\"b\":0},\"hsl\":{\"h\":46.2857142857143,\"s\":100,\"l\":34},\"name\":\"DarkGoldenrod\"},{\"colorId\":137,\"hexString\":\"#af875f\",\"rgb\":{\"r\":175,\"g\":135,\"b\":95},\"hsl\":{\"h\":30,\"s\":33,\"l\":52},\"name\":\"LightSalmon3\"},{\"colorId\":138,\"hexString\":\"#af8787\",\"rgb\":{\"r\":175,\"g\":135,\"b\":135},\"hsl\":{\"h\":0,\"s\":20,\"l\":60},\"name\":\"RosyBrown\"},{\"colorId\":139,\"hexString\":\"#af87af\",\"rgb\":{\"r\":175,\"g\":135,\"b\":175},\"hsl\":{\"h\":300,\"s\":20,\"l\":60},\"name\":\"Grey63\"},{\"colorId\":140,\"hexString\":\"#af87d7\",\"rgb\":{\"r\":175,\"g\":135,\"b\":215},\"hsl\":{\"h\":270,\"s\":50,\"l\":68},\"name\":\"MediumPurple2\"},{\"colorId\":141,\"hexString\":\"#af87ff\",\"rgb\":{\"r\":175,\"g\":135,\"b\":255},\"hsl\":{\"h\":260,\"s\":100,\"l\":76},\"name\":\"MediumPurple1\"},{\"colorId\":142,\"hexString\":\"#afaf00\",\"rgb\":{\"r\":175,\"g\":175,\"b\":0},\"hsl\":{\"h\":60,\"s\":100,\"l\":34},\"name\":\"Gold3\"},{\"colorId\":143,\"hexString\":\"#afaf5f\",\"rgb\":{\"r\":175,\"g\":175,\"b\":95},\"hsl\":{\"h\":60,\"s\":33,\"l\":52},\"name\":\"DarkKhaki\"},{\"colorId\":144,\"hexString\":\"#afaf87\",\"rgb\":{\"r\":175,\"g\":175,\"b\":135},\"hsl\":{\"h\":60,\"s\":20,\"l\":60},\"name\":\"NavajoWhite3\"},{\"colorId\":145,\"hexString\":\"#afafaf\",\"rgb\":{\"r\":175,\"g\":175,\"b\":175},\"hsl\":{\"h\":0,\"s\":0,\"l\":68},\"name\":\"Grey69\"},{\"colorId\":146,\"hexString\":\"#afafd7\",\"rgb\":{\"r\":175,\"g\":175,\"b\":215},\"hsl\":{\"h\":240,\"s\":33,\"l\":76},\"name\":\"LightSteelBlue3\"},{\"colorId\":147,\"hexString\":\"#afafff\",\"rgb\":{\"r\":175,\"g\":175,\"b\":255},\"hsl\":{\"h\":240,\"s\":100,\"l\":84},\"name\":\"LightSteelBlue\"},{\"colorId\":148,\"hexString\":\"#afd700\",\"rgb\":{\"r\":175,\"g\":215,\"b\":0},\"hsl\":{\"h\":71.1627906976744,\"s\":100,\"l\":42},\"name\":\"Yellow3\"},{\"colorId\":149,\"hexString\":\"#afd75f\",\"rgb\":{\"r\":175,\"g\":215,\"b\":95},\"hsl\":{\"h\":80,\"s\":60,\"l\":60},\"name\":\"DarkOliveGreen3\"},{\"colorId\":150,\"hexString\":\"#afd787\",\"rgb\":{\"r\":175,\"g\":215,\"b\":135},\"hsl\":{\"h\":90,\"s\":50,\"l\":68},\"name\":\"DarkSeaGreen3\"},{\"colorId\":151,\"hexString\":\"#afd7af\",\"rgb\":{\"r\":175,\"g\":215,\"b\":175},\"hsl\":{\"h\":120,\"s\":33,\"l\":76},\"name\":\"DarkSeaGreen2\"},{\"colorId\":152,\"hexString\":\"#afd7d7\",\"rgb\":{\"r\":175,\"g\":215,\"b\":215},\"hsl\":{\"h\":180,\"s\":33,\"l\":76},\"name\":\"LightCyan3\"},{\"colorId\":153,\"hexString\":\"#afd7ff\",\"rgb\":{\"r\":175,\"g\":215,\"b\":255},\"hsl\":{\"h\":210,\"s\":100,\"l\":84},\"name\":\"LightSkyBlue1\"},{\"colorId\":154,\"hexString\":\"#afff00\",\"rgb\":{\"r\":175,\"g\":255,\"b\":0},\"hsl\":{\"h\":78.8235294117647,\"s\":100,\"l\":50},\"name\":\"GreenYellow\"},{\"colorId\":155,\"hexString\":\"#afff5f\",\"rgb\":{\"r\":175,\"g\":255,\"b\":95},\"hsl\":{\"h\":90,\"s\":100,\"l\":68},\"name\":\"DarkOliveGreen2\"},{\"colorId\":156,\"hexString\":\"#afff87\",\"rgb\":{\"r\":175,\"g\":255,\"b\":135},\"hsl\":{\"h\":100,\"s\":100,\"l\":76},\"name\":\"PaleGreen1\"},{\"colorId\":157,\"hexString\":\"#afffaf\",\"rgb\":{\"r\":175,\"g\":255,\"b\":175},\"hsl\":{\"h\":120,\"s\":100,\"l\":84},\"name\":\"DarkSeaGreen2\"},{\"colorId\":158,\"hexString\":\"#afffd7\",\"rgb\":{\"r\":175,\"g\":255,\"b\":215},\"hsl\":{\"h\":150,\"s\":100,\"l\":84},\"name\":\"DarkSeaGreen1\"},{\"colorId\":159,\"hexString\":\"#afffff\",\"rgb\":{\"r\":175,\"g\":255,\"b\":255},\"hsl\":{\"h\":180,\"s\":100,\"l\":84},\"name\":\"PaleTurquoise1\"},{\"colorId\":160,\"hexString\":\"#d70000\",\"rgb\":{\"r\":215,\"g\":0,\"b\":0},\"hsl\":{\"h\":0,\"s\":100,\"l\":42},\"name\":\"Red3\"},{\"colorId\":161,\"hexString\":\"#d7005f\",\"rgb\":{\"r\":215,\"g\":0,\"b\":95},\"hsl\":{\"h\":333.488372093023,\"s\":100,\"l\":42},\"name\":\"DeepPink3\"},{\"colorId\":162,\"hexString\":\"#d70087\",\"rgb\":{\"r\":215,\"g\":0,\"b\":135},\"hsl\":{\"h\":322.325581395349,\"s\":100,\"l\":42},\"name\":\"DeepPink3\"},{\"colorId\":163,\"hexString\":\"#d700af\",\"rgb\":{\"r\":215,\"g\":0,\"b\":175},\"hsl\":{\"h\":311.162790697674,\"s\":100,\"l\":42},\"name\":\"Magenta3\"},{\"colorId\":164,\"hexString\":\"#d700d7\",\"rgb\":{\"r\":215,\"g\":0,\"b\":215},\"hsl\":{\"h\":300,\"s\":100,\"l\":42},\"name\":\"Magenta3\"},{\"colorId\":165,\"hexString\":\"#d700ff\",\"rgb\":{\"r\":215,\"g\":0,\"b\":255},\"hsl\":{\"h\":290.588235294118,\"s\":100,\"l\":50},\"name\":\"Magenta2\"},{\"colorId\":166,\"hexString\":\"#d75f00\",\"rgb\":{\"r\":215,\"g\":95,\"b\":0},\"hsl\":{\"h\":26.5116279069767,\"s\":100,\"l\":42},\"name\":\"DarkOrange3\"},{\"colorId\":167,\"hexString\":\"#d75f5f\",\"rgb\":{\"r\":215,\"g\":95,\"b\":95},\"hsl\":{\"h\":0,\"s\":60,\"l\":60},\"name\":\"IndianRed\"},{\"colorId\":168,\"hexString\":\"#d75f87\",\"rgb\":{\"r\":215,\"g\":95,\"b\":135},\"hsl\":{\"h\":340,\"s\":60,\"l\":60},\"name\":\"HotPink3\"},{\"colorId\":169,\"hexString\":\"#d75faf\",\"rgb\":{\"r\":215,\"g\":95,\"b\":175},\"hsl\":{\"h\":320,\"s\":60,\"l\":60},\"name\":\"HotPink2\"},{\"colorId\":170,\"hexString\":\"#d75fd7\",\"rgb\":{\"r\":215,\"g\":95,\"b\":215},\"hsl\":{\"h\":300,\"s\":60,\"l\":60},\"name\":\"Orchid\"},{\"colorId\":171,\"hexString\":\"#d75fff\",\"rgb\":{\"r\":215,\"g\":95,\"b\":255},\"hsl\":{\"h\":285,\"s\":100,\"l\":68},\"name\":\"MediumOrchid1\"},{\"colorId\":172,\"hexString\":\"#d78700\",\"rgb\":{\"r\":215,\"g\":135,\"b\":0},\"hsl\":{\"h\":37.6744186046512,\"s\":100,\"l\":42},\"name\":\"Orange3\"},{\"colorId\":173,\"hexString\":\"#d7875f\",\"rgb\":{\"r\":215,\"g\":135,\"b\":95},\"hsl\":{\"h\":20,\"s\":60,\"l\":60},\"name\":\"LightSalmon3\"},{\"colorId\":174,\"hexString\":\"#d78787\",\"rgb\":{\"r\":215,\"g\":135,\"b\":135},\"hsl\":{\"h\":0,\"s\":50,\"l\":68},\"name\":\"LightPink3\"},{\"colorId\":175,\"hexString\":\"#d787af\",\"rgb\":{\"r\":215,\"g\":135,\"b\":175},\"hsl\":{\"h\":330,\"s\":50,\"l\":68},\"name\":\"Pink3\"},{\"colorId\":176,\"hexString\":\"#d787d7\",\"rgb\":{\"r\":215,\"g\":135,\"b\":215},\"hsl\":{\"h\":300,\"s\":50,\"l\":68},\"name\":\"Plum3\"},{\"colorId\":177,\"hexString\":\"#d787ff\",\"rgb\":{\"r\":215,\"g\":135,\"b\":255},\"hsl\":{\"h\":280,\"s\":100,\"l\":76},\"name\":\"Violet\"},{\"colorId\":178,\"hexString\":\"#d7af00\",\"rgb\":{\"r\":215,\"g\":175,\"b\":0},\"hsl\":{\"h\":48.8372093023256,\"s\":100,\"l\":42},\"name\":\"Gold3\"},{\"colorId\":179,\"hexString\":\"#d7af5f\",\"rgb\":{\"r\":215,\"g\":175,\"b\":95},\"hsl\":{\"h\":40,\"s\":60,\"l\":60},\"name\":\"LightGoldenrod3\"},{\"colorId\":180,\"hexString\":\"#d7af87\",\"rgb\":{\"r\":215,\"g\":175,\"b\":135},\"hsl\":{\"h\":30,\"s\":50,\"l\":68},\"name\":\"Tan\"},{\"colorId\":181,\"hexString\":\"#d7afaf\",\"rgb\":{\"r\":215,\"g\":175,\"b\":175},\"hsl\":{\"h\":0,\"s\":33,\"l\":76},\"name\":\"MistyRose3\"},{\"colorId\":182,\"hexString\":\"#d7afd7\",\"rgb\":{\"r\":215,\"g\":175,\"b\":215},\"hsl\":{\"h\":300,\"s\":33,\"l\":76},\"name\":\"Thistle3\"},{\"colorId\":183,\"hexString\":\"#d7afff\",\"rgb\":{\"r\":215,\"g\":175,\"b\":255},\"hsl\":{\"h\":270,\"s\":100,\"l\":84},\"name\":\"Plum2\"},{\"colorId\":184,\"hexString\":\"#d7d700\",\"rgb\":{\"r\":215,\"g\":215,\"b\":0},\"hsl\":{\"h\":60,\"s\":100,\"l\":42},\"name\":\"Yellow3\"},{\"colorId\":185,\"hexString\":\"#d7d75f\",\"rgb\":{\"r\":215,\"g\":215,\"b\":95},\"hsl\":{\"h\":60,\"s\":60,\"l\":60},\"name\":\"Khaki3\"},{\"colorId\":186,\"hexString\":\"#d7d787\",\"rgb\":{\"r\":215,\"g\":215,\"b\":135},\"hsl\":{\"h\":60,\"s\":50,\"l\":68},\"name\":\"LightGoldenrod2\"},{\"colorId\":187,\"hexString\":\"#d7d7af\",\"rgb\":{\"r\":215,\"g\":215,\"b\":175},\"hsl\":{\"h\":60,\"s\":33,\"l\":76},\"name\":\"LightYellow3\"},{\"colorId\":188,\"hexString\":\"#d7d7d7\",\"rgb\":{\"r\":215,\"g\":215,\"b\":215},\"hsl\":{\"h\":0,\"s\":0,\"l\":84},\"name\":\"Grey84\"},{\"colorId\":189,\"hexString\":\"#d7d7ff\",\"rgb\":{\"r\":215,\"g\":215,\"b\":255},\"hsl\":{\"h\":240,\"s\":100,\"l\":92},\"name\":\"LightSteelBlue1\"},{\"colorId\":190,\"hexString\":\"#d7ff00\",\"rgb\":{\"r\":215,\"g\":255,\"b\":0},\"hsl\":{\"h\":69.4117647058823,\"s\":100,\"l\":50},\"name\":\"Yellow2\"},{\"colorId\":191,\"hexString\":\"#d7ff5f\",\"rgb\":{\"r\":215,\"g\":255,\"b\":95},\"hsl\":{\"h\":75,\"s\":100,\"l\":68},\"name\":\"DarkOliveGreen1\"},{\"colorId\":192,\"hexString\":\"#d7ff87\",\"rgb\":{\"r\":215,\"g\":255,\"b\":135},\"hsl\":{\"h\":80,\"s\":100,\"l\":76},\"name\":\"DarkOliveGreen1\"},{\"colorId\":193,\"hexString\":\"#d7ffaf\",\"rgb\":{\"r\":215,\"g\":255,\"b\":175},\"hsl\":{\"h\":90,\"s\":100,\"l\":84},\"name\":\"DarkSeaGreen1\"},{\"colorId\":194,\"hexString\":\"#d7ffd7\",\"rgb\":{\"r\":215,\"g\":255,\"b\":215},\"hsl\":{\"h\":120,\"s\":100,\"l\":92},\"name\":\"Honeydew2\"},{\"colorId\":195,\"hexString\":\"#d7ffff\",\"rgb\":{\"r\":215,\"g\":255,\"b\":255},\"hsl\":{\"h\":180,\"s\":100,\"l\":92},\"name\":\"LightCyan1\"},{\"colorId\":196,\"hexString\":\"#ff0000\",\"rgb\":{\"r\":255,\"g\":0,\"b\":0},\"hsl\":{\"h\":0,\"s\":100,\"l\":50},\"name\":\"Red1\"},{\"colorId\":197,\"hexString\":\"#ff005f\",\"rgb\":{\"r\":255,\"g\":0,\"b\":95},\"hsl\":{\"h\":337.647058823529,\"s\":100,\"l\":50},\"name\":\"DeepPink2\"},{\"colorId\":198,\"hexString\":\"#ff0087\",\"rgb\":{\"r\":255,\"g\":0,\"b\":135},\"hsl\":{\"h\":328.235294117647,\"s\":100,\"l\":50},\"name\":\"DeepPink1\"},{\"colorId\":199,\"hexString\":\"#ff00af\",\"rgb\":{\"r\":255,\"g\":0,\"b\":175},\"hsl\":{\"h\":318.823529411765,\"s\":100,\"l\":50},\"name\":\"DeepPink1\"},{\"colorId\":200,\"hexString\":\"#ff00d7\",\"rgb\":{\"r\":255,\"g\":0,\"b\":215},\"hsl\":{\"h\":309.411764705882,\"s\":100,\"l\":50},\"name\":\"Magenta2\"},{\"colorId\":201,\"hexString\":\"#ff00ff\",\"rgb\":{\"r\":255,\"g\":0,\"b\":255},\"hsl\":{\"h\":300,\"s\":100,\"l\":50},\"name\":\"Magenta1\"},{\"colorId\":202,\"hexString\":\"#ff5f00\",\"rgb\":{\"r\":255,\"g\":95,\"b\":0},\"hsl\":{\"h\":22.3529411764706,\"s\":100,\"l\":50},\"name\":\"OrangeRed1\"},{\"colorId\":203,\"hexString\":\"#ff5f5f\",\"rgb\":{\"r\":255,\"g\":95,\"b\":95},\"hsl\":{\"h\":0,\"s\":100,\"l\":68},\"name\":\"IndianRed1\"},{\"colorId\":204,\"hexString\":\"#ff5f87\",\"rgb\":{\"r\":255,\"g\":95,\"b\":135},\"hsl\":{\"h\":345,\"s\":100,\"l\":68},\"name\":\"IndianRed1\"},{\"colorId\":205,\"hexString\":\"#ff5faf\",\"rgb\":{\"r\":255,\"g\":95,\"b\":175},\"hsl\":{\"h\":330,\"s\":100,\"l\":68},\"name\":\"HotPink\"},{\"colorId\":206,\"hexString\":\"#ff5fd7\",\"rgb\":{\"r\":255,\"g\":95,\"b\":215},\"hsl\":{\"h\":315,\"s\":100,\"l\":68},\"name\":\"HotPink\"},{\"colorId\":207,\"hexString\":\"#ff5fff\",\"rgb\":{\"r\":255,\"g\":95,\"b\":255},\"hsl\":{\"h\":300,\"s\":100,\"l\":68},\"name\":\"MediumOrchid1\"},{\"colorId\":208,\"hexString\":\"#ff8700\",\"rgb\":{\"r\":255,\"g\":135,\"b\":0},\"hsl\":{\"h\":31.7647058823529,\"s\":100,\"l\":50},\"name\":\"DarkOrange\"},{\"colorId\":209,\"hexString\":\"#ff875f\",\"rgb\":{\"r\":255,\"g\":135,\"b\":95},\"hsl\":{\"h\":15,\"s\":100,\"l\":68},\"name\":\"Salmon1\"},{\"colorId\":210,\"hexString\":\"#ff8787\",\"rgb\":{\"r\":255,\"g\":135,\"b\":135},\"hsl\":{\"h\":0,\"s\":100,\"l\":76},\"name\":\"LightCoral\"},{\"colorId\":211,\"hexString\":\"#ff87af\",\"rgb\":{\"r\":255,\"g\":135,\"b\":175},\"hsl\":{\"h\":340,\"s\":100,\"l\":76},\"name\":\"PaleVioletRed1\"},{\"colorId\":212,\"hexString\":\"#ff87d7\",\"rgb\":{\"r\":255,\"g\":135,\"b\":215},\"hsl\":{\"h\":320,\"s\":100,\"l\":76},\"name\":\"Orchid2\"},{\"colorId\":213,\"hexString\":\"#ff87ff\",\"rgb\":{\"r\":255,\"g\":135,\"b\":255},\"hsl\":{\"h\":300,\"s\":100,\"l\":76},\"name\":\"Orchid1\"},{\"colorId\":214,\"hexString\":\"#ffaf00\",\"rgb\":{\"r\":255,\"g\":175,\"b\":0},\"hsl\":{\"h\":41.1764705882353,\"s\":100,\"l\":50},\"name\":\"Orange1\"},{\"colorId\":215,\"hexString\":\"#ffaf5f\",\"rgb\":{\"r\":255,\"g\":175,\"b\":95},\"hsl\":{\"h\":30,\"s\":100,\"l\":68},\"name\":\"SandyBrown\"},{\"colorId\":216,\"hexString\":\"#ffaf87\",\"rgb\":{\"r\":255,\"g\":175,\"b\":135},\"hsl\":{\"h\":20,\"s\":100,\"l\":76},\"name\":\"LightSalmon1\"},{\"colorId\":217,\"hexString\":\"#ffafaf\",\"rgb\":{\"r\":255,\"g\":175,\"b\":175},\"hsl\":{\"h\":0,\"s\":100,\"l\":84},\"name\":\"LightPink1\"},{\"colorId\":218,\"hexString\":\"#ffafd7\",\"rgb\":{\"r\":255,\"g\":175,\"b\":215},\"hsl\":{\"h\":330,\"s\":100,\"l\":84},\"name\":\"Pink1\"},{\"colorId\":219,\"hexString\":\"#ffafff\",\"rgb\":{\"r\":255,\"g\":175,\"b\":255},\"hsl\":{\"h\":300,\"s\":100,\"l\":84},\"name\":\"Plum1\"},{\"colorId\":220,\"hexString\":\"#ffd700\",\"rgb\":{\"r\":255,\"g\":215,\"b\":0},\"hsl\":{\"h\":50.5882352941176,\"s\":100,\"l\":50},\"name\":\"Gold1\"},{\"colorId\":221,\"hexString\":\"#ffd75f\",\"rgb\":{\"r\":255,\"g\":215,\"b\":95},\"hsl\":{\"h\":45,\"s\":100,\"l\":68},\"name\":\"LightGoldenrod2\"},{\"colorId\":222,\"hexString\":\"#ffd787\",\"rgb\":{\"r\":255,\"g\":215,\"b\":135},\"hsl\":{\"h\":40,\"s\":100,\"l\":76},\"name\":\"LightGoldenrod2\"},{\"colorId\":223,\"hexString\":\"#ffd7af\",\"rgb\":{\"r\":255,\"g\":215,\"b\":175},\"hsl\":{\"h\":30,\"s\":100,\"l\":84},\"name\":\"NavajoWhite1\"},{\"colorId\":224,\"hexString\":\"#ffd7d7\",\"rgb\":{\"r\":255,\"g\":215,\"b\":215},\"hsl\":{\"h\":0,\"s\":100,\"l\":92},\"name\":\"MistyRose1\"},{\"colorId\":225,\"hexString\":\"#ffd7ff\",\"rgb\":{\"r\":255,\"g\":215,\"b\":255},\"hsl\":{\"h\":300,\"s\":100,\"l\":92},\"name\":\"Thistle1\"},{\"colorId\":226,\"hexString\":\"#ffff00\",\"rgb\":{\"r\":255,\"g\":255,\"b\":0},\"hsl\":{\"h\":60,\"s\":100,\"l\":50},\"name\":\"Yellow1\"},{\"colorId\":227,\"hexString\":\"#ffff5f\",\"rgb\":{\"r\":255,\"g\":255,\"b\":95},\"hsl\":{\"h\":60,\"s\":100,\"l\":68},\"name\":\"LightGoldenrod1\"},{\"colorId\":228,\"hexString\":\"#ffff87\",\"rgb\":{\"r\":255,\"g\":255,\"b\":135},\"hsl\":{\"h\":60,\"s\":100,\"l\":76},\"name\":\"Khaki1\"},{\"colorId\":229,\"hexString\":\"#ffffaf\",\"rgb\":{\"r\":255,\"g\":255,\"b\":175},\"hsl\":{\"h\":60,\"s\":100,\"l\":84},\"name\":\"Wheat1\"},{\"colorId\":230,\"hexString\":\"#ffffd7\",\"rgb\":{\"r\":255,\"g\":255,\"b\":215},\"hsl\":{\"h\":60,\"s\":100,\"l\":92},\"name\":\"Cornsilk1\"},{\"colorId\":231,\"hexString\":\"#ffffff\",\"rgb\":{\"r\":255,\"g\":255,\"b\":255},\"hsl\":{\"h\":0,\"s\":0,\"l\":100},\"name\":\"Grey100\"},{\"colorId\":232,\"hexString\":\"#080808\",\"rgb\":{\"r\":8,\"g\":8,\"b\":8},\"hsl\":{\"h\":0,\"s\":0,\"l\":3},\"name\":\"Grey3\"},{\"colorId\":233,\"hexString\":\"#121212\",\"rgb\":{\"r\":18,\"g\":18,\"b\":18},\"hsl\":{\"h\":0,\"s\":0,\"l\":7},\"name\":\"Grey7\"},{\"colorId\":234,\"hexString\":\"#1c1c1c\",\"rgb\":{\"r\":28,\"g\":28,\"b\":28},\"hsl\":{\"h\":0,\"s\":0,\"l\":10},\"name\":\"Grey11\"},{\"colorId\":235,\"hexString\":\"#262626\",\"rgb\":{\"r\":38,\"g\":38,\"b\":38},\"hsl\":{\"h\":0,\"s\":0,\"l\":14},\"name\":\"Grey15\"},{\"colorId\":236,\"hexString\":\"#303030\",\"rgb\":{\"r\":48,\"g\":48,\"b\":48},\"hsl\":{\"h\":0,\"s\":0,\"l\":18},\"name\":\"Grey19\"},{\"colorId\":237,\"hexString\":\"#3a3a3a\",\"rgb\":{\"r\":58,\"g\":58,\"b\":58},\"hsl\":{\"h\":0,\"s\":0,\"l\":22},\"name\":\"Grey23\"},{\"colorId\":238,\"hexString\":\"#444444\",\"rgb\":{\"r\":68,\"g\":68,\"b\":68},\"hsl\":{\"h\":0,\"s\":0,\"l\":26},\"name\":\"Grey27\"},{\"colorId\":239,\"hexString\":\"#4e4e4e\",\"rgb\":{\"r\":78,\"g\":78,\"b\":78},\"hsl\":{\"h\":0,\"s\":0,\"l\":30},\"name\":\"Grey30\"},{\"colorId\":240,\"hexString\":\"#585858\",\"rgb\":{\"r\":88,\"g\":88,\"b\":88},\"hsl\":{\"h\":0,\"s\":0,\"l\":34},\"name\":\"Grey35\"},{\"colorId\":241,\"hexString\":\"#626262\",\"rgb\":{\"r\":98,\"g\":98,\"b\":98},\"hsl\":{\"h\":0,\"s\":0,\"l\":37},\"name\":\"Grey39\"},{\"colorId\":242,\"hexString\":\"#6c6c6c\",\"rgb\":{\"r\":108,\"g\":108,\"b\":108},\"hsl\":{\"h\":0,\"s\":0,\"l\":40},\"name\":\"Grey42\"},{\"colorId\":243,\"hexString\":\"#767676\",\"rgb\":{\"r\":118,\"g\":118,\"b\":118},\"hsl\":{\"h\":0,\"s\":0,\"l\":46},\"name\":\"Grey46\"},{\"colorId\":244,\"hexString\":\"#808080\",\"rgb\":{\"r\":128,\"g\":128,\"b\":128},\"hsl\":{\"h\":0,\"s\":0,\"l\":50},\"name\":\"Grey50\"},{\"colorId\":245,\"hexString\":\"#8a8a8a\",\"rgb\":{\"r\":138,\"g\":138,\"b\":138},\"hsl\":{\"h\":0,\"s\":0,\"l\":54},\"name\":\"Grey54\"},{\"colorId\":246,\"hexString\":\"#949494\",\"rgb\":{\"r\":148,\"g\":148,\"b\":148},\"hsl\":{\"h\":0,\"s\":0,\"l\":58},\"name\":\"Grey58\"},{\"colorId\":247,\"hexString\":\"#9e9e9e\",\"rgb\":{\"r\":158,\"g\":158,\"b\":158},\"hsl\":{\"h\":0,\"s\":0,\"l\":61},\"name\":\"Grey62\"},{\"colorId\":248,\"hexString\":\"#a8a8a8\",\"rgb\":{\"r\":168,\"g\":168,\"b\":168},\"hsl\":{\"h\":0,\"s\":0,\"l\":65},\"name\":\"Grey66\"},{\"colorId\":249,\"hexString\":\"#b2b2b2\",\"rgb\":{\"r\":178,\"g\":178,\"b\":178},\"hsl\":{\"h\":0,\"s\":0,\"l\":69},\"name\":\"Grey70\"},{\"colorId\":250,\"hexString\":\"#bcbcbc\",\"rgb\":{\"r\":188,\"g\":188,\"b\":188},\"hsl\":{\"h\":0,\"s\":0,\"l\":73},\"name\":\"Grey74\"},{\"colorId\":251,\"hexString\":\"#c6c6c6\",\"rgb\":{\"r\":198,\"g\":198,\"b\":198},\"hsl\":{\"h\":0,\"s\":0,\"l\":77},\"name\":\"Grey78\"},{\"colorId\":252,\"hexString\":\"#d0d0d0\",\"rgb\":{\"r\":208,\"g\":208,\"b\":208},\"hsl\":{\"h\":0,\"s\":0,\"l\":81},\"name\":\"Grey82\"},{\"colorId\":253,\"hexString\":\"#dadada\",\"rgb\":{\"r\":218,\"g\":218,\"b\":218},\"hsl\":{\"h\":0,\"s\":0,\"l\":85},\"name\":\"Grey85\"},{\"colorId\":254,\"hexString\":\"#e4e4e4\",\"rgb\":{\"r\":228,\"g\":228,\"b\":228},\"hsl\":{\"h\":0,\"s\":0,\"l\":89},\"name\":\"Grey89\"},{\"colorId\":255,\"hexString\":\"#eeeeee\",\"rgb\":{\"r\":238,\"g\":238,\"b\":238},\"hsl\":{\"h\":0,\"s\":0,\"l\":93},\"name\":\"Grey93\"}]"
  },
  {
    "path": "lib/panela/colors.py",
    "content": "import os\nimport json\n\nCOLORS_JSON = os.path.join(os.path.dirname(os.path.abspath(__file__)), \"colors.json\")\nCOLOR_TABLE = json.loads(open(COLORS_JSON, \"r\").read())\nVALID_COLORS = [x[\"hexString\"] for x in COLOR_TABLE]\nHEX_TO_ANSI = {x[\"hexString\"]: x[\"colorId\"] for x in COLOR_TABLE}\n\n\ndef rgb_from_str(s):\n    # s starts with a #.\n    r, g, b = int(s[1:3], 16), int(s[3:5], 16), int(s[5:7], 16)\n    return r, g, b\n\n\ndef find_nearest_color(hex_color):\n    R, G, B = rgb_from_str(hex_color)\n    mindiff = None\n    for d in VALID_COLORS:\n        r, g, b = rgb_from_str(d)\n        diff = abs(R - r) * 256 + abs(G - g) * 256 + abs(B - b) * 256\n        if mindiff is None or diff < mindiff:\n            mindiff = diff\n            mincolorname = d\n    return mincolorname\n"
  },
  {
    "path": "lib/panela/panela_colors.py",
    "content": "# vim: encoding=utf-8\n\nimport os\nimport sys\nimport colored\nimport itertools\nfrom globals import MYDIR\n\n\"\"\"\n\nAfter panela will be ready for it, it will be split out in a separate project,\nthat will be used for all chubin's console services.\nThere are several features that not yet implemented (see ___doc___ in Panela)\n\nTODO:\n    * html output\n    * png output\n\n\"\"\"\n\nfrom wcwidth import wcswidth\nfrom colors import find_nearest_color, HEX_TO_ANSI, rgb_from_str\nimport pyte\n\n# http://stackoverflow.com/questions/19782975/convert-rgb-color-to-the-nearest-color-in-palette-web-safe-color\n\ntry:\n    basestring  # Python 2\nexcept NameError:\n    basestring = str  # Python 3\n\n\ndef color_mapping(clr):\n    if clr == \"default\":\n        return None\n    return clr\n\n\nclass Point(object):\n    \"\"\"\n    One point (character) on a terminal\n    \"\"\"\n\n    def __init__(self, char=None, foreground=None, background=None):\n        self.foreground = foreground\n        self.background = background\n        self.char = char\n\n\nclass Panela:\n    \"\"\"\n    To implement:\n\n    Blocks manipulation:\n\n        [*] copy\n        [*] crop\n        [*] cut\n        [*] extend\n        [ ] join\n        [ ] move\n        [*] paste\n        [*] strip\n\n    Colors manipulation:\n\n        [*] paint           foreground/background\n        [*] paint_line\n        [ ] paint_svg\n        [ ] fill            background\n        [ ] fill_line\n        [ ] fill_svg\n        [ ] trans\n\n    Drawing:\n\n        [*] put_point\n        [*] put_line\n        [*] put_circle\n        [*] put_rectangle\n\n    Printing and reading:\n        ansi            reads vt100 sequence\n    \"\"\"\n\n    def __init__(self, x=80, y=25, panela=None, field=None):\n\n        if panela:\n            self.field = [x for x in panela.field]\n            self.size_x = panela.size_x\n            self.size_y = panela.size_y\n            return\n\n        if field:\n            self.field = field\n            self.size_x = len(field[0])\n            self.size_y = len(field)\n            return\n\n        self.field = [[Point() for _ in range(x)] for _ in range(y)]\n        self.size_x = x\n        self.size_y = y\n\n    def in_field(self, col, row):\n        if col < 0:\n            return False\n        if row < 0:\n            return False\n        if col >= self.size_x:\n            return False\n        if row >= self.size_y:\n            return False\n        return True\n\n    #\n    # Blocks manipulation\n    #\n\n    def copy(self, x1, y1, x2, y2):\n\n        if x1 < 0:\n            x1 += self.size_x\n        if x2 < 0:\n            x2 += self.size_x\n        if x1 > x2:\n            x1, x2 = x2, x1\n\n        if y1 < 0:\n            y1 += self.size_y\n        if y2 < 0:\n            y2 += self.size_y\n        if y1 > y2:\n            y1, y2 = y2, y1\n\n        field = [self.field[i] for i in range(y1, y2 + 1)]\n        field = [line[x1 : x2 + 1] for line in field]\n\n        return Panela(field=field)\n\n    def cut(self, x1, y1, x2, y2):\n        \"\"\" \"\"\"\n        if x1 < 0:\n            x1 += self.size_x\n        if x2 < 0:\n            x2 += self.size_x\n        if x1 > x2:\n            x1, x2 = x2, x1\n\n        if y1 < 0:\n            y1 += self.size_y\n        if y2 < 0:\n            y2 += self.size_y\n        if y1 > y2:\n            y1, y2 = y2, y1\n\n        copied = self.copy(x1, y1, x2, y2)\n\n        for y in range(y1, y2 + 1):\n            for x in range(x1, x2 + 1):\n                self.field[y][x] = Point()\n\n        return copied\n\n    def extend(self, cols=None, rows=None):\n        \"\"\"\n        Adds [cols] columns from the right\n        and [rows] rows from the bottom\n        \"\"\"\n        if cols and cols > 0:\n            self.field = [x + [Point() for _ in range(cols)] for x in self.field]\n            self.size_x += cols\n\n        if rows and rows > 0:\n            self.field = self.field + [\n                [Point() for _ in range(self.size_x)] for _ in range(rows)\n            ]\n            self.size_y += rows\n\n    def crop(self, left=None, right=None, top=None, bottom=None):\n        \"\"\"\n        Crop panela.\n        Remove <left>, <right> columns from left or right,\n        and <top> and <bottom> rows from top and bottom.\n        \"\"\"\n\n        if left:\n            if left >= self.size_x:\n                left = self.size_x\n            self.field = [x[left:] for x in self.field]\n            self.size_x -= left\n\n        if right:\n            if right >= self.size_x:\n                right = self.size_x\n            self.field = [x[:-right] for x in self.field]\n            self.size_x -= right\n\n        if top:\n            if top >= self.size_y:\n                top = self.size_y\n            self.field = self.field[top:]\n            self.size_y -= top\n\n        if bottom:\n            if bottom >= self.size_y:\n                bottom = self.size_y\n            self.field = self.field[:-bottom]\n            self.size_y -= bottom\n\n    def paste(self, panela, x1, y1, extend=False, transparence=False):\n        \"\"\"\n        Paste <panela> starting at <x1>, <y1>.\n        If <extend> is True current panela space will be automatically extended\n        If <transparence> is True, then <panela> is overlaid and characters behind them are seen\n        \"\"\"\n\n        # FIXME:\n        #  negative x1, y1\n        #  x1,y1 > size_x, size_y\n\n        if extend:\n            x_extend = 0\n            y_extend = 0\n            if x1 + panela.size_x > self.size_x:\n                x_extend = x1 + panela.size_x - self.size_x\n            if y1 + panela.size_y > self.size_y:\n                y_extend = y1 + panela.size_y - self.size_y\n            self.extend(cols=x_extend, rows=y_extend)\n\n        for i in range(y1, min(self.size_y, y1 + panela.size_y)):\n            for j in range(x1, min(self.size_x, x1 + panela.size_x)):\n                if transparence:\n                    if (\n                        panela.field[i - y1][j - x1].char\n                        and panela.field[i - y1][j - x1].char != \" \"\n                    ):\n                        if panela.field[i - y1][j - x1].foreground:\n                            self.field[i][j].foreground = panela.field[i - y1][\n                                j - x1\n                            ].foreground\n                        if panela.field[i - y1][j - x1].background:\n                            self.field[i][j].background = panela.field[i - y1][\n                                j - x1\n                            ].background\n                        self.field[i][j].char = panela.field[i - y1][j - x1].char\n                else:\n                    self.field[i][j] = panela.field[i - y1][j - x1]\n\n    def strip(self):\n        \"\"\"\n        Strip panela: remove empty spaces around panels rectangle\n        \"\"\"\n\n        def left_spaces(line):\n            answer = 0\n            for elem in line:\n                if not elem.char:\n                    answer += 1\n                else:\n                    break\n            return answer\n\n        def right_spaces(line):\n            return left_spaces(line[::-1])\n\n        def empty_line(line):\n            return left_spaces(line) == len(line)\n\n        left_space = []\n        right_space = []\n        for line in self.field:\n            left_space.append(left_spaces(line))\n            right_space.append(right_spaces(line))\n        left = min(left_space)\n        right = min(right_space)\n\n        top = 0\n        while top < self.size_y and empty_line(self.field[top]):\n            top += 1\n\n        bottom = 0\n        while bottom < self.size_y and empty_line(self.field[-(bottom + 1)]):\n            bottom += 1\n\n        self.crop(left=left, right=right, top=top, bottom=bottom)\n\n    #\n    # Drawing and painting\n    #\n\n    def put_point(self, col, row, char=None, color=None, background=None):\n        \"\"\"\n        Puts character with color and background color on the field.\n        Char can be a Point or a character.\n        \"\"\"\n\n        if not self.in_field(col, row):\n            return\n        if isinstance(char, Point):\n            self.field[row][col] = char\n        elif char is None:\n            if background:\n                self.field[row][col].background = background\n            if color:\n                self.field[row][col].foreground = color\n        else:\n            self.field[row][col] = Point(\n                char=char, foreground=color, background=background\n            )\n\n    def put_string(self, col, row, s=None, color=None, background=None):\n        \"\"\"\n        Put string <s> with foreground color <color> and background color <background>\n        ad <col>, <row>\n        \"\"\"\n        for i, c in enumerate(s):\n            self.put_point(col + i, row, c, color=color, background=background)\n\n    def put_line(self, x1, y1, x2, y2, char=None, color=None, background=None):\n        \"\"\"\n        Draw line (x1, y1) - (x2, y2) fill foreground color <color>, background color <background>\n        and character <char>, if specified.\n        \"\"\"\n\n        def get_line(start, end):\n            \"\"\"Bresenham's Line Algorithm\n            Produces a list of tuples from start and end\n\n            Source: http://www.roguebasin.com/index.php?title=Bresenham%27s_Line_Algorithm#Python\n\n            >>> points1 = get_line((0, 0), (3, 4))\n            >>> points2 = get_line((3, 4), (0, 0))\n            >>> assert(set(points1) == set(points2))\n            >>> print points1\n            [(0, 0), (1, 1), (1, 2), (2, 3), (3, 4)]\n            >>> print points2\n            [(3, 4), (2, 3), (1, 2), (1, 1), (0, 0)]\n            \"\"\"\n            # Setup initial conditions\n            x1, y1 = start\n            x2, y2 = end\n            dx = x2 - x1\n            dy = y2 - y1\n\n            # Determine how steep the line is\n            is_steep = abs(dy) > abs(dx)\n\n            # Rotate line\n            if is_steep:\n                x1, y1 = y1, x1\n                x2, y2 = y2, x2\n\n            # Swap start and end points if necessary and store swap state\n            swapped = False\n            if x1 > x2:\n                x1, x2 = x2, x1\n                y1, y2 = y2, y1\n                swapped = True\n\n            # Recalculate differentials\n            dx = x2 - x1\n            dy = y2 - y1\n\n            # Calculate error\n            error = int(dx / 2.0)\n            ystep = 1 if y1 < y2 else -1\n\n            # Iterate over bounding box generating points between start and end\n            y = y1\n            points = []\n            for x in range(x1, x2 + 1):\n                coord = (y, x) if is_steep else (x, y)\n                points.append(coord)\n                error -= abs(dy)\n                if error < 0:\n                    y += ystep\n                    error += dx\n\n            # Reverse the list if the coordinates were swapped\n            if swapped:\n                points.reverse()\n            return points\n\n        if color and not isinstance(color, basestring):\n            color_iter = itertools.cycle(color)\n        else:\n            color_iter = itertools.repeat(color)\n\n        if background and not isinstance(background, basestring):\n            background_iter = itertools.cycle(background)\n        else:\n            background_iter = itertools.repeat(background)\n\n        if char:\n            char_iter = itertools.cycle(char)\n        else:\n            char_iter = itertools.repeat(char)\n\n        for x, y in get_line((x1, y1), (x2, y2)):\n            char = next(char_iter)\n            color = next(color_iter)\n            background = next(background_iter)\n\n            self.put_point(x, y, char=char, color=color, background=background)\n\n    def paint(\n        self, x1, y1, x2, y2, c1, c2=None, bg1=None, bg2=None, angle=None, angle_bg=None\n    ):\n        \"\"\"\n        Paint rectangle (x1,y1) (x2,y2) with foreground color c1 and background bg1 if specified.\n        If specified colors c2/bg2, rectangle is painted with linear gradient (inclined under angle).\n        \"\"\"\n\n        def calculate_color(i, j):\n            if angle == None:\n                a = 0\n            else:\n                a = angle\n\n            r1, g1, b1 = rgb_from_str(c1)\n            r2, g2, b2 = rgb_from_str(c2)\n            k = 1.0 * (j - x1) / (x2 - x1) * (1 - a)\n            l = 1.0 * (i - y1) / (y2 - y1) * a\n            r3, g3, b3 = (\n                int(r1 + 1.0 * (r2 - r1) * (k + l)),\n                int(g1 + 1.0 * (g2 - g1) * (k + l)),\n                int(b1 + 1.0 * (b2 - b1) * (k + l)),\n            )\n\n            return \"#%02x%02x%02x\" % (r3, g3, b3)\n\n        def calculate_bg(i, j):\n            if angle_bg == None:\n                a = 0\n            else:\n                a = angle\n\n            r1, g1, b1 = rgb_from_str(bg1)\n            r2, g2, b2 = rgb_from_str(bg2)\n            k = 1.0 * (j - x1) / (x2 - x1) * (1 - a)\n            l = 1.0 * (i - y1) / (y2 - y1) * a\n            r3, g3, b3 = (\n                int(r1 + 1.0 * (r2 - r1) * (k + l)),\n                int(g1 + 1.0 * (g2 - g1) * (k + l)),\n                int(b1 + 1.0 * (b2 - b1) * (k + l)),\n            )\n\n            return \"#%02x%02x%02x\" % (r3, g3, b3)\n\n        if c2 == None:\n            for i in range(y1, y2):\n                for j in range(x1, x2):\n                    self.field[i][j].foreground = c1\n                    if bg1:\n                        if bg2:\n                            self.field[i][j].background = calculate_bg(i, j)\n                        else:\n                            self.field[i][j].background = bg1\n        else:\n            for i in range(y1, y2):\n                for j in range(x1, x2):\n                    self.field[i][j].foreground = calculate_color(i, j)\n                    if bg1:\n                        if bg2:\n                            self.field[i][j].background = calculate_bg(i, j)\n                        else:\n                            self.field[i][j].background = bg1\n\n        return self\n\n    def put_rectangle(\n        self, x1, y1, x2, y2, char=None, frame=None, color=None, background=None\n    ):\n        \"\"\"\n        Draw rectangle (x1,y1), (x2,y2) using <char> character, <color> and <background> color\n        \"\"\"\n\n        frame_chars = {\n            \"ascii\": \"++++-|\",\n            \"single\": \"┌┐└┘─│\",\n            \"double\": \"┌┐└┘─│\",\n        }\n        if frame in frame_chars:\n            chars = frame_chars[frame]\n        else:\n            chars = char * 6\n\n        for x in range(x1, x2):\n            self.put_point(x, y1, char=chars[4], color=color, background=background)\n            self.put_point(x, y2, char=chars[4], color=color, background=background)\n\n        for y in range(y1, y2):\n            self.put_point(x1, y, char=chars[5], color=color, background=background)\n            self.put_point(x2, y, char=chars[5], color=color, background=background)\n\n        self.put_point(x1, y1, char=chars[0], color=color, background=background)\n        self.put_point(x2, y1, char=chars[1], color=color, background=background)\n        self.put_point(x1, y2, char=chars[2], color=color, background=background)\n        self.put_point(x2, y2, char=chars[3], color=color, background=background)\n\n    def put_circle(self, x0, y0, radius, char=None, color=None, background=None):\n        \"\"\"\n        Draw cricle with center in (x, y) and radius r (x1,y1), (x2,y2)\n        using <char> character, <color> and <background> color\n        \"\"\"\n\n        def k(x):\n            return int(x * 1.9)\n\n        f = 1 - radius\n        ddf_x = 1\n        ddf_y = -2 * radius\n        x = 0\n        y = radius\n        self.put_point(x0, y0 + radius, char=char, color=color, background=background)\n        self.put_point(x0, y0 - radius, char=char, color=color, background=background)\n        self.put_point(\n            x0 + k(radius), y0, char=char, color=color, background=background\n        )\n        self.put_point(\n            x0 - k(radius), y0, char=char, color=color, background=background\n        )\n\n        char = \"x\"\n        while x < y:\n            if f >= 0:\n                y -= 1\n                ddf_y += 2\n                f += ddf_y\n            x += 1\n            ddf_x += 2\n            f += ddf_x\n            self.put_point(\n                x0 + k(x), y0 + y, char=char, color=color, background=background\n            )\n            self.put_point(\n                x0 - k(x), y0 + y, char=char, color=color, background=background\n            )\n            self.put_point(\n                x0 + k(x), y0 - y, char=char, color=color, background=background\n            )\n            self.put_point(\n                x0 - k(x), y0 - y, char=char, color=color, background=background\n            )\n            self.put_point(\n                x0 + k(y), y0 + x, char=char, color=color, background=background\n            )\n            self.put_point(\n                x0 - k(y), y0 + x, char=char, color=color, background=background\n            )\n            self.put_point(\n                x0 + k(y), y0 - x, char=char, color=color, background=background\n            )\n            self.put_point(\n                x0 - k(y), y0 - x, char=char, color=color, background=background\n            )\n\n    def read_ansi(self, seq, x=0, y=0, transparence=True):\n        \"\"\"\n        Read ANSI sequence and render it to the panela starting from x and y.\n        If transparence is True, replace spaces with \"\"\n        \"\"\"\n        screen = pyte.screens.Screen(self.size_x, self.size_y + 1)\n\n        stream = pyte.streams.ByteStream()\n        stream.attach(screen)\n\n        stream.feed(seq.replace(\"\\n\", \"\\r\\n\"))\n\n        for i, line in sorted(screen.buffer.items(), key=lambda x: x[0]):\n            for j, char in sorted(line.items(), key=lambda x: x[0]):\n                if j >= self.size_x:\n                    break\n                self.field[i][j] = Point(\n                    char.data, color_mapping(char.fg), color_mapping(char.bg)\n                )\n\n    def __str__(self):\n        answer = \"\"\n        skip_next = False\n        for i, line in enumerate(self.field):\n            for j, c in enumerate(line):\n                fg_ansi = \"\"\n                bg_ansi = \"\"\n                stop = \"\"\n\n                if self.field[i][j].foreground:\n                    fg_ansi = \"\\033[38;2;%s;%s;%sm\" % rgb_from_str(\n                        self.field[i][j].foreground\n                    )\n                    stop = colored.attr(\"reset\")\n\n                if self.field[i][j].background:\n                    bg_ansi = \"\\033[48;2;%s;%s;%sm\" % rgb_from_str(\n                        self.field[i][j].background\n                    )\n                    stop = colored.attr(\"reset\")\n\n                char = c.char or \" \"\n                if not skip_next:\n                    answer += fg_ansi + bg_ansi + char.encode(\"utf-8\") + stop\n                skip_next = wcswidth(char) == 2\n\n            # answer += \"...\\n\"\n            answer += \"\\n\"\n        return answer\n\n\n########################################################################################################\n\n\nclass Template(object):\n    def __init__(self):\n        self._mode = \"page\"\n        self.page = []\n        self.mask = []\n        self.code = []\n        self.panela = None\n\n        self._colors = {\n            \"A\": \"#00cc00\",\n            \"B\": \"#00cc00\",\n            \"C\": \"#00aacc\",\n            \"D\": \"#888888\",\n            \"E\": \"#cccc00\",\n            \"F\": \"#ff0000\",\n            \"H\": \"#22aa22\",\n            \"I\": \"#cc0000\",\n            \"J\": \"#000000\",\n        }\n\n        self._bg_colors = {\n            \"G\": \"#555555\",\n            \"J\": \"#555555\",\n        }\n\n    def _process_line(self, line):\n        if line == \"mask\":\n            self._mode = \"mask\"\n        if line == \"\":\n            self._mode = \"code\"\n\n    def read(self, filename):\n        \"\"\"\n        Read template from `filename`\n        \"\"\"\n        with open(filename) as f:\n            self._mode = \"page\"\n            for line in f.readlines():\n                line = line.rstrip(\"\\n\")\n                if line.startswith(\"==[\") and line.endswith(\"]==\"):\n                    self._process_line(line[3:-3].strip())\n                    continue\n\n                if self._mode == \"page\":\n                    self.page.append(line)\n                elif self._mode == \"mask\":\n                    self.mask.append(line)\n                elif self._mode == \"code\":\n                    self.mask.append(line)\n\n    def apply_mask(self):\n\n        lines = self.page\n        x_size = max([len(x) for x in lines])\n        y_size = len(lines)\n\n        self.panela = Panela(x=x_size, y=y_size)\n        self.panela.read_ansi(\"\".join(\"%s\\n\" % x for x in self.page))\n\n        for i, line in enumerate(self.mask):\n            for j, char in enumerate(line):\n                if char in self._colors or char in self._bg_colors:\n                    color = self._colors.get(char)\n                    bg_color = self._bg_colors.get(char)\n                    self.panela.put_point(j, i, color=color, background=bg_color)\n\n    def show(self):\n\n        if self.panela:\n            return str(self.panela)\n\n        return self.page\n\n\ndef main():\n    \"Only for experiments\"\n\n    pagepath = os.path.join(MYDIR, \"share/firstpage-v2.pnl\")\n    template = Template()\n    template.read(pagepath)\n    template.apply_mask()\n    sys.stdout.write(template.show())\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "lib/post.py",
    "content": "\"\"\"\nPOST requests processing.\nCurrently used only for new cheat sheets submission.\n\nConfiguration parameters:\n\n    path.spool\n\"\"\"\n\nimport string\nimport os\nimport random\nfrom config import CONFIG\n\n\ndef _save_cheatsheet(topic_name, cheatsheet):\n    \"\"\"\n    Save posted cheat sheet `cheatsheet` with `topic_name`\n    in the spool directory\n    \"\"\"\n\n    nonce = \"\".join(\n        random.choice(string.ascii_uppercase + string.digits) for _ in range(9)\n    )\n    filename = topic_name.replace(\"/\", \".\") + \".\" + nonce\n    filename = os.path.join(CONFIG[\"path.spool\"], filename)\n\n    open(filename, \"w\").write(cheatsheet)\n\n\ndef process_post_request(req, topic):\n    \"\"\"\n    Process POST request `req`.\n    \"\"\"\n    for key, val in req.form.items():\n        if key == \"\":\n            if topic is None:\n                topic_name = \"UNNAMED\"\n            else:\n                topic_name = topic\n            cheatsheet = val\n        else:\n            if val == \"\":\n                if topic is None:\n                    topic_name = \"UNNAMED\"\n                else:\n                    topic_name = topic\n                cheatsheet = key\n            else:\n                topic_name = key\n                cheatsheet = val\n\n        _save_cheatsheet(topic_name, cheatsheet)\n"
  },
  {
    "path": "lib/postprocessing.py",
    "content": "import search\nimport fmt.comments\n\n\ndef postprocess(answer, keyword, options, request_options=None):\n    answer = _answer_add_comments(answer, request_options=request_options)\n    answer = _answer_filter_by_keyword(\n        answer, keyword, options, request_options=request_options\n    )\n    return answer\n\n\ndef _answer_add_comments(answer, request_options=None):\n\n    if answer[\"format\"] != \"text+code\":\n        return answer\n\n    topic = answer[\"topic\"]\n    if \"filetype\" in answer:\n        filetype = answer[\"filetype\"]\n    else:\n        filetype = \"bash\"\n        if \"/\" in topic:\n            filetype = topic.split(\"/\", 1)[0]\n            if filetype.startswith(\"q:\"):\n                filetype = filetype[2:]\n\n    answer[\"answer\"] = fmt.comments.beautify(\n        answer[\"answer\"], filetype, request_options\n    )\n    answer[\"format\"] = \"code\"\n    answer[\"filetype\"] = filetype\n    return answer\n\n\ndef _answer_filter_by_keyword(answer, keyword, options, request_options=None):\n    answer[\"answer\"] = _filter_by_keyword(answer[\"answer\"], keyword, options)\n    return answer\n\n\ndef _filter_by_keyword(answer, keyword, options):\n\n    def _join_paragraphs(paragraphs):\n        answer = \"\\n\".join(paragraphs)\n        return answer\n\n    def _split_paragraphs(text):\n        answer = []\n        paragraph = \"\"\n        if isinstance(text, bytes):\n            text = text.decode(\"utf-8\")\n        for line in text.splitlines():\n            if line == \"\":\n                answer.append(paragraph)\n                paragraph = \"\"\n            else:\n                paragraph += line + \"\\n\"\n        answer.append(paragraph)\n        return answer\n\n    paragraphs = [\n        p\n        for p in _split_paragraphs(answer)\n        if search.match(p, keyword, options=options)\n    ]\n    if not paragraphs:\n        return \"\"\n\n    return _join_paragraphs(paragraphs)\n"
  },
  {
    "path": "lib/routing.py",
    "content": "\"\"\"\nQueries routing and caching.\n\nExports:\n\n    get_topics_list()\n    get_answers()\n\"\"\"\n\nimport random\nimport re\nfrom typing import Any, Dict, List\n\nimport cache\nimport adapter.cheat_sheets\nimport adapter.cmd\nimport adapter.internal\nimport adapter.latenz\nimport adapter.learnxiny\nimport adapter.question\nimport adapter.rosetta\nfrom config import CONFIG\n\n\nclass Router(object):\n    \"\"\"\n    Implementation of query routing. Routing is based on `routing_table`\n    and the data exported by the adapters (functions `get_list()` and `is_found()`).\n\n    `get_topics_list()` returns available topics (accessible at /:list).\n    `get_answer_dict()` return answer for the query.\n    \"\"\"\n\n    def __init__(self):\n\n        self._cached_topics_list = []\n        self._cached_topic_type = {}\n\n        adapter_class = adapter.all_adapters(as_dict=True)\n\n        active_adapters = set(CONFIG[\"adapters.active\"] + CONFIG[\"adapters.mandatory\"])\n\n        self._adapter = {\n            \"internal\": adapter.internal.InternalPages(\n                get_topic_type=self.get_topic_type, get_topics_list=self.get_topics_list\n            ),\n            \"unknown\": adapter.internal.UnknownPages(\n                get_topic_type=self.get_topic_type, get_topics_list=self.get_topics_list\n            ),\n        }\n\n        for by_name in active_adapters:\n            if by_name not in self._adapter:\n                self._adapter[by_name] = adapter_class[by_name]()\n\n        self._topic_list = {key: obj.get_list() for key, obj in self._adapter.items()}\n\n        self.routing_table = CONFIG[\"routing.main\"]\n        self.routing_table = (\n            CONFIG[\"routing.pre\"] + self.routing_table + CONFIG[\"routing.post\"]\n        )\n\n    def get_topics_list(self, skip_dirs=False, skip_internal=False):\n        \"\"\"\n        List of topics returned on /:list\n        \"\"\"\n\n        if self._cached_topics_list:\n            return self._cached_topics_list\n\n        skip = [\"fosdem\"]\n        if skip_dirs:\n            skip.append(\"cheat.sheets dir\")\n        if skip_internal:\n            skip.append(\"internal\")\n        sources_to_merge = [x for x in self._adapter if x not in skip]\n\n        answer = {}\n        for key in sources_to_merge:\n            answer.update({name: key for name in self._topic_list[key]})\n        answer = sorted(set(answer.keys()))\n\n        self._cached_topics_list = answer\n        return answer\n\n    def get_topic_type(self, topic: str) -> List[str]:\n        \"\"\"\n        Return list of topic types for `topic`\n        or [\"unknown\"] if topic can't be determined.\n        \"\"\"\n\n        def __get_topic_type(topic: str) -> List[str]:\n            result = []\n            for regexp, route in self.routing_table:\n                if re.search(regexp, topic):\n                    if route in self._adapter:\n                        if self._adapter[route].is_found(topic):\n                            result.append(route)\n                    else:\n                        result.append(route)\n            if not result:\n                return [CONFIG[\"routing.default\"]]\n\n            # cut the default route off, if there are more than one route found\n            if len(result) > 1:\n                return result[:-1]\n            return result\n\n        if topic not in self._cached_topic_type:\n            self._cached_topic_type[topic] = __get_topic_type(topic)\n        return self._cached_topic_type[topic]\n\n    def _get_page_dict(self, query, topic_type, request_options=None):\n        \"\"\"\n        Return answer_dict for the `query`.\n        \"\"\"\n        return self._adapter[topic_type].get_page_dict(\n            query, request_options=request_options\n        )\n\n    def handle_if_random_request(self, topic):\n        \"\"\"\n        Check if the `query` is a :random one,\n        if yes we check its correctness and then randomly select a topic,\n        based on the provided prefix.\n\n        \"\"\"\n\n        def __select_random_topic(prefix, topic_list):\n            # Here we remove the special cases\n            cleaned_topic_list = [\n                x for x in topic_list if \"/\" not in x and \":\" not in x\n            ]\n\n            # Here we still check that cleaned_topic_list in not empty\n            if not cleaned_topic_list:\n                return prefix\n\n            random_topic = random.choice(cleaned_topic_list)\n            return prefix + random_topic\n\n        if topic.endswith(\"/:random\") or topic.lstrip(\"/\") == \":random\":\n            # We strip the :random part and see if the query is valid by running a get_topics_list()\n            if topic.lstrip(\"/\") == \":random\":\n                topic = topic.lstrip(\"/\")\n            prefix = topic[:-7]\n\n            topic_list = [\n                x[len(prefix) :] for x in self.get_topics_list() if x.startswith(prefix)\n            ]\n\n            if \"\" in topic_list:\n                topic_list.remove(\"\")\n\n            if topic_list:\n                # This is a correct formatted random query like /cpp/:random as the topic_list is not empty.\n                random_topic = __select_random_topic(prefix, topic_list)\n                return random_topic\n            else:\n                # This is a wrongly formatted random query like /xyxyxy/:random as the topic_list is empty\n                # we just strip the /:random and let the already implemented logic handle it.\n                wrongly_formatted_random = topic[:-8]\n                return wrongly_formatted_random\n\n        # Here if not a random request, we just forward the topic\n        return topic\n\n    def get_answers(\n        self, topic: str, request_options: Dict[str, str] = None\n    ) -> List[Dict[str, Any]]:\n        \"\"\"\n        Find cheat sheets for the topic.\n\n        Args:\n            `topic` (str):    the name of the topic of the cheat sheet\n\n        Returns:\n            [answer_dict]:    list of answers (dictionaries)\n        \"\"\"\n\n        # if topic specified as <topic_type>:<topic>,\n        # cut <topic_type> off\n        topic_type = \"\"\n        if re.match(\"[^/]+:\", topic):\n            topic_type, topic = topic.split(\":\", 1)\n\n        topic = self.handle_if_random_request(topic)\n        topic_types = self.get_topic_type(topic)\n\n        # if topic_type is specified explicitly,\n        # show pages only of that type\n        if topic_type and topic_type in topic_types:\n            topic_types = [topic_type]\n\n        # 'question' queries are pretty expensive, that's why they should be handled\n        # in a special way:\n        # we do not drop the old style cache entries and try to reuse them if possible\n        if topic_types == [\"question\"]:\n            answer = cache.get(\"q:\" + topic)\n            if answer:\n                if isinstance(answer, dict):\n                    return [answer]\n                return [\n                    {\n                        \"topic\": topic,\n                        \"topic_type\": \"question\",\n                        \"answer\": answer,\n                        \"format\": \"text+code\",\n                    }\n                ]\n\n            answer = self._get_page_dict(\n                topic, topic_types[0], request_options=request_options\n            )\n            if answer.get(\"cache\", True):\n                cache.put(\"q:\" + topic, answer)\n            return [answer]\n\n        # Try to find cacheable queries in the cache.\n        # If answer was not found in the cache, resolve it in a normal way and save in the cache\n        answers = []\n        for topic_type in topic_types:\n\n            cache_entry_name = f\"{topic_type}:{topic}\"\n            cache_needed = self._adapter[topic_type].is_cache_needed()\n\n            if cache_needed:\n                answer = cache.get(cache_entry_name)\n                if not isinstance(answer, dict):\n                    answer = None\n                if answer:\n                    answers.append(answer)\n                    continue\n\n            answer = self._get_page_dict(\n                topic, topic_type, request_options=request_options\n            )\n            if isinstance(answer, dict):\n                if \"cache\" in answer:\n                    cache_needed = answer[\"cache\"]\n\n            if cache_needed and answer:\n                cache.put(cache_entry_name, answer)\n\n            answers.append(answer)\n\n        return answers\n\n\n# pylint: disable=invalid-name\n_ROUTER = Router()\nget_topics_list = _ROUTER.get_topics_list\nget_answers = _ROUTER.get_answers\n"
  },
  {
    "path": "lib/search.py",
    "content": "\"\"\"\nVery naive search implementation. Just a placeholder.\n\nExports:\n\n    find_answer_by_keyword()\n\nIt should be implemented on the adapter basis:\n\n    1. adapter.search(keyword) returns list of matching answers\n        * maybe with some initial weight\n    2. ranking is done\n    3. sorted results are returned\n    4. eage page are cut by keyword\n    5. results are paginated\n\nConfiguration parameters:\n\n    search.limit\n\"\"\"\n\nimport re\n\nfrom config import CONFIG\nfrom routing import get_answers, get_topics_list\n\n\ndef _limited_entry():\n    return {\n        \"topic_type\": \"LIMITED\",\n        \"topic\": \"LIMITED\",\n        \"answer\": \"LIMITED TO %s ANSWERS\" % CONFIG[\"search.limit\"],\n        \"format\": \"code\",\n    }\n\n\ndef _parse_options(options):\n    \"\"\"Parse search options string into optiond_dict\"\"\"\n\n    if options is None:\n        return {}\n\n    search_options = {\n        \"insensitive\": \"i\" in options,\n        \"word_boundaries\": \"b\" in options,\n        \"recursive\": \"r\" in options,\n    }\n    return search_options\n\n\ndef match(paragraph, keyword, options=None, options_dict=None):\n    \"\"\"Search for each keyword from `keywords` in `page`\n    and if all of them are found, return `True`.\n    Otherwise return `False`.\n\n    Several keywords can be joined together using ~\n    For example: ~ssh~passphrase\n    \"\"\"\n\n    if keyword is None:\n        return True\n\n    if \"~\" in keyword:\n        keywords = keyword.split(\"~\")\n    else:\n        keywords = [keyword]\n\n    if options_dict is None:\n        options_dict = _parse_options(options)\n\n    for kwrd in keywords:\n        if not kwrd:\n            continue\n\n        regex = re.escape(kwrd)\n        if options_dict[\"word_boundaries\"]:\n            regex = r\"\\b%s\\b\" % kwrd\n\n        if options_dict[\"insensitive\"]:\n            if not re.search(regex, paragraph, re.IGNORECASE):\n                return False\n        else:\n            if not re.search(regex, paragraph):\n                return False\n    return True\n\n\ndef find_answers_by_keyword(directory, keyword, options=\"\", request_options=None):\n    \"\"\"\n    Search in the whole tree of all cheatsheets or in its subtree `directory`\n    by `keyword`\n    \"\"\"\n\n    options_dict = _parse_options(options)\n\n    answers_found = []\n    for topic in get_topics_list(skip_internal=True, skip_dirs=True):\n\n        if not topic.startswith(directory):\n            continue\n\n        subtopic = topic[len(directory) :]\n        if not options_dict[\"recursive\"] and \"/\" in subtopic:\n            continue\n\n        answer_dicts = get_answers(topic, request_options=request_options)\n        for answer_dict in answer_dicts:\n            answer_text = answer_dict.get(\"answer\", \"\")\n            # Temporary hotfix:\n            # In some cases answer_text may be 'bytes' and not 'str'\n            if type(b\"\") == type(answer_text):\n                answer_text = answer_text.decode(\"utf-8\")\n\n            if match(answer_text, keyword, options_dict=options_dict):\n                answers_found.append(answer_dict)\n\n        if len(answers_found) > CONFIG[\"search.limit\"]:\n            answers_found.append(_limited_entry())\n            break\n\n    return answers_found\n"
  },
  {
    "path": "lib/standalone.py",
    "content": "\"\"\"\nStandalone wrapper for the cheat.sh server.\n\"\"\"\n\nfrom __future__ import print_function\n\nimport sys\nimport textwrap\n\ntry:\n    import urlparse\nexcept ModuleNotFoundError:\n    import urllib.parse as urlparse\n\nimport config\n\nconfig.CONFIG[\"cache.type\"] = \"none\"\n\nimport cheat_wrapper\nimport options\n\n\ndef show_usage():\n    \"\"\"\n    Show how to use the program in the standalone mode\n    \"\"\"\n\n    print(\n        textwrap.dedent(\n            \"\"\"\n        Usage:\n\n            lib/standalone.py [OPTIONS] QUERY\n\n        For OPTIONS see :help\n    \"\"\"\n        )[1:-1]\n    )\n\n\ndef parse_cmdline(args):\n    \"\"\"\n    Parses command line arguments and returns\n    query and request_options\n    \"\"\"\n\n    if not args:\n        show_usage()\n        sys.exit(0)\n\n    query_string = \" \".join(args)\n    parsed = urlparse.urlparse(\"https://srv:0/%s\" % query_string)\n    request_options = options.parse_args(\n        urlparse.parse_qs(parsed.query, keep_blank_values=True)\n    )\n\n    query = parsed.path.lstrip(\"/\")\n    if not query:\n        query = \":firstpage\"\n\n    return query, request_options\n\n\ndef main(args):\n    \"\"\"\n    standalone wrapper for cheat_wrapper()\n    \"\"\"\n\n    query, request_options = parse_cmdline(args)\n    answer, _ = cheat_wrapper.cheat_wrapper(query, request_options=request_options)\n    sys.stdout.write(answer)\n\n\nif __name__ == \"__main__\":\n    main(sys.argv[1:])\n"
  },
  {
    "path": "lib/stateful_queries.py",
    "content": "\"\"\"\nSupport for the stateful queries\n\"\"\"\n\nimport cache\n\n\ndef save_query(client_id, query):\n    \"\"\"\n    Save the last query `query` for the client `client_id`\n    \"\"\"\n    cache.put(\"l:%s\" % client_id, query)\n\n\ndef last_query(client_id):\n    \"\"\"\n    Return the last query for the client `client_id`\n    \"\"\"\n    return cache.get(\"l:%s\" % client_id)\n"
  },
  {
    "path": "requirements.txt",
    "content": "wheel\ngevent\nflask\nrequests\npygments\ndateutils\nfuzzywuzzy\nredis\ncolored<1.4.3\nlangdetect\ncffi\npolyglot\nPyICU\npycld2\ncolorama\npyyaml\npython-Levenshtein\npytest\nblack\n"
  },
  {
    "path": "share/adapters/chmod.grc",
    "content": "# with option -sI\n# e.g. grc curl -sI mysite.com\n# http\nregexp=^(HTTP).*\ncolours=yellow\n======\n# server\nregexp=^(Server).*\ncolours=cyan\n======\n# site\nregexp=^(Link).*\ncolours=magenta\n======\n# colouring the output of script 'cheat chmod'\n# e.g. grc curl -s cheat.sh/chmod/755\n# linux string\nregexp=^(Linux.*Permissions).*(String:)\\s+(.*)$\ncolours=yellow,green,red\n======\n# linux number\nregexp=^(Linux.*Permissions).*(Number:)\\s+(.*)$\ncolours=yellow,green,red\n======\n# header\nregexp=^(Special)\\s+(Owner)\\s+(Group)\\s+(Public)$\ncolours=white\n======\n# setuid\nregexp=^(Setuid)\\s+\\[.*\\].*(Read).*\ncolours=green,bold cyan\n======\n# setgid\nregexp=^(Setgid)\\s+\\[.*\\].*(Write).*\ncolours=green,bold yellow\n======\n# sticky bit\nregexp=^(Sticky bit)\\s+\\[.*\\].*(Execute).*\ncolours=green,bold magenta\n======\n"
  },
  {
    "path": "share/adapters/chmod.sh",
    "content": "#!/usr/bin/env bash\n\n# Contributed by Erez Binyamin (github.com/ErezBinyamin)\n\nGRC_STYLESHEET=\"${BASH_SOURCE[0]}\"; GRC_STYLESHEET=${GRC_STYLESHEET%.sh}.grc\n\n# Translate between chmod string and number\n# Inspired by http://permissions-calculator.org/\n# Contrib to chubin - cheat.sh\nchmod_calc(){\n  p_s=\"\"\n  p_n=\"\"\n  R=()\n  W=()\n  X=()\n  setuid=' '\n  setgid=' '\n  sticky=' '\n  # If permission number is given -> calc string\n  if [[ $1 =~ ^-?[0-9]+$ && ${#1} -ge 1 && ${#1} -le 4 ]]\n  then\n    p_n=$(printf \"%04s\\n\" \"$1\" | tr ' ' '0')\n    echo $p_n | grep -q '[8-9]' && return 1\n    for (( i=0; i<${#p_n}; i++ ))\n    do\n      num=$(echo \"obase=2;${p_n:$i:1}\" | bc | xargs printf '%03d')\n      # If 4 digit input -> process specials\n      if [ $i -eq 0 ]\n      then\n        [ ${num:0:1} -eq 1 ] && setuid='X' || setuid=' '\n        [ ${num:1:1} -eq 1 ] && setgid='X' || setgid=' '\n        [ ${num:2:1} -eq 1 ] && sticky='X' || sticky=' '\n      else\n        # Build p_s string\n        [ ${num:0:1} -eq 1 ] && p_s+='r' || p_s+='-'\n        [ ${num:1:1} -eq 1 ] && p_s+='w' || p_s+='-'\n        # Use sS or tT instead of x- according to specials\n        if [[ $i -eq 1 && $setuid == 'X' ]]\n        then\n          [ ${num:2:1} -eq 1 ] && p_s+='s' || p_s+='S'\n        elif [[ $i -eq 2 && $setgid == 'X' ]]\n        then\n          [ ${num:2:1} -eq 1 ] && p_s+='s' || p_s+='S'\n        elif [[ $i -eq 3 && $sticky == 'X' ]]\n        then\n          [ ${num:2:1} -eq 1 ] && p_s+='t' || p_s+='T'\n        else\n          [ ${num:2:1} -eq 1 ] && p_s+='x' || p_s+='-'\n        fi\n        # Populate arrays for the table\n        [ ${num:0:1} -eq 1 ] && R+=('X') || R+=(' ')\n        [ ${num:1:1} -eq 1 ] && W+=('X') || W+=(' ')\n        [ ${num:2:1} -eq 1 ] && X+=('X') || X+=(' ')\n      fi\n    done\n  # If permission string is given -> calc number\n  elif [[ $1 =~ ^[r,s,S,t,T,w,x,-]+$ ]]\n  then\n    # FULL STRING\n    if [[ ${#1} -eq 9 ]]\n    then\n      p_s=$1\n      num=0\n      # Process specials\n      [[ 'sS' =~ ${p_s:2:1} ]] && setuid='X' && num=$((num+4))\n      [[ 'sS' =~ ${p_s:5:1} ]] && setgid='X' && num=$((num+2))\n      [[ 'tT' =~ ${p_s:8:1} ]] && sticky='X' && num=$((num+1))\n      [ ${num} -gt 0 ] && p_n+=\"$num\"\n      # Calculate rest of p_n number while populating arrays for table\n      for (( i=0; i<${#p_s}; i+=0 ))\n      do\n        num=0\n        [[ \"r-\" =~ ${p_s:$i:1} ]] || return 1\n        [[ ${p_s:$i:1} == 'r' ]] && R+=('X') || R+=(' ')\n        [[ ${p_s:$((i++)):1} == 'r' ]] && let num++\n        num=$(( num << 1 ))\n        [[ \"w-\" =~ ${p_s:$i:1} ]] || return 1\n        [[ ${p_s:$i:1} == 'w' ]] && W+=('X') || W+=(' ')\n        [[ ${p_s:$((i++)):1} == 'w' ]] && let num++\n        num=$(( num << 1 ))\n        if [ $i -lt 6 ]\n        then\n          [[ \"sSx-\" =~ ${p_s:$i:1} ]] || return 1\n          [[ \"sx\" =~ ${p_s:$i:1} ]] && X+=('X') || X+=(' ')\n          [[ \"sx\" =~ ${p_s:$((i++)):1} ]] && let num++\n        else\n          [[ \"tTx-\" =~ ${p_s:$i:1} ]] || return 1\n          [[ \"tx\" =~ ${p_s:$i:1} ]] && X+=('X') || X+=(' ')\n          [[ \"tx\" =~ ${p_s:$((i++)):1} ]] && let num++\n        fi\n        p_n+=\"$num\"\n      done\n    # PARTIAL STRING\n    elif [[ $1 =~ ^[r,s,t,w,x]+$ ]]\n    then\n      p_s='---------'\n      p_n0=0\n      p_n1=0\n      p_n2=0\n      p_n3=0\n      R=(' ' ' ' ' ')\n      W=(' ' ' ' ' ')\n      X=(' ' ' ' ' ')\n      if [[ $1 =~ 'r' ]]\n      then\n        p_s=$(echo $p_s | sed 's/./r/1; s/./r/4; s/./r/7;')\n        let p_n1+=4\n        let p_n2+=4\n        let p_n3+=4\n        R=('X' 'X' 'X')\n      fi\n      if [[ $1 =~ 'w' ]]\n      then\n        p_s=$(echo $p_s | sed 's/./w/2')\n        let p_n1+=2\n        W=('X' ' ' ' ')\n      fi\n      if [[ $1 =~ 'x' ]]\n      then\n        p_s=$(echo $p_s | sed 's/./x/3; s/./x/6; s/./x/9;')\n        let p_n1+=1\n        let p_n2+=1\n        let p_n3+=1\n        X=('X' 'X' 'X')\n      fi\n      if [[ $1 =~ 's' ]]\n      then\n        [[ ${p_s:2:1} == 'x' ]] && p_s=$(echo $p_s | sed 's/./s/3') || p_s=$(echo $p_s | sed 's/./S/3')\n        [[ ${p_s:5:1} == 'x' ]] && p_s=$(echo $p_s | sed 's/./s/6') || p_s=$(echo $p_s | sed 's/./S/6')\n        let p_n0+=6\n        setuid='X'\n        setgid='X'\n      fi\n      if [[ $1 =~ 't' ]]\n      then\n        let p_n0+=1\n        [[ ${p_s:8:1} == 'x' ]] && p_s=$(echo $p_s | sed 's/./t/9') || p_s=$(echo $p_s | sed 's/./T/9')\n        sticky='X'\n      fi\n      p_n=\"${p_n0}${p_n1}${p_n2}${p_n3}\"\n    else\n      return 1\n    fi\n  else\n    return 1\n  fi\n  # Print Final results table\n  printf \"\nLinux Permissions String:\\t${p_s}\nLinux Permissions Number:\\t${p_n}\n\nSpecial\\t\\tOwner\\t\\tGroup\\t\\tPublic\n\nSetuid     [$setuid]\\tRead    [${R[0]}]\\tRead    [${R[1]}]\\tRead    [${R[2]}]\nSetgid     [$setgid]\\tWrite   [${W[0]}]\\tWrite   [${W[1]}]\\tWrite   [${W[2]}]\nSticky bit [$sticky]\\tExecute [${X[0]}]\\tExecute [${X[1]}]\\tExecute [${X[2]}]\n\n\" | grcat \"$GRC_STYLESHEET\"\n}\n\nchmod_calc $@\n[ $? -ne 0 ] && printf \"Invalid permissions string: $@\\n\"\n"
  },
  {
    "path": "share/adapters/oeis.sh",
    "content": "#!/usr/bin/env bash\n\n# Written by Erez Binyamin (github.com/ErezBinyamin)\n\n# Search for an integer sequence\n# USAGE:\n#\toeis <language> <sequence ID>\n#\toeis <sequence ID> <language>\n#\toeis <val_a, val_b, val_c, ...>\noeis() (\n  local URL='https://oeis.org/search?q='\n  local TMP=$(mktemp -d oeis.XXXXXXX)\n  local DOC=${TMP}/doc.html\n  local MAX_TERMS_LONG=30\n  local MAX_TERMS_SHORT=10\n  mkdir -p $TMP\n  rm -f ${TMP}/authors ${TMP}/bibliograpy ${TMP}/section $TMP/code_snippet\n  # -- MAIN --\n  # Search sequence by ID (optional language arg)\n  # \t. oeis <SEQ_ID>\n  # \t. oeis <SEQ_ID> <SECTION>\n  # \t. oeis <SECTION> <SEQ_ID>\n  isNum='^[0-9]+$'\n  # Search for specific sequence (and potentially language or :SECTION (list)\n  if [ $# -ge 1 ] \\\n     && [[ $(echo $1 | tr -d 'aA') =~ $isNum || $(echo $2 | tr -d 'aA') =~ $isNum ]] \\\n     && [[ ! $(echo $1 | tr -d 'aA') =~ $isNum || ! $(echo $2 | tr -d 'aA') =~ $isNum ]]\n  then\n    # Arg-Parse ID, Generate URL\n    if [[ $(echo $1 | tr -d 'aA') =~ $isNum ]]\n    then\n      ID=${1^^}\n      SECTION=$2\n    else\n      ID=${2^^}\n      SECTION=$1\n    fi\n    [[ ${ID:0:1} == 'A' ]] && ID=${ID:1}\n    ID=$(bc <<< \"$ID\")\n    ID=\"A$(printf '%06d' ${ID})\"\n    URL+=\"id:${ID}&fmt=text\"\n    curl $URL 2>/dev/null > $DOC\n    # :list available language code_snippets\n    if [[ ${SECTION^^} == ':LIST' || ${SECTION^^} == ':PROG' ]]\n    then\n      grep -q '%p' $DOC && echo 'maple' >> $TMP/section\n      grep -q '%t' $DOC && echo 'mathematica' >> $TMP/section\n      grep '%o' $DOC \\\n        | grep \"${ID} (\" \\\n        | sed \"s/^.*${ID} (//; s/).*//\" \\\n        | awk 'NF == 1' \\\n        >> $TMP/section\n      [[ -f $TMP/section && $(wc -c < $TMP/section) -ne 0 ]] \\\n        && cat ${TMP}/section | sort -u \\\n        || printf 'No code snippets available.\\n'\n      rm -rf $TMP\n      return 0\n    fi\n    # Print ID\n    printf \"ID: ${ID}\\n\"\n    # Print Description (%N)\n    grep '%N' $DOC | sed \"s/^.*${ID} //\"\n    printf '\\n'\n    # Print Sequence (Three sections %S %T and %U)\n    grep '%S' $DOC | sed \"s/^.*${ID} //\" | tr -d '\\n' > $TMP/seq\n    grep '%T' $DOC | sed \"s/^.*${ID} //\" | tr -d '\\n' >> $TMP/seq\n    grep '%U' $DOC | sed \"s/^.*${ID} //\" | tr -d '\\n' >> $TMP/seq\n    cat $TMP/seq \\\n      | cut -d ',' -f 1-${MAX_TERMS_LONG} \\\n      | sed 's/,/, /g; s/$/ .../'\n    # Generate code snippet (%p, %t, %o) (maple, mathematica, prog sections)\n    if [ $# -gt 1 ]\n    then\n      printf \"\\n\\n\"\n      # MAPLE section (%p)\n      if [[ ${SECTION^^} == 'MAPLE' ]] && grep -q '%p' $DOC\n      then\n        grep '%p' $DOC | sed \"s/^.*${ID} //\" > $TMP/code_snippet\n      # MATHEMATICA section (%t)\n      elif [[ ${SECTION^^} == 'MATHEMATICA' ]] && grep -q '%t' $DOC\n      then\n        grep '%t' $DOC | sed \"s/^.*${ID} //\" > $TMP/code_snippet\n      # PROG section (%o)\n      elif grep -qi '%o' $DOC && grep -qi $SECTION $DOC\n      then\n        # Print out code sample for specified language\n        grep '%o' $DOC \\\n          | sed \"s/%o ${ID} //\" \\\n          | awk -v tgt=\"${SECTION^^}\" -F'[()]' '{act=$2} sub(/^\\([^()]+\\) */,\"\"){f=(tgt==toupper(act))} f' \\\n          > ${TMP}/code_snippet\n      fi\n      # Print code snippet with 4-space indent to enable colorization\n      if [[ -f $TMP/code_snippet && $(wc -c < $TMP/code_snippet) -ne 0 ]]\n      then\n        # Get authors\n        grep -o ' _[A-Z].* [A-Z].*_, [A-Z].*[0-9]' ${TMP}/code_snippet \\\n          | sed 's/,.*//' \\\n          | sort -u \\\n          > ${TMP}/authors\n        i=1\n        # Replace authors with numbers\n        while read author\n        do\n          author=$(<<<\"$author\" sed 's/[]\\\\\\*\\(\\.[]/\\\\&/g')\n          sed -i \"s|${author}.*[0-9]|[${i}]|\" ${TMP}/code_snippet\n          author=$(echo $author | tr -d '_\\\\')\n          author_url='https://oeis.org/wiki/User:'\"$(echo ${author} | tr ' ' '_')\"\n          echo \"[${i}] [${author}] [${author_url}]\" \\\n           >> ${TMP}/bibliograpy\n          let i++\n        done <${TMP}/authors\n        # Print snippet\n        sed 's/^/   /' ${TMP}/code_snippet\n      else\n        printf \"${SECTION^^} unavailable. Use :list to view available languages.\\n\"\n      fi\n    fi\n  # Search unknown sequence\n  elif [ $# -gt 1 ] && ! echo $@ | grep -q -e [a-z] -e [A-Z]\n  then\n    # Build URL\n    URL+=\"signed:$(echo $@ | tr -sc '[:digit:]-' ',')&fmt=short\"\n    curl $URL 2>/dev/null > $DOC\n    # Sequence IDs\n    grep -o '\"/A[0-9][0-9][0-9][0-9][0-9][0-9]\">A[0-9][0-9][0-9][0-9][0-9][0-9]' $DOC \\\n      | sed 's/.*>//' \\\n      > $TMP/id\n    readarray -t ID < $TMP/id\n    # Descriptions\n    grep -A 1 '<td valign=top align=left>' $DOC \\\n      | sed '/--/d; s/<[^>]*>//g; /^\\s*$/d; s/^[ \\t]*//' \\\n      | sed 's/&nbsp;/ /g; s/\\&amp;/\\&/g; s/&gt;/>/g; s/&lt;/</g; s/&quot;/\"/g' \\\n      > $TMP/desc\n    readarray -t DESC < $TMP/desc\n    # Sequences\n    grep 'style=\"color:black;font-size:120%' $DOC \\\n      | sed 's/<[^>]*>//g; s/^[ \\t]*//' \\\n      | cut -d ',' -f 1-${MAX_TERMS_SHORT} \\\n      | sed 's/,/, /g; s/$/ .../' \\\n      > $TMP/seq\n    readarray -t SEQ < $TMP/seq\n    # Print all ID, DESC, SEQ\n    for i in ${!ID[@]}\n    do\n      printf \"${ID[$i]}: ${DESC[$i]}\\n\"\n      printf \"${SEQ[$i]}\\n\\n\"\n    done\n  else\n    printf \"\n# oeis\n#\n# The On-Line Encyclopedia of Integer Sequences (OEIS),\n# also cited simply as Sloane's, is an online database of integer sequences.\n\n# Find all possible OEIS sequences for some sequence (1,1,1,1...)\ncurl cheat.sh/oeis/1+1+1+1\n\n# Describe an OEIS sequence (A2)\ncurl cheat.sh/oeis/A2\n\n# Implementation of the A2 OEIS sequence in Python\ncurl cheat.sh/oeis/A2/python\n\n# List all available implementations of the A2 OEIS sequence\ncurl cheat.sh/oeis/A2/:list\n\"\n    rm -rf $TMP\n    return 1\n  fi\n  # Error statements\n  grep 'results, too many to show. Please refine your search.' $DOC | sed -e 's/<[^>]*>//g; s/^[ \\t]*//'\n  grep -o 'Sorry, but the terms do not match anything in the table.' $DOC\n  # print bibliography\n  printf \"\\n\\n\"\n  [ -f ${TMP}/bibliograpy ] && cat ${TMP}/bibliograpy\n  # Print URL for user\n  printf \"[${URL}]\\n\" \\\n    | rev \\\n    | sed 's/,//' \\\n    | rev \\\n    | sed 's/&.*/]/'\n  rm -rf $TMP\n  return 0\n)\n\noeis $@\n"
  },
  {
    "path": "share/adapters/rfc.sh",
    "content": "#!/usr/bin/env bash\n\n# Contributed by Erez Binyamin (github.com/ErezBinyamin)\n\n# Search for an RFC\n# Contrib to chubin - cheat.sh\nRFC_get()\n(\n  rfc_describe() {\n    sed -ne '/0001/,$p' ${RFC_INDEX} \\\n      | tr '\\n' '#' \\\n      | sed 's/##/\\n/g' \\\n      | sed 's/#    //g' \\\n      | grep -o '.*\\. ' \\\n      | sed -E 's/^(.*)(January|February|March|April|May|June|July|August|September|October|November|December) [[:digit:]]{4}(.*)$/\\1/'\n  }\n\n  UNAME=$(uname -s)\n  if [ \"$UNAME\" = \"Darwin\" ]; then\n    SED_I=\"sed -i ''\"\n  else\n    SED_I=\"sed -i\"\n  fi\n\n  mkdir -p /tmp/RFC_get\n  local WEB_RESP=\"/tmp/RFC_get/rfc_get_web_resp_${RANDOM}.html\"\n  local RFC_INDEX=\"/tmp/RFC_get/rfc_index.html\"\n  local isNum='^[0-9]+$'\n  # Update RFC_INDEX if file does not exist\n  [ -f ${RFC_INDEX} ] || curl 'https://www.ietf.org/download/rfc-index.txt' 2>/dev/null > ${RFC_INDEX}\n  local MIN_RFC=1\n  local MAX_RFC=$(sed '/^ / d' ${RFC_INDEX} | tail -n 1 | sed 's/ .*//')\n  \n  local arg_lower=$(echo \"$1\" | tr '[:upper:]' '[:lower:]')\n  \n  # Syntax check Usage statement\n  if [ $# -lt 1 ] || [ \"$arg_lower\" = \"-h\" ] || [ \"$arg_lower\" = \"--help\" ] || [ \"$arg_lower\" = \":help\" ] || [ \"$arg_lower\" = \":usage\" ]\n  then\n    printf \"\n    USAGE:\n      rfc <RFC_number>\t\tSearch RFC by number\n      rfc <Topic_string>\tSearch RFC by topic\n      rfc :list\t\t\tList available RFC's\n      rfc :usage\t\tShow this help message\n    \\n\"\n    return 0\n  fi\n  # Get corresponding RFC by number\n  if [[ ${1} =~ $isNum ]]\n  then\n    # Validate RFC range\n    if [ \"$1\" -gt $MAX_RFC ] || [ \"$1\" -lt $MIN_RFC ]\n    then\n      echo \"Valid RFC numbers: [ ${MIN_RFC} - ${MAX_RFC} ]\"\n      return 1\n    fi\n    # If valid N: Retrieve RFC <N>\n    curl \"https://www.ietf.org/rfc/rfc${1}.txt\" --write-out %{http_code} --silent --output ${WEB_RESP} 2>/dev/null | grep -q '200'\n    if [ $? -ne 0 ]\n    then\n      # Attempt to retrieve PDF link to RFC <N>\n      curl \"https://www.rfc-editor.org/info/rfc${1}\" --write-out %{http_code} --silent --output ${WEB_RESP} 2>/dev/null | grep -q '200'\n      # Webpage error code (Not 200 OK)\n      if [ $? -ne 0 ]\n      then\n        echo \"Error retrieving https://www.rfc-editor.org/info/rfc${1}\"\n        echo \"Please create github issue at https://github.com/chubin/cheat.sh/issues\"\n        return 2\n      # RFC never issued\n      elif grep -q '<h2>Not Issued</h2>' ${WEB_RESP}\n      then\n        echo \"RFC ${1} was never issued\"\n        return 0\n      # RFC does not exist\n      elif grep -q 'does not exist</h3>' ${WEB_RESP}\n      then\n        echo \"RFC ${1} does not exist\"\n        return 0\n      # RFC exists only as PDF\n      elif grep -q 'https.*\\.pdf' $WEB_RESP\n      then\n        grep -o 'https.*\\.pdf' $WEB_RESP\n        return 0\n      # Unknown error\n      else\n        echo \"Error retrieving RFC $1\"\n        echo \"Please create github issue at https://github.com/chubin/cheat.sh/issues\"\n        return 2\n      fi\n    fi\n  # Print list of available RFCs\n  elif [ \"$arg_lower\" = \":list\" ]\n  then\n    # Format RFC_INDEX to show short description of each RFC\n    rfc_describe \\\n      | grep -v 'Not Issued' \\\n      | sed 's/ .*//; s/^0*//'\n    return 0\n  # Print list of available RFCs\n  elif [ \"$arg_lower\" = \":describe\" ]\n  then\n    # Format RFC_INDEX to show short description of each RFC\n    rfc_describe\n    return 0\n  # Format list of RFCs related to keyword:   RFC_N  RFC_Title\n  else\n    ARG=\"$*\"\n    rfc_describe \\\n      | grep -i \"$ARG\" \\\n      > $WEB_RESP\n  fi\n  # Format nicely and print\n  $SED_I -e '/Page [0-9]/,+2d; /page [0-9]/,+2d' ${WEB_RESP}\n  if grep -q '<!DOCTYPE html>' ${WEB_RESP}\n  then\n    echo \"Error retrieving RFC $1\"\n    echo \"Please create github issue at https://github.com/chubin/cheat.sh/issues\"\n    return 2\n  else\n    cat -s ${WEB_RESP}\n    return 0\n  fi\n)\nRFC_get \"$1\"\n"
  },
  {
    "path": "share/ansi2html.sh",
    "content": "#!/bin/sh\n\n# Convert ANSI (terminal) colours and attributes to HTML\n\n# Licence: LGPLv2\n# Author:\n#    http://www.pixelbeat.org/docs/terminal_colours/\n# Examples:\n#    ls -l --color=always | ansi2html.sh > ls.html\n#    git show --color | ansi2html.sh > last_change.html\n#    Generally one can use the `script` util to capture full terminal output.\n# Changes:\n#    V0.1, 24 Apr 2008, Initial release\n#    V0.2, 01 Jan 2009, Phil Harnish <philharnish@gmail.com>\n#                         Support `git diff --color` output by\n#                         matching ANSI codes that specify only\n#                         bold or background colour.\n#                       P@draigBrady.com\n#                         Support `ls --color` output by stripping\n#                         redundant leading 0s from ANSI codes.\n#                         Support `grep --color=always` by stripping\n#                         unhandled ANSI codes (specifically ^[[K).\n#    V0.3, 20 Mar 2009, http://eexpress.blog.ubuntu.org.cn/\n#                         Remove cat -v usage which mangled non ascii input.\n#                         Cleanup regular expressions used.\n#                         Support other attributes like reverse, ...\n#                       P@draigBrady.com\n#                         Correctly nest <span> tags (even across lines).\n#                         Add a command line option to use a dark background.\n#                         Strip more terminal control codes.\n#    V0.4, 17 Sep 2009, P@draigBrady.com\n#                         Handle codes with combined attributes and color.\n#                         Handle isolated <bold> attributes with css.\n#                         Strip more terminal control codes.\n#    V0.23, 22 Dec 2015\n#      http://github.com/pixelb/scripts/commits/master/scripts/ansi2html.sh\n\ngawk --version >/dev/null || exit 1\n\nif [ \"$1\" = \"--version\" ]; then\n    printf '0.22\\n' && exit\nfi\n\nif [ \"$1\" = \"--help\" ]; then\n    printf '%s\\n' \\\n'This utility converts ANSI codes in data passed to stdin\nIt has 2 optional parameters:\n   --bg=dark --palette=linux|solarized|tango|xterm\nE.g.: ls -l --color=always | ansi2html.sh --bg=dark > ls.html' >&2\n    exit\nfi\n\n[ \"$1\" = \"--bg=dark\" ] && { dark_bg=yes; shift; }\n\nif [ \"$1\" = \"--palette=solarized\" ]; then\n   # See http://ethanschoonover.com/solarized\n   P0=073642;  P1=D30102;  P2=859900;  P3=B58900;\n   P4=268BD2;  P5=D33682;  P6=2AA198;  P7=EEE8D5;\n   P8=002B36;  P9=CB4B16; P10=586E75; P11=657B83;\n  P12=839496; P13=6C71C4; P14=93A1A1; P15=FDF6E3;\n  shift;\nelif [ \"$1\" = \"--palette=solarized-xterm\" ]; then\n   # Above mapped onto the xterm 256 color palette\n   P0=262626;  P1=AF0000;  P2=5F8700;  P3=AF8700;\n   P4=0087FF;  P5=AF005F;  P6=00AFAF;  P7=E4E4E4;\n   P8=1C1C1C;  P9=D75F00; P10=585858; P11=626262;\n  P12=808080; P13=5F5FAF; P14=8A8A8A; P15=FFFFD7;\n  shift;\nelif [ \"$1\" = \"--palette=tango\" ]; then\n   # Gnome default\n   P0=000000;  P1=CC0000;  P2=4E9A06;  P3=C4A000;\n   P4=3465A4;  P5=75507B;  P6=06989A;  P7=D3D7CF;\n   P8=555753;  P9=EF2929; P10=8AE234; P11=FCE94F;\n  P12=729FCF; P13=AD7FA8; P14=34E2E2; P15=EEEEEC;\n  shift;\nelif [ \"$1\" = \"--palette=xterm\" ]; then\n   P0=000000;  P1=CD0000;  P2=00CD00;  P3=CDCD00;\n   P4=0000EE;  P5=CD00CD;  P6=00CDCD;  P7=E5E5E5;\n   P8=7F7F7F;  P9=FF0000; P10=00FF00; P11=FFFF00;\n  P12=5C5CFF; P13=FF00FF; P14=00FFFF; P15=FFFFFF;\n  shift;\nelse # linux console\n   P0=000000;  P1=AA0000;  P2=00AA00;  P3=AA5500;\n   P4=0000AA;  P5=AA00AA;  P6=00AAAA;  P7=AAAAAA;\n   P8=555555;  P9=FF5555; P10=55FF55; P11=FFFF55;\n  P12=5555FF; P13=FF55FF; P14=55FFFF; P15=FFFFFF;\n  [ \"$1\" = \"--palette=linux\" ] && shift\nfi\n\n[ \"$1\" = \"--bg=dark\" ] && { dark_bg=yes; shift; }\n\n# Mac OSX's GNU sed is installed as gsed\n# use e.g. homebrew 'gnu-sed' to get it\nif ! sed --version >/dev/null 2>&1; then\n  if gsed --version >/dev/null 2>&1; then\n    alias sed=gsed\n  else\n    echo \"Error, can't find an acceptable GNU sed.\" >&2\n    exit 1\n  fi\nfi\n\nprintf '%s' \"<html>\n<head>\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=utf-8\\\"/>\n<link rel=\\\"search\\\" type=\\\"application/opensearchdescription+xml\\\" href=\\\"/files/opensearch.xml\\\" title=\\\"cheat.sh\\\" />\n<link rel=\\\"stylesheet\\\" type=\\\"text/css\\\" href=\\\"/files/style.css\\\" />\n<style type=\\\"text/css\\\">\n.ef0,.f0 { color: #$P0; } .eb0,.b0 { background-color: #$P0; }\n.ef1,.f1 { color: #$P1; } .eb1,.b1 { background-color: #$P1; }\n.ef2,.f2 { color: #$P2; } .eb2,.b2 { background-color: #$P2; }\n.ef3,.f3 { color: #$P3; } .eb3,.b3 { background-color: #$P3; }\n.ef4,.f4 { color: #$P4; } .eb4,.b4 { background-color: #$P4; }\n.ef5,.f5 { color: #$P5; } .eb5,.b5 { background-color: #$P5; }\n.ef6,.f6 { color: #$P6; } .eb6,.b6 { background-color: #$P6; }\n.ef7,.f7 { color: #$P7; } .eb7,.b7 { background-color: #$P7; }\n.ef8, .f0 > .bold,.bold > .f0 { color: #$P8; font-weight: normal; }\n.ef9, .f1 > .bold,.bold > .f1 { color: #$P9; font-weight: normal; }\n.ef10,.f2 > .bold,.bold > .f2 { color: #$P10; font-weight: normal; }\n.ef11,.f3 > .bold,.bold > .f3 { color: #$P11; font-weight: normal; }\n.ef12,.f4 > .bold,.bold > .f4 { color: #$P12; font-weight: normal; }\n.ef13,.f5 > .bold,.bold > .f5 { color: #$P13; font-weight: normal; }\n.ef14,.f6 > .bold,.bold > .f6 { color: #$P14; font-weight: normal; }\n.ef15,.f7 > .bold,.bold > .f7 { color: #$P15; font-weight: normal; }\n.eb8  { background-color: #$P8; }\n.eb9  { background-color: #$P9; }\n.eb10 { background-color: #$P10; }\n.eb11 { background-color: #$P11; }\n.eb12 { background-color: #$P12; }\n.eb13 { background-color: #$P13; }\n.eb14 { background-color: #$P14; }\n.eb15 { background-color: #$P15; }\n\"\n\n# The default xterm 256 colour palette\nfor red in 0 1 2 3 4 5 ; do\n  for green in 0 1 2 3 4 5 ; do\n    for blue in 0 1 2 3 4 5 ; do\n      c=$((16 + ($red * 36) + ($green * 6) + $blue))\n      r=$((($red * 40 + 55) * ($red > 0)))\n      g=$((($green * 40 + 55) * ($green > 0)))\n      b=$((($blue * 40 + 55) * ($blue > 0)))\n      printf \".ef%d { color: #%2.2x%2.2x%2.2x; } \" $c $r $g $b\n      printf \".eb%d { background-color: #%2.2x%2.2x%2.2x; }\\n\" $c $r $g $b\n    done\n  done\ndone\nfor gray in $(seq 0 23); do\n  c=$(($gray+232))\n  l=$(($gray*10 + 8))\n  printf \".ef%d { color: #%2.2x%2.2x%2.2x; } \" $c $l $l $l\n  printf \".eb%d { background-color: #%2.2x%2.2x%2.2x; }\\n\" $c $l $l $l\ndone\n\nprintf '%s' '\n.f9 { color: '`[ \"$dark_bg\" ] && printf \"#$P7;\" || printf \"#$P0;\"`' }\n.b9 { background-color: #'`[ \"$dark_bg\" ] && printf $P0 || printf $P15`'; }\n.f9 > .bold,.bold > .f9, body.f9 > pre > .bold {\n  /* Bold is heavy black on white, or bright white\n     depending on the default background */\n  color: '`[ \"$dark_bg\" ] && printf \"#$P15;\" || printf \"#$P0;\"`'\n  font-weight: '`[ \"$dark_bg\" ] && printf 'normal;' || printf 'bold;'`'\n}\n.reverse {\n  /* CSS does not support swapping fg and bg colours unfortunately,\n     so just hardcode something that will look OK on all backgrounds. */\n  '\"color: #$P0; background-color: #$P7;\"'\n}\n.underline { text-decoration: underline; }\n.line-through { text-decoration: line-through; }\n.blink { text-decoration: blink; }\n\n/* Avoid pixels between adjacent span elements.\n   Note this only works for lines less than 80 chars\n   where we close span elements on the same line.\nspan { display: inline-block; }\n*/\n</style>\n</head>\n\n<body class=\"\">\n<pre>\n'\n\np='\\x1b\\['        #shortcut to match escape codes\n\n# Handle various xterm control sequences.\n# See /usr/share/doc/xterm-*/ctlseqs.txt\nsed \"\n# escape ampersand and quote\ns#&#\\&amp;#g; s#\\\"#\\&quot;#g;\ns#\\x1b[^\\x1b]*\\x1b\\\\\\##g  # strip anything between \\e and ST\ns#\\x1b][0-9]*;[^\\a]*\\a##g # strip any OSC (xterm title etc.)\n\ns#\\r\\$## # strip trailing \\r\n\n# strip other non SGR escape sequences\ns#[\\x07]##g\ns#\\x1b[]>=\\][0-9;]*##g\ns#\\x1bP+.\\{5\\}##g\n# Mark cursor positioning codes \\\"Jr;c;\ns#${p}\\([0-9]\\{1,2\\}\\)G#\\\"J;\\1;#g\ns#${p}\\([0-9]\\{1,2\\}\\);\\([0-9]\\{1,2\\}\\)H#\\\"J\\1;\\2;#g\n\n# Mark clear as \\\"Cn where n=1 is screen and n=0 is to end-of-line\ns#${p}H#\\\"C1;#g\ns#${p}K#\\\"C0;#g\n# Mark Cursor move columns as \\\"Mn where n is +ve for right, -ve for left\ns#${p}C#\\\"M1;#g\ns#${p}\\([0-9]\\{1,\\}\\)C#\\\"M\\1;#g\ns#${p}\\([0-9]\\{1,\\}\\)D#\\\"M-\\1;#g\ns#${p}\\([0-9]\\{1,\\}\\)P#\\\"X\\1;#g\n\ns#${p}[0-9;?]*[^0-9;?m]##g\n\n\" |\n\n# Normalize the input before transformation\nsed \"\n# escape HTML (ampersand and quote done above)\ns#>#\\&gt;#g; s#<#\\&lt;#g;\n\n# normalize SGR codes a little\n\n# split 256 colors out and mark so that they're not\n# recognised by the following 'split combined' line\n:e\ns#${p}\\([0-9;]\\{1,\\}\\);\\([34]8;5;[0-9]\\{1,3\\}\\)m#${p}\\1m${p}¬\\2m#g; t e\ns#${p}\\([34]8;5;[0-9]\\{1,3\\}\\)m#${p}¬\\1m#g;\n\n:c\ns#${p}\\([0-9]\\{1,\\}\\);\\([0-9;]\\{1,\\}\\)m#${p}\\1m${p}\\2m#g; t c   # split combined\ns#${p}0\\([0-7]\\)#${p}\\1#g                                 #strip leading 0\ns#${p}1m\\(\\(${p}[4579]m\\)*\\)#\\1${p}1m#g                   #bold last (with clr)\ns#${p}m#${p}0m#g                                          #add leading 0 to norm\n\n# undo any 256 color marking\ns#${p}¬\\([34]8;5;[0-9]\\{1,3\\}\\)m#${p}\\1m#g;\n\n# map 16 color codes to color + bold\ns#${p}9\\([0-7]\\)m#${p}3\\1m${p}1m#g;\ns#${p}10\\([0-7]\\)m#${p}4\\1m${p}1m#g;\n\n# change 'reset' code to \\\"R\ns#${p}0m#\\\"R;#g\n\" |\n\n# Convert SGR sequences to HTML\nsed \"\n# common combinations to minimise html (optional)\n:f\ns#${p}3[0-7]m${p}3\\([0-7]\\)m#${p}3\\1m#g; t f\n:b\ns#${p}4[0-7]m${p}4\\([0-7]\\)m#${p}4\\1m#g; t b\ns#${p}3\\([0-7]\\)m${p}4\\([0-7]\\)m#<span class=\\\"f\\1 b\\2\\\">#g\ns#${p}4\\([0-7]\\)m${p}3\\([0-7]\\)m#<span class=\\\"f\\2 b\\1\\\">#g\n\ns#${p}1m#<span class=\\\"bold\\\">#g\ns#${p}4m#<span class=\\\"underline\\\">#g\ns#${p}5m#<span class=\\\"blink\\\">#g\ns#${p}7m#<span class=\\\"reverse\\\">#g\ns#${p}9m#<span class=\\\"line-through\\\">#g\ns#${p}3\\([0-9]\\)m#<span class=\\\"f\\1\\\">#g\ns#${p}4\\([0-9]\\)m#<span class=\\\"b\\1\\\">#g\n\ns#${p}38;5;\\([0-9]\\{1,3\\}\\)m#<span class=\\\"ef\\1\\\">#g\ns#${p}48;5;\\([0-9]\\{1,3\\}\\)m#<span class=\\\"eb\\1\\\">#g\n\ns#${p}[0-9;]*m##g # strip unhandled codes\n\" |\n\n# Convert alternative character set and handle cursor movement codes\n# Note we convert here, as if we do at start we have to worry about avoiding\n# conversion of SGR codes etc., whereas doing here we only have to\n# avoid conversions of stuff between &...; or <...>\n#\n# Note we could use sed to do this based around:\n#   sed 'y/abcdefghijklmnopqrstuvwxyz{}`~/▒␉␌␍␊°±␤␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π£◆·/'\n# However that would be very awkward as we need to only conv some input.\n# The basic scheme that we do in the awk script below is:\n#  1. enable transliterate once \"T1; is seen\n#  2. disable once \"T0; is seen (may be on diff line)\n#  3. never transliterate between &; or <> chars\n#  4. track x,y movements and active display mode at each position\n#  5. buffer line/screen and dump when required\nsed \"\n# change 'smacs' and 'rmacs' to \\\"T1 and \\\"T0 to simplify matching.\ns#\\x1b(0#\\\"T1;#g;\ns#\\x0E#\\\"T1;#g;\n\ns#\\x1b(B#\\\"T0;#g\ns#\\x0F#\\\"T0;#g\n\" |\n(\ngawk '\nfunction dump_line(l,del,c,blanks,ret) {\n  for(c=1;c<maxX;c++) {\n    if ((c SUBSEP l) in attr || length(cur)) {\n      ret = ret blanks fixas(cur,attr[c,l])\n      if(del) delete attr[c,l]\n      blanks=\"\"\n    }\n    if ((c SUBSEP l) in dump) {\n      ret=ret blanks dump[c,l]\n      if(del) delete dump[c,l]\n      blanks=\"\"\n    } else blanks=blanks \" \"\n  }\n  if(length(cur)) ret=ret blanks\n  return ret\n}\n\nfunction dump_screen(l,ret) {\n  for(l=1;l<=maxY;l++)\n    ret=ret dump_line(l,0) \"\\n\"\n  return ret fixas(cur, \"\")\n}\n\nfunction atos(a,i,ret) {\n  for(i=1;i<=length(a);i++) if(i in a) ret=ret a[i]\n  return ret\n}\n\nfunction fixas(a,s,spc,i,attr,rm,ret) {\n  spc=length(a)\n  l=split(s,attr,\">\")\n  for(i=1;i<=spc;i++) {\n    rm=rm?rm:(a[i]!=attr[i]\">\")\n    if(rm) {\n      ret=ret \"</span>\"\n      delete a[i];\n    }\n  }\n  for(i=1;i<l;i++) {\n    attr[i]=attr[i]\">\"\n    if(a[i]!=attr[i]) {\n      a[i]=attr[i]\n      ret = ret attr[i]\n    }\n  }\n  return ret\n}\n\nfunction encode(string,start,end,i,ret,pos,sc,buf) {\n   if(!end) end=length(string);\n   if(!start) start=1;\n   state=3\n   for(i=1;i<=length(string);i++) {\n     c=substr(string,i,1)\n     if(state==2) {\n       sc=sc c\n       if(c==\";\") {\n          c=sc\n          state=last_mode\n       } else continue\n     } else {\n       if(c==\"\\r\") { x=1; continue }\n       if(c==\"<\") {\n         # Change attributes - store current active\n         # attributes in span array\n         split(substr(string,i),cord,\">\");\n         i+=length(cord[1])\n         span[++spc]=cord[1] \">\"\n         continue\n       }\n       else if(c==\"&\") {\n         # All goes to single position till we see a semicolon\n         sc=c\n         state=2\n         continue\n       }\n       else if(c==\"\\b\") {\n          # backspace move insertion point back 1\n          if(spc) attr[x,y]=atos(span)\n          x=x>1?x-1:1\n          continue\n       }\n       else if(c==\"\\\"\") {\n          split(substr(string,i+2),cord,\";\")\n          cc=substr(string,i+1,1);\n          if(cc==\"T\") {\n              # Transliterate on/off\n              if(cord[1]==1&&state==3) last_mode=state=4\n              if(cord[1]==0&&state==4) last_mode=state=3\n          }\n          else if(cc==\"C\") {\n              # Clear\n              if(cord[1]+0) {\n                # Screen - if Recording dump screen\n                if(dumpStatus==dsActive) ret=ret dump_screen()\n                dumpStatus=dsActive\n                delete dump\n                delete attr\n                x=y=1\n              } else {\n                # To end of line\n                for(pos=x;pos<maxX;pos++) {\n                  dump[pos,y]=\" \"\n                  if (!spc) delete attr[pos,y]\n                  else attr[pos,y]=atos(span)\n                }\n              }\n          }\n          else if(cc==\"J\") {\n              # Jump to x,y\n              i+=length(cord[2])+1\n              # If line is higher - dump previous screen\n              if(dumpStatus==dsActive&&cord[1]<y) {\n                ret=ret dump_screen();\n                dumpStatus=dsNew;\n              }\n              x=cord[2]\n              if(length(cord[1]) && y!=cord[1]){\n                y=cord[1]\n                if(y>maxY) maxY=y\n                # Change y - start recording\n                dumpStatus=dumpStatus?dumpStatus:dsReset\n              }\n          }\n          else if(cc==\"M\") {\n              # Move left/right on current line\n              x+=cord[1]\n          }\n          else if(cc==\"X\") {\n              # delete on right\n              for(pos=x;pos<=maxX;pos++) {\n                nx=pos+cord[1]\n                if(nx<maxX) {\n                  if((nx SUBSEP y) in attr) attr[pos,y] = attr[nx,y]\n                  else delete attr[pos,y]\n                  if((nx SUBSEP y) in dump) dump[pos,y] = dump[nx,y]\n                  else delete dump[pos,y]\n                } else if(spc) {\n                  attr[pos,y]=atos(span)\n                  dump[pos,y]=\" \"\n                }\n              }\n          }\n          else if(cc==\"R\") {\n              # Reset attributes\n              while(spc) delete span[spc--]\n          }\n          i+=length(cord[1])+2\n          continue\n       }\n       else if(state==4&&i>=start&&i<=end&&c in Trans) c=Trans[c]\n     }\n     if(dumpStatus==dsReset) {\n       delete dump\n       delete attr\n       ret=ret\"\\n\"\n       dumpStatus=dsActive\n     }\n     if(dumpStatus==dsNew) {\n       # After moving/clearing we are now ready to write\n       # something to the screen so start recording now\n       ret=ret\"\\n\"\n       dumpStatus=dsActive\n     }\n     if(dumpStatus==dsActive||dumpStatus==dsOff) {\n       dump[x,y] = c\n       if(!spc) delete attr[x,y]\n       else attr[x,y] = atos(span)\n       if(++x>maxX) maxX=x;\n     }\n    }\n    # End of line if dumping increment y and set x back to first col\n    x=1\n    if(!dumpStatus) return ret dump_line(y,1);\n    else if(++y>maxY) maxY=y;\n    return ret\n}\nBEGIN{\n  OFS=FS\n  # dump screen status\n  dsOff=0    # Not dumping screen contents just write output direct\n  dsNew=1    # Just after move/clear waiting for activity to start recording\n  dsReset=2  # Screen cleared build new empty buffer and record\n  dsActive=3 # Currently recording\n  F=\"abcdefghijklmnopqrstuvwxyz{}`~\"\n  T=\"▒␉␌␍␊°±␤␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π£◆·\"\n  maxX=80\n  delete cur;\n  x=y=1\n  for(i=1;i<=length(F);i++)Trans[substr(F,i,1)]=substr(T,i,1);\n}\n\n{ $0=encode($0) }\n1\nEND {\n  if(dumpStatus) {\n    print dump_screen();\n  }\n}'\n)\n\nprintf '</pre>\n</body>\n</html>\\n'\n"
  },
  {
    "path": "share/bash_completion.txt",
    "content": "_cht_complete()\n{\n    local cur prev opts\n    _get_comp_words_by_ref -n : cur\n\n    COMPREPLY=()\n    cur=\"${COMP_WORDS[COMP_CWORD]}\"\n    prev=\"${COMP_WORDS[COMP_CWORD-1]}\"\n    opts=\"$(curl -s cheat.sh/:list)\"\n\n    if [ ${COMP_CWORD} = 1 ]; then\n\t  COMPREPLY=( $(compgen -W \"${opts}\" -- ${cur}) )\n\t  __ltrim_colon_completions \"$cur\"\n    fi\n    return 0\n}\ncomplete -F _cht_complete cht.sh\n"
  },
  {
    "path": "share/cht.sh.txt",
    "content": "#!/bin/bash\n# shellcheck disable=SC1117,SC2001\n#\n# [X] open section\n# [X] one shot mode\n# [X] usage info\n# [X] dependencies check\n# [X] help\n# [X] yank/y/copy/c\n# [X] Y/C\n# [X] eof problem\n# [X] more\n# [X] stealth mode\n#\n# here are several examples for the stealth mode:\n#\n# zip lists\n# list permutation\n# random list element\n# reverse a list\n# read json from file\n# append string to a file\n# run process in background\n# count words in text counter\n# group elements list\n\n__CHTSH_VERSION=0.0.4\n__CHTSH_DATETIME=\"2021-04-25 12:30:30 +0200\"\n\n# cht.sh configuration loading\n#\n# configuration is stored in ~/.cht.sh/ (can be overridden with CHTSH env var.)\n#\nCHTSH_HOME=${CHTSH:-\"$HOME\"/.cht.sh}\n[ -z \"$CHTSH_CONF\" ] && CHTSH_CONF=$CHTSH_HOME/cht.sh.conf\n# shellcheck disable=SC1090,SC2002\n[ -e \"$CHTSH_CONF\" ] && source \"$CHTSH_CONF\"\n[ -z \"$CHTSH_URL\" ] && CHTSH_URL=https://cht.sh\n\n# currently we support only two modes:\n# * lite = access the server using curl\n# * auto = try standalone usage first\nCHTSH_MODE=\"$(cat \"$CHTSH_HOME\"/mode 2> /dev/null)\"\n[ \"$CHTSH_MODE\" != lite ] && CHTSH_MODE=auto\nCHEATSH_INSTALLATION=\"$(cat \"$CHTSH_HOME/standalone\" 2> /dev/null)\"\n\n\nexport LESSSECURE=1\nSTEALTH_MAX_SELECTION_LENGTH=5\n\ncase \"$(uname -s)\" in\n  Darwin) is_macos=yes ;;\n  *) is_macos=no ;;\nesac\n\n# for KSH93\n# shellcheck disable=SC2034,SC2039,SC2168\nif echo \"$KSH_VERSION\" | grep -q ' 93' && ! local foo 2>/dev/null; then\n  alias local=typeset\nfi\n\nfatal()\n{\n  echo \"ERROR: $*\" >&2\n  exit 1\n}\n\n_say_what_i_do()\n{\n  [ -n \"$LOG\" ] && echo \"$(date '+[%Y-%m-%d %H:%M%S]') $*\" >> \"$LOG\"\n\n  local this_prompt=\"\\033[0;1;4;32m>>\\033[0m\"\n  printf \"\\n${this_prompt}%s\\033[0m\\n\" \" $* \"\n}\n\ncheatsh_standalone_install()\n{\n  # the function installs cheat.sh with the upstream repositories\n  # in the standalone mode\n  local installdir; installdir=\"$1\"\n  local default_installdir=\"$HOME/.cheat.sh\"\n\n  [ -z \"$installdir\" ] && installdir=${default_installdir}\n\n  if [ \"$installdir\" = help ]; then\n    cat <<EOF\nInstall cheat.sh in the standalone mode.\n\nAfter the installation, cheat.sh can be used locally, without accessing\nthe public cheat.sh service, or it can be used in the server mode,\nwhere the newly installed server could be accessed by external clients\nin the same fashion as the public cheat.sh server.\n\nDuring the installation, cheat.sh code as well as the cheat.sh upstream\ncheat sheets repositories will be fetched.\n\nIt takes approximately 1G of the disk space.\n\nDefault installation location:  ~/.cheat.sh/\nIt can be overridden by a command line parameter to this script:\n\n    ${0##*/} --standalone-install DIR\n\nSee cheat.sh/:standalone or https://github.com/chubin/cheat.sh/README.md\nfor more information:\n\n    cht.sh :standalone\n    curl cheat.sh/:standalone\n\nAfter the installation is finished, the cht.sh shell client is switched\nto the auto mode, where it uses the local cheat.sh installation if possible.\nYou can switch the mode with the --mode switch:\n\n    cht.sh --mode lite      # use https://cheat.sh/ only\n    cht.sh --mode auto      # use local installation\n\nFor installation and standalone usage, you need \\`git\\`, \\`python\\`,\nand \\`virtualenv\\` to be installed locally.\nEOF\n    return\n  fi\n\n  local _exit_code=0\n\n  local dependencies=(python git virtualenv)\n  for dep in \"${dependencies[@]}\"; do\n    command -v \"$dep\" >/dev/null || \\\n    { echo \"DEPENDENCY: \\\"$dep\\\" is needed to install cheat.sh in the standalone mode\" >&2; _exit_code=1; }\n  done\n  [ \"$_exit_code\" -ne 0 ] && return \"$_exit_code\"\n\n  while true; do\n    local _installdir\n    echo -n \"Where should cheat.sh be installed [$installdir]? \"; read -r _installdir\n    [ -n \"$_installdir\" ] && installdir=$_installdir\n\n    if [ \"$installdir\" = y ] \\\n        || [ \"$installdir\" = Y ] \\\n        || [ \"$(echo \"$installdir\" | tr \"[:upper:]\" \"[:lower:]\")\" = yes ]\n    then\n      echo Please enter the directory name\n      echo If it was the directory name already, please prepend it with \\\"./\\\": \"./$installdir\"\n    else\n      break\n    fi\n  done\n\n  if [ -e \"$installdir\" ]; then\n    echo \"ERROR: Installation directory [$installdir] exists already\"\n    echo \"Please remove it first before continuing\"\n    return 1\n  fi\n\n  if ! mkdir -p \"$installdir\"; then\n    echo \"ERROR: Could not create the installation directory \\\"$installdir\\\"\"\n    echo \"ERROR: Please check the permissions and start the script again\"\n    return 1\n  fi\n\n  local space_needed=700\n  local space_available; space_available=$(($(df -k \"$installdir\" | awk '{print $4}' | tail -1)/1024))\n\n  if [ \"$space_available\" -lt \"$space_needed\" ]; then\n    echo \"ERROR: Installation directory has no enough space (needed: ${space_needed}M, available: ${space_available}M\"\n    echo \"ERROR: Please clean up and start the script again\"\n    rmdir \"$installdir\"\n    return 1\n  fi\n\n  _say_what_i_do Cloning cheat.sh locally\n  local url=https://github.com/chubin/cheat.sh\n  rmdir \"$installdir\"\n  git clone \"$url\" \"$installdir\" || fatal Could not clone \"$url\" with git into \"$installdir\"\n  cd \"$installdir\" || fatal \"Cannot cd into $installdir\"\n\n  # after the repository cloned, we may have the log directory\n  # and we can write our installation log into it\n  mkdir -p \"log/\"\n  LOG=\"$PWD/log/install.log\"\n\n  # we use tee everywhere so we should set -o pipefail\n  set -o pipefail\n\n  # currently the script uses python 2,\n  # but cheat.sh supports python 3 too\n  # if you want to switch it to python 3\n  # set PYTHON2 to NO:\n  # PYTHON2=NO\n  #\n  PYTHON2=NO\n  if [[ $PYTHON2 = YES ]]; then\n    python=\"python2\"\n    pip=\"pip\"\n    virtualenv_python3_option=()\n  else\n    python=\"python3\"\n    pip=\"pip3\"\n    virtualenv_python3_option=(-p python3)\n  fi\n\n  _say_what_i_do Creating virtual environment\n  virtualenv \"${virtualenv_python3_option[@]}\" ve \\\n      || fatal \"Could not create virtual environment with 'virtualenv ve'\"\n\n  export CHEATSH_PATH_WORKDIR=$PWD\n\n  # rapidfuzz does not support Python 2,\n  # so if we are using Python 2, install fuzzywuzzy instead\n  if [[ $PYTHON2 = YES ]]; then\n    sed -i s/rapidfuzz/fuzzywuzzy/ requirements.txt\n    echo \"python-Levenshtein\" >> requirements.txt\n  fi\n\n  _say_what_i_do Installing python requirements into the virtual environment\n  ve/bin/\"$pip\" install -r requirements.txt > \"$LOG\" \\\n      || {\n\n    echo \"ERROR:\"\n    echo \"---\"\n    tail -n 10 \"$LOG\"\n    echo \"---\"\n    echo \"See $LOG for more\"\n    fatal Could not install python dependencies into the virtual environment\n  }\n  echo \"$(ve/bin/\"$pip\" freeze | wc -l) dependencies were successfully installed\"\n\n  _say_what_i_do Fetching the upstream cheat sheets repositories\n  ve/bin/python lib/fetch.py fetch-all | tee -a \"$LOG\"\n\n  _say_what_i_do Running self-tests\n  (\n    cd tests || exit\n\n    if CHEATSH_TEST_STANDALONE=YES \\\n       CHEATSH_TEST_SKIP_ONLINE=NO \\\n       CHEATSH_TEST_SHOW_DETAILS=NO \\\n       PYTHON=../ve/bin/python bash run-tests.sh | tee -a \"$LOG\"\n    then\n      printf \"\\033[0;32m%s\\033[0m\\n\" \"SUCCESS\"\n    else\n      printf \"\\033[0;31m%s\\033[0m\\n\" \"FAILED\"\n      echo \"Some tests were failed. Run the tests manually for further investigation:\"\n      echo \"  cd $PWD; bash run-tests.sh)\"\n    fi\n  )\n\n  mkdir -p \"$CHTSH_HOME\"\n  echo \"$installdir\" > \"$CHTSH_HOME/standalone\"\n  echo auto > \"$CHTSH_HOME/mode\"\n\n  _say_what_i_do Done\n\n  local v1; v1=$(printf \"\\033[0;1;32m\")\n  local v2; v2=$(printf \"\\033[0m\")\n\n  cat <<EOF | sed \"s/{/$v1/; s/}/$v2/\"\n\n{      _      }\n{     \\\\ \\\\   }     The installation is successfully finished.\n{      \\\\ \\\\  }\n{      / /    }   Now you can use cheat.sh in the standalone mode,\n{     /_/     }   or you can start your own cheat.sh server.\n\n\nNow the cht.sh shell client is switched to the auto mode, where it uses\nthe local cheat.sh installation if possible.\nYou can switch the mode with the --mode switch:\n\n    cht.sh --mode lite      # use https://cheat.sh/ only\n    cht.sh --mode auto      # use local installation\n\nYou can add your own cheat sheets repository (config is in \\`etc/config.yaml\\`),\nor create new cheat sheets adapters (in \\`lib/adapters\\`).\n\nTo update local copies of cheat sheets repositores on a regular basis,\nadd the following line to your user crontab (crontab -e):\n\n    10 * * * * $installdir/ve/bin/python $installdir/lib/fetch.py update-all\n\nAll cheat sheets will be automatically actualized each hour.\n\nIf you are running a server reachable from the Internet, it can be instantly\nnotified via a HTTP request about any cheat sheets changes. For that, please\nopen an issue on the cheat.sh project repository [github.com/chubin/cheat.sh]\nwith the ENTRY-POINT from the URL https://ENTRY-POINT/:actualize specified\nEOF\n}\n\nchtsh_mode()\n{\n  local mode=\"$1\"\n\n  local text; text=$(\n    echo \"  auto    use the standalone installation first\"\n    echo \"  lite    use the cheat sheets server directly\"\n  )\n\n  if [ -z \"$mode\" ]; then\n    echo \"current mode: $CHTSH_MODE ($(printf \"%s\" \"$text\" | grep \"$CHTSH_MODE\" | sed \"s/$CHTSH_MODE//; s/^ *//; s/ \\+/ /\"))\"\n    if [ -d \"$CHEATSH_INSTALLATION\" ]; then\n      echo \"cheat.sh standalone installation: $CHEATSH_INSTALLATION\"\n    else\n      echo 'cheat.sh standalone installation not found; falling back to the \"lite\" mode'\n    fi\n  elif [ \"$mode\" = auto ] || [ \"$mode\" = lite ]; then\n    if [ \"$mode\" = \"$CHTSH_MODE\" ]; then\n      echo \"The configured mode was \\\"$CHTSH_MODE\\\"; nothing changed\"\n    else\n      mkdir -p \"$CHTSH_HOME\"\n      echo \"$mode\" > \"$CHTSH_HOME/mode\"\n      echo \"Configured mode: $mode\"\n    fi\n  else\n    echo \"Unknown mode: $mode\"\n    echo Supported modes:\n    echo \"  auto    use the standalone installation first\"\n    echo \"  lite    use the cheat sheets server directly\"\n  fi\n}\n\nget_query_options()\n{\n  local query=\"$*\"\n  if [ -n \"$CHTSH_QUERY_OPTIONS\" ]; then\n    case $query in\n      *\\?*)   query=\"$query&${CHTSH_QUERY_OPTIONS}\";;\n      *)      query=\"$query?${CHTSH_QUERY_OPTIONS}\";;\n    esac\n  fi\n  printf \"%s\" \"$query\"\n}\n\ndo_query()\n{\n  local query=\"$*\"\n  local b_opts=\n  local uri=\"${CHTSH_URL}/\\\"\\$(get_query_options $query)\\\"\"\n\n  if [ -e \"$CHTSH_HOME/id\" ]; then\n    b_opts=\"-b \\\"\\$CHTSH_HOME/id\\\"\"\n  fi\n\n  eval curl \"$b_opts\" -s \"$uri\" > \"$TMP1\"\n\n  if [ -z \"$lines\" ] || [ \"$(wc -l \"$TMP1\" | awk '{print $1}')\" -lt \"$lines\" ]; then\n    cat \"$TMP1\"\n  else\n    ${PAGER:-$defpager} \"$TMP1\"\n  fi\n}\n\nprepare_query()\n{\n  local section=\"$1\"; shift\n  local input=\"$1\"; shift\n  local arguments=\"$1\"\n\n  local query\n  if [ -z \"$section\" ] || [ x\"${input}\" != x\"${input#/}\" ]; then\n    query=$(printf %s \"$input\" | sed 's@ @/@; s@ @+@g')\n  else\n    query=$(printf %s \"$section/$input\" | sed 's@ @+@g')\n  fi\n\n  [ -n \"$arguments\" ] && arguments=\"?$arguments\"\n  printf %s \"$query$arguments\"\n}\n\nget_list_of_sections()\n{\n  curl -s \"${CHTSH_URL}\"/:list | grep -v '/.*/' | grep '/$' | xargs\n}\n\ngen_random_str()\n(\n  len=$1\n  if command -v openssl >/dev/null; then\n    openssl rand -base64 $((len*3/4)) | awk -v ORS='' //\n  else\n    rdev=/dev/urandom\n    for d in /dev/{srandom,random,arandom}; do\n      test -r \"$d\" && rdev=$d\n    done\n    if command -v hexdump >/dev/null; then\n      hexdump -vn $((len/2)) -e '1/1 \"%02X\" 1 \"\"' \"$rdev\"\n    elif command -v xxd >/dev/null; then\n      xxd -l $((len/2)) -ps \"$rdev\" | awk -v ORS='' //\n    else\n      cd /tmp || { echo Cannot cd into /tmp >&2; exit 1; }\n      s=\n      # shellcheck disable=SC2000\n      while [ \"$(echo \"$s\" | wc -c)\" -lt \"$len\" ]; do\n        s=\"$s$(mktemp -u XXXXXXXXXX)\"\n      done\n      printf \"%.${len}s\" \"$s\"\n    fi\n  fi\n)\n\nif [ \"$CHTSH_MODE\" = auto ] && [ -d \"$CHEATSH_INSTALLATION\" ]; then\n  curl() {\n    # ignoring all options\n    # currently the standalone.py does not support them anyway\n    local opt\n    while getopts \"b:s\" opt; do\n      :\n    done\n    shift $((OPTIND - 1))\n\n    local url; url=\"$1\"; shift\n    PYTHONIOENCODING=UTF-8 \"$CHEATSH_INSTALLATION/ve/bin/python\" \"$CHEATSH_INSTALLATION/lib/standalone.py\" \"${url#\"$CHTSH_URL\"}\" \"$@\"\n  }\nelif [ \"$(uname -s)\" = OpenBSD ] && [ -x /usr/bin/ftp ]; then\n  # any better test not involving either OS matching or actual query?\n  curl() {\n    local opt args=\"-o -\"\n    while getopts \"b:s\" opt; do\n      case $opt in\n        b) args=\"$args -c $OPTARG\";;\n        s) args=\"$args -M -V\";;\n        *) echo \"internal error: unsupported cURL option '$opt'\" >&2; exit 1;;\n      esac\n    done\n    shift $((OPTIND - 1))\n    /usr/bin/ftp \"$args\" \"$@\"\n  }\nelse\n  command -v curl   >/dev/null || { echo 'DEPENDENCY: install \"curl\" to use cht.sh' >&2; exit 1; }\n  _CURL=$(command -v curl)\n  if [ x\"$CHTSH_CURL_OPTIONS\" != x ]; then\n    curl() {\n      $_CURL \"${CHTSH_CURL_OPTIONS}\" \"$@\"\n    }\n  fi\nfi\n\nif [ \"$1\" = --read ]; then\n  read -r a || a=\"exit\"\n  printf \"%s\\n\" \"$a\"\n  exit 0\nelif [ x\"$1\" = x--help ] || [ -z \"$1\" ]; then\n\n  n=${0##*/}\n  s=$(echo \"$n\" | sed \"s/./ /\"g)\n\n  cat <<EOF\nUsage:\n\n    $n [OPTIONS|QUERY]\n\nOptions:\n\n    QUERY                   process QUERY and exit\n\n    --help                  show this help\n    --shell [LANG]          shell mode (open LANG if specified)\n\n    --standalone-install [DIR|help]\n                            install cheat.sh in the standalone mode\n                            (by default, into ~/.cheat.sh/)\n\n    --mode [auto|lite]      set (or display) mode of operation\n                            * auto - prefer the local installation\n                            * lite - use the cheat sheet server\n\nEOF\n  exit 0\nelif [ x\"$1\" = x--shell ]; then\n  shell_mode=yes\n  shift\nelif [ x\"$1\" = x--standalone-install ]; then\n  shift\n  cheatsh_standalone_install \"$@\"\n  exit \"$?\"\nelif [ x\"$1\" = x--mode ]; then\n  shift\n  chtsh_mode \"$@\"\n  exit \"$?\"\nfi\n\nprompt=\"cht.sh\"\nopts=\"\"\ninput=\"\"\nfor o; do\n  if [ x\"$o\" != x\"${o#-}\" ]; then\n    opts=\"${opts}${o#-}\"\n  else\n    input=\"$input $o\"\n  fi\ndone\nquery=$(echo \"$input\" | sed 's@ *$@@; s@^ *@@; s@ @/@; s@ @+@g')\n\nif [ \"$shell_mode\" != yes ]; then\n  curl -s \"${CHTSH_URL}\"/\"$(get_query_options \"$query\")\"\n  exit 0\nelse\n  new_section=\"$1\"\n  valid_sections=$(get_list_of_sections)\n  valid=no; for q in $valid_sections; do [ \"$q\" = \"$new_section/\" ] && { valid=yes; break; }; done\n\n  if [ \"$valid\" = yes ]; then\n    section=\"$new_section\"\n    # shellcheck disable=SC2001\n    this_query=\"$(echo \"$input\" | sed 's@ *[^ ]* *@@')\"\n    this_prompt=\"\\033[0;32mcht.sh/$section>\\033[0m \"\n  else\n    this_query=\"$input\"\n    this_prompt=\"\\033[0;32mcht.sh>\\033[0m \"\n  fi\n  if [ -n \"$this_query\" ] && [ -z \"$CHEATSH_RESTART\" ]; then\n    printf \"$this_prompt$this_query\\n\"\n    curl -s \"${CHTSH_URL}\"/\"$(get_query_options \"$query\")\"\n  fi\nfi\n\nif [ \"$is_macos\" != yes ]; then\n  if [ \"$XDG_SESSION_TYPE\" = wayland ]; then\n    command -v wl-copy >/dev/null || echo 'DEPENDENCY: please install \"wl-copy\" for \"copy\"' >&2\n  else\n    command -v xsel >/dev/null ||   echo 'DEPENDENCY: please install \"xsel\" for \"copy\"' >&2\n  fi\nfi\ncommand -v rlwrap >/dev/null || { echo 'DEPENDENCY: install \"rlwrap\" to use cht.sh in the shell mode' >&2; exit 1; }\n\nmkdir -p \"$CHTSH_HOME/\"\nlines=$(tput lines)\n\nif command -v less >/dev/null; then\n  defpager=\"less -R\"\nelif command -v more >/dev/null; then\n  defpager=\"more\"\nelse\n  defpager=\"cat\"\nfi\n\ncmd_cd() {\n  if [ $# -eq 0 ]; then\n    section=\"\"\n  else\n    new_section=$(echo \"$input\" | sed 's/cd  *//; s@/*$@@; s@^/*@@')\n    if [ -z \"$new_section\" ] || [ \"..\" = \"$new_section\" ]; then\n      section=\"\"\n    else\n      valid_sections=$(get_list_of_sections)\n      valid=no; for q in $valid_sections; do [ \"$q\" = \"$new_section/\" ] && { valid=yes; break; }; done\n      if [ \"$valid\" = no ]; then\n        echo \"Invalid section: $new_section\"\n        echo \"Valid sections:\"\n        echo \"$valid_sections\" \\\n            | xargs printf \"%-10s\\n\" \\\n            | tr ' ' .  \\\n            | xargs -n 10 \\\n            | sed 's/\\./ /g; s/^/  /'\n      else\n        section=\"$new_section\"\n      fi\n    fi\n  fi\n}\n\ncmd_copy() {\n  if [ -z \"$DISPLAY\" ] && [ \"$is_macos\" != yes ]; then\n    echo copy: supported only in the Desktop version\n  elif [ -z \"$input\" ]; then\n    echo copy: Make at least one query first.\n  else\n    curl -s \"${CHTSH_URL}\"/\"$(get_query_options \"$query\"?T)\" > \"$TMP1\"\n    if [ \"$is_macos\" != yes ]; then\n      if [ \"$XDG_SESSION_TYPE\" = wayland ]; then\n        wl-copy < \"$TMP1\"\n      else\n        xsel -bi < \"$TMP1\"\n      fi\n    else\n      pbcopy < \"$TMP1\"\n    fi\n    echo \"copy: $(wc -l \"$TMP1\" | awk '{print $1}') lines copied to the selection\"\n  fi\n}\n\ncmd_ccopy() {\n  if [ -z \"$DISPLAY\" ] && [ \"$is_macos\" != yes ]; then\n    echo copy: supported only in the Desktop version\n  elif [ -z \"$input\" ]; then\n    echo copy: Make at least one query first.\n  else\n    curl -s \"${CHTSH_URL}\"/\"$(get_query_options \"$query\"?TQ)\" > \"$TMP1\"\n    if [ \"$is_macos\" != yes ]; then\n      if [ \"$XDG_SESSION_TYPE\" = wayland ]; then\n        wl-copy < \"$TMP1\"\n      else\n        xsel -bi < \"$TMP1\"\n      fi\n    else\n      pbcopy < \"$TMP1\"\n    fi\n    echo \"copy: $(wc -l \"$TMP1\" | awk '{print $1}') lines copied to the selection\"\n  fi\n}\n\ncmd_exit() {\n  exit 0\n}\n\ncmd_help() {\n  cat <<EOF\nhelp    - show this help\nhush    - do not show the 'help' string at start anymore\ncd LANG - change the language context\ncopy    - copy the last answer in the clipboard (aliases: yank, y, c)\nccopy   - copy the last answer w/o comments (cut comments; aliases: cc, Y, C)\nexit    - exit the cheat shell (aliases: quit, ^D)\nid [ID] - set/show an unique session id (\"reset\" to reset, \"remove\" to remove)\nstealth - stealth mode (automatic queries for selected text)\nupdate  - self update (only if the scriptfile is writeable)\nversion - show current cht.sh version\n/:help  - service help\nQUERY   - space separated query staring (examples are below)\n              cht.sh> python zip list\n              cht.sh/python> zip list\n              cht.sh/go> /python zip list\nEOF\n}\n\ncmd_hush() {\n  mkdir -p \"$CHTSH_HOME/\" && touch \"$CHTSH_HOME/.hushlogin\" && echo \"Initial 'use help' message was disabled\"\n}\n\ncmd_id() {\n  id_file=\"$CHTSH_HOME/id\"\n\n  if [ id = \"$input\" ]; then\n    new_id=\"\"\n  else\n    new_id=$(echo \"$input\" | sed 's/id  *//; s/ *$//; s/ /+/g')\n  fi\n  if [ \"$new_id\" = remove ]; then\n    if [ -e \"$id_file\" ]; then\n      rm -f -- \"$id_file\" && echo \"id is removed\"\n    else\n      echo \"id was not set, so you can't remove it\"\n    fi\n    return\n  fi\n  if [ -n \"$new_id\" ] && [ reset != \"$new_id\" ] && [ \"$(/bin/echo -n \"$new_id\" | wc -c)\" -lt 16 ]; then\n    echo \"ERROR: $new_id: Too short id. Minimal id length is 16. Use 'id reset' for a random id\"\n    return\n  fi\n  if [ -z \"$new_id\" ]; then\n    # if new_id is not specified check if we have some id already\n    # if yes, just show it\n    # if not, generate a new id\n    if [ -e \"$id_file\" ]; then\n      awk '$6 == \"id\" {print $NF}' <\"$id_file\" | tail -n 1\n      return\n    else\n      new_id=reset\n    fi\n  fi\n  if [ \"$new_id\" = reset ]; then\n    new_id=$(gen_random_str 12)\n  else\n    echo WARNING: if someone gueses your id, he can read your cht.sh search history\n  fi\n  if [ -e \"$id_file\" ] && grep -q '\\tid\\t[^\\t][^\\t]*$' \"$id_file\" 2> /dev/null; then\n    sed -i 's/\\tid\\t[^\\t][^\\t]*$/ id '\"$new_id\"'/' \"$id_file\"\n  else\n    if ! [ -e \"$id_file\" ]; then\n      printf '#\\n\\n' > \"$id_file\"\n    fi\n    printf \".cht.sh\\tTRUE\\t/\\tTRUE\\t0\\tid\\t$new_id\\n\" >> \"$id_file\"\n  fi\n  echo \"$new_id\"\n}\n\ncmd_query() {\n  query=$(prepare_query \"$section\" \"$input\")\n  do_query \"$query\"\n}\n\ncmd_stealth() {\n  if [ \"$input\" != stealth ]; then\n    arguments=$(echo \"$input\" | sed 's/stealth //; s/ /\\&/')\n  fi\n  trap break INT\n  if [ \"$is_macos\" = yes ]; then\n    past=$(pbpaste)\n  else\n    if [ \"$XDG_SESSION_TYPE\" = wayland ]; then\n      past=$(wl-paste -p)\n    else\n      past=$(xsel -o)\n    fi\n  fi\n  printf \"\\033[0;31mstealth:\\033[0m you are in the stealth mode; select any text in any window for a query\\n\"\n  printf \"\\033[0;31mstealth:\\033[0m selections longer than $STEALTH_MAX_SELECTION_LENGTH words are ignored\\n\"\n  if [ -n \"$arguments\" ]; then\n    printf \"\\033[0;31mstealth:\\033[0m query arguments: ?$arguments\\n\"\n  fi\n  printf \"\\033[0;31mstealth:\\033[0m use ^C to leave this mode\\n\"\n  while true; do\n    if [ \"$is_macos\" = yes ]; then\n      current=$(pbpaste)\n    else\n      if [ \"$XDG_SESSION_TYPE\" = wayland ]; then\n        current=$(wl-paste -p)\n      else\n        current=$(xsel -o)\n      fi\n    fi\n    if [ \"$past\" != \"$current\" ]; then\n      past=$current\n      current_text=\"$(echo $current | tr -c '[a-zA-Z0-9]' ' ')\"\n      if [ \"$(echo \"$current_text\" | wc -w)\" -gt \"$STEALTH_MAX_SELECTION_LENGTH\" ]; then\n        printf \"\\033[0;31mstealth:\\033[0m selection length is longer than $STEALTH_MAX_SELECTION_LENGTH words; ignoring\\n\"\n        continue\n      else\n        printf \"\\n\\033[0;31mstealth: \\033[7m $current_text\\033[0m\\n\"\n        query=$(prepare_query \"$section\" \"$current_text\" \"$arguments\")\n        do_query \"$query\"\n      fi\n    fi\n    sleep 1;\n  done\n  trap - INT\n}\n\ncmd_update() {\n  [ -w \"$0\" ] || { echo \"The script is readonly; please update manually: curl -s ${CHTSH_URL}/:cht.sh | sudo tee $0\"; return; }\n  TMP2=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX)\n  curl -s \"${CHTSH_URL}\"/:cht.sh > \"$TMP2\"\n  if ! cmp \"$0\" \"$TMP2\" > /dev/null 2>&1; then\n    if grep -q ^__CHTSH_VERSION= \"$TMP2\"; then\n      # section was validated by us already\n      args=(--shell \"$section\")\n      cp \"$TMP2\" \"$0\" && echo \"Updated. Restarting...\" && rm \"$TMP2\" && CHEATSH_RESTART=1 exec \"$0\" \"${args[@]}\"\n    else\n      echo \"Something went wrong. Please update manually\"\n    fi\n  else\n    echo \"cht.sh is up to date. No update needed\"\n  fi\n  rm -f \"$TMP2\" > /dev/null 2>&1\n}\n\ncmd_version() {\n  insttime=$(ls -l -- \"$0\" | sed 's/  */ /g' | cut -d ' ' -f 6-8)\n  echo \"cht.sh version $__CHTSH_VERSION of $__CHTSH_DATETIME; installed at: $insttime\"\n  TMP2=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX)\n  if curl -s \"${CHTSH_URL}\"/:cht.sh > \"$TMP2\"; then\n    if ! cmp \"$0\" \"$TMP2\" > /dev/null 2>&1; then\n      echo \"Update needed (type 'update' for that)\".\n    else\n      echo \"Up to date. No update needed\"\n    fi\n  fi\n  rm -f \"$TMP2\" > /dev/null 2>&1\n}\n\nTMP1=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX)\ntrap 'rm -f $TMP1 $TMP2' EXIT\ntrap 'true' INT\n\nif ! [ -e \"$CHTSH_HOME/.hushlogin\" ] && [ -z \"$this_query\" ]; then\n  echo \"type 'help' for the cht.sh shell help\"\nfi\n\nwhile true; do\n  if [ \"$section\" != \"\" ]; then\n    full_prompt=\"$prompt/$section> \"\n  else\n    full_prompt=\"$prompt> \"\n  fi\n\n  input=$(\n    rlwrap -H \"$CHTSH_HOME/history\" -pgreen -C cht.sh -S \"$full_prompt\" bash \"$0\" --read | sed 's/ *#.*//'\n  )\n\n  cmd_name=${input%% *}\n  cmd_args=${input#* }\n  case $cmd_name in\n    \"\")             continue;;   # skip empty input lines\n    '?'|h|help)     cmd_name=help;;\n    hush)           cmd_name=hush;;\n    cd)             cmd_name=\"cd\";;\n    exit|quit)      cmd_name=\"exit\";;\n    copy|yank|c|y)  cmd_name=copy;;\n    ccopy|cc|C|Y)   cmd_name=ccopy;;\n    id)             cmd_name=id;;\n    stealth)        cmd_name=stealth;;\n    update)         cmd_name=update;;\n    version)        cmd_name=version;;\n    *)              cmd_name=\"query\"; cmd_args=\"$input\";;\n  esac\n  \"cmd_$cmd_name\" $cmd_args\ndone\n"
  },
  {
    "path": "share/emacs-ivy.txt",
    "content": ";;\n;; Written by RenJMR\n;; https://www.reddit.com/r/emacs/comments/6ddr7p/snippet_search_cheatsh_using_ivy/ \n;; \n;;;\n;;; Install the package `ivy' and use `(require 'ivy)' if you do not have\n;;; access to the `ivy-read' function.\n\n(defun ejmr-search-cheat-sh ()\n  \"Search `http://cheat.sh/' for help on commands and code.\"\n  (interactive)\n  (ivy-read \"Command or Topic: \"\n      (process-lines \"curl\" \"--silent\" \"http://cheat.sh/:list?T&q\")\n      :require-match t\n      :sort t\n      :history 'ejmr-search-cheat-sh\n      :action (lambda (input)\n        (browse-url (concat \"http://cheat.sh/\" input \"?T&q\")))\n      :caller 'ejmr-search-cheat-sh))\n"
  },
  {
    "path": "share/emacs.txt",
    "content": ";;; cheat-sh.el --- Interact with cheat.sh  -*- lexical-binding: t -*-\n;; Copyright 2017 by Dave Pearson <davep@davep.org>\n\n;; Author: Dave Pearson <davep@davep.org>\n;; Version: 1.7\n;; Keywords: docs, help\n;; URL: https://github.com/davep/cheat-sh.el\n;; Package-Requires: ((emacs \"24\"))\n\n;; cheat-sh.el is free software distributed under the terms of the GNU\n;; General Public Licence, version 2 or (at your option) any later version.\n;; For details see the file COPYING.\n\n;;; Commentary:\n;;\n;; cheat-sh.el provides a simple Emacs interface for looking things up on\n;; cheat.sh.\n\n;;; Code:\n\n(require 'url-vars)\n\n(defgroup cheat-sh nil\n  \"Interact with cheat.sh.\"\n  :group 'docs)\n\n(defface cheat-sh-section\n  '((t :inherit (bold font-lock-doc-face)))\n  \"Face used on sections in a cheat-sh output window.\"\n  :group 'cheat-sh)\n\n(defface cheat-sh-caption\n  '((t :inherit (bold font-lock-function-name-face)))\n  \"Face used on captions in the cheat-sh output window.\"\n  :group 'cheat-sh)\n\n(defcustom cheat-sh-list-timeout (* 60 60 4)\n  \"Seconds to wait before deciding the cached sheet list is \\\"stale\\\".\"\n  :type 'integer\n  :group 'cheat-sh)\n\n(defconst cheat-sh-url \"http://cheat.sh/%s?T\"\n  \"URL for cheat.sh.\")\n\n(defconst cheat-sh-user-agent \"cheat-sh.el (curl)\"\n  \"User agent to send to cheat.sh.\n\nNote that \\\"curl\\\" should ideally be included in the user agent\nstring because of the way cheat.sh works.\n\ncheat.sh looks for a specific set of clients in the user\nagent (see https://goo.gl/8gh95X for this) to decide if it should\ndeliver plain text rather than HTML. cheat-sh.el requires plain\ntext.\")\n\n(defun cheat-sh-get (thing)\n  \"Get THING from cheat.sh.\"\n  (let* ((url-request-extra-headers `((\"User-Agent\" . ,cheat-sh-user-agent)))\n         (buffer (url-retrieve-synchronously (format cheat-sh-url (url-hexify-string thing)) t t)))\n    (when buffer\n      (with-current-buffer buffer\n        (setf (point) (point-min))\n        (when (search-forward-regexp \"^$\" nil t)\n          (buffer-substring (point) (point-max)))))))\n\n(defvar cheat-sh-sheet-list nil\n  \"List of all available sheets.\")\n\n(defvar cheat-sh-sheet-list-acquired nil\n  \"The time when variable `cheat-sh-sheet-list' was populated.\")\n\n(defun cheat-sh-sheet-list-cache ()\n  \"Return the list of sheets.\n\nThe list is cached in memory, and is considered \\\"stale\\\" and is\nrefreshed after `cheat-sh-list-timeout' seconds.\"\n  (when (and cheat-sh-sheet-list-acquired\n             (> (- (time-to-seconds) cheat-sh-sheet-list-acquired) cheat-sh-list-timeout))\n    (setq cheat-sh-sheet-list nil))\n  (or cheat-sh-sheet-list\n      (let ((list (cheat-sh-get \":list\")))\n        (when list\n          (setq cheat-sh-sheet-list-acquired (time-to-seconds))\n          (setq cheat-sh-sheet-list (split-string list \"\\n\"))))))\n\n(defun cheat-sh-read (prompt)\n  \"Read input from the user, showing PROMPT to prompt them.\n\nThis function is used by some `interactive' functions in\ncheat-sh.el to get the item to look up. It provides completion\nbased of the sheets that are available on cheat.sh.\"\n  (completing-read prompt (cheat-sh-sheet-list-cache)))\n\n(defun cheat-sh-decorate-all (buffer regexp face)\n  \"Decorate BUFFER, finding REGEXP and setting face to FACE.\"\n  (with-current-buffer buffer\n    (save-excursion\n      (setf (point) (point-min))\n      (while (search-forward-regexp regexp nil t)\n        (replace-match (propertize (match-string 1) 'font-lock-face face) nil t)))))\n\n(defun cheat-sh-decorate-results (buffer)\n  \"Decorate BUFFER with properties to highlight results.\"\n  ;; \"[Search section]\"\n  (cheat-sh-decorate-all buffer \"^\\\\(\\\\[.*\\\\]\\\\)$\"        'cheat-sh-section)\n  ;; \"# Result caption\"\n  (cheat-sh-decorate-all buffer \"^\\\\(#.*\\\\)$\"             'cheat-sh-caption)\n  ;; \"cheat-sh help caption:\"\n  (cheat-sh-decorate-all buffer \"^\\\\([^[:space:]].*:\\\\)$\" 'cheat-sh-caption))\n\n;;;###autoload\n(defun cheat-sh (thing)\n  \"Look up THING on cheat.sh and display the result.\"\n  (interactive (list (cheat-sh-read \"Lookup: \")))\n  (let ((result (cheat-sh-get thing)))\n    (if result\n        (with-help-window \"*cheat.sh*\"\n          (princ result)\n          (cheat-sh-decorate-results standard-output))\n      (error \"Can't find anything for %s on cheat.sh\" thing))))\n\n;;;###autoload\n(defun cheat-sh-region (start end)\n  \"Look up the text between START and END on cheat.sh.\"\n  (interactive \"r\")\n  (deactivate-mark)\n  (cheat-sh (buffer-substring-no-properties start end)))\n\n;;;###autoload\n(defun cheat-sh-maybe-region ()\n  \"If region is active lookup content of region, otherwise prompt.\"\n  (interactive)\n  (call-interactively (if mark-active #'cheat-sh-region #'cheat-sh)))\n\n;;;###autoload\n(defun cheat-sh-help ()\n  \"Get help on using cheat.sh.\"\n  (interactive)\n  (cheat-sh \":help\"))\n\n;;;###autoload\n(defun cheat-sh-list (thing)\n  \"Get a list of topics available on cheat.sh.\n\nEither gets a topic list for subject THING, or simply gets a list\nof all available topics on cheat.sh if THING is supplied as an\nempty string.\"\n  (interactive (list (cheat-sh-read \"List sheets for: \")))\n  (cheat-sh (format \"%s/:list\" thing)))\n\n;;;###autoload\n(defun cheat-sh-search (thing)\n  \"Search for THING on cheat.sh and display the result.\"\n  (interactive \"sSearch: \")\n  (cheat-sh (concat \"~\" thing)))\n\n;;;###autoload\n(defun cheat-sh-search-topic (topic thing)\n  \"Search TOPIC for THING on cheat.sh and display the result.\"\n  (interactive\n   (list (cheat-sh-read \"Topic: \")\n         (read-string \"Search: \")))\n  (cheat-sh (concat topic \"/~\" thing)))\n\n(provide 'cheat-sh)\n\n;;; cheat-sh.el ends here\n"
  },
  {
    "path": "share/firstpage-v1.txt",
    "content": "\n          oooo                                .                oooo        \n          `888                              .o8                `888        \n .ooooo.   888 .oo.    .ooooo.   .oooo.   .o888oo      .oooo.o  888 .oo.   \nd88' `\"Y8  888P\"Y88b  d88' `88b `P  )88b    888       d88(  \"8  888P\"Y88b  \n888        888   888  888ooo888  .oP\"888    888       `\"Y88b.   888   888  \n888   .o8  888   888  888    .o d8(  888    888 . .o. o.  )88b  888   888  \n`Y8bod8P' o888o o888o `Y8bod8P' `Y888\"\"8o   \"888\" Y8P 8\"\"888P' o888o o888o \n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n    * the fastest way to find <command options> | <code pieces> you need\n    * provides access to community driven cheat sheets repositories\n    * delivers <906> cheat sheets in <16> areas and growing\n    * covers UNIX/Linux commands and programming languages\n    * programming languages cheat sheets are under:\n        <clojure/> <c++/> <elixir/> <elm/> <erlang/> <go/> <haskell/> <js/>\n        <julia/> <lua/> <ocaml/> <perl/> <php/> <python/> <rust/> <scala/>\n    * database management systems:\n        <mongo/> <redis/>\n    * supports bash completion (add {/:bash_completion} to your {~/.bashrc})\n    * editors integration (see {/:emacs} and {/:vim})\n\n\nTo show a cheat sheet:\n\n    $ curl cheat.sh/{command}\n\nTo find a cheat sheet (details in {/:help}):\n\n    $ curl cheat.sh/{~keyword}\n\nTo post a cheat sheet (details in {/:post}):\n\n    $ curl -F 'newcmd=<-' cheat.sh\n\n[Follow @igor_chubin for updates] [github.com/chubin/cheat.sh]\n"
  },
  {
    "path": "share/firstpage-v2.pnl",
    "content": "      _                _         _    __  \n  ___| |__   ___  __ _| |_   ___| |__ \\ \\      The only cheat sheet you need\n / __| '_ \\ / _ \\/ _` | __| / __| '_ \\ \\ \\     Unified access to the best\n| (__| | | |  __/ (_| | |_ _\\__ \\ | | |/ /     community driven documentation\n \\___|_| |_|\\___|\\__,_|\\__(_)___/_| |_/_/      repositories of the world\n\n+------------------------+ +------------------------+ +------------------------+\n| $ curl cheat.sh/ls     | | $ cht.sh btrfs         | | $ cht.sh lua/:learn    |\n| $ curl cht.sh/btrfs    | | $ cht.sh tar~list      | | Learn any* programming |\n| $ curl cht.sh/tar~list | |                        | | language not leaving   |\n| $ curl https://cht.sh  | |                        | | your shell             |\n|                        | |                        | | *) any of 60           |\n|                        | |                        | |                        |\n+-- queries with curl ---+ +- own optional client --+ +- learn, learn, learn! -+\n+------------------------+ +------------------------+ +------------------------+\n| $ cht.sh go/f<tab><tab>| | $ cht.sh --shell       | | $ cht.sh go zip lists  |\n| go/for   go/func       | | cht.sh> help           | | Ask any question using |\n| $ cht.sh go/for        | | ...                    | | cht.sh or curl cht.sh: |\n| ...                    | | $ curl cht.sh/:cht.sh  | | /go/zip+lists          |\n|                        | | #!/bin/sh              | | (use /,+ when curling) |\n|                        | | ...                    | |                        |\n+---- TAB-completion ----+ +-- interactive shell ---+ +- programming questions-+\n+------------------------+ +------------------------+ +------------------------+\n| $ curl cht.sh/:help    | | $ vim prg.py           | | $ time curl cht.sh/    |\n| see /:help and /:intro | | ...                    | | ...                    |\n| for usage information  | | zip lists _            | | real    0m0.075s       |\n| and README.md on GitHub| | <leader>KK             | |                        |\n| for the details        | |             *awesome*  | |                        |\n|            *start here*| |                        | |                        |\n+--- self-documented ----+ +- queries from editor! -+ +---- instant answers ---+\n\n[Follow @igor_chubin for updates][github.com/chubin/cheat.sh]\n==[mask]==\nKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKAAAAA\nKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKAAAAA GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\nKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKAAAA    DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\nKKKKKKKKKKKKKKKKKKKKKKKKKKKLKKKKKKKKKKKAAAA    DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\nKKKKKKKKKKKKKKKKKKKKKKKKKKLLLKKKKKKKKKAAAAA    DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\n\nDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDD\nD $ BBBB CCCCCCCCCCCCCCC D D $ BBBBBB CCCCCCCCCCCCC D D $ CCCCCCCCCCCBBBBBB    D\nD $ BBBB CCCCCCCCCCCCCCC D D $ BBBBBB CCCCCCCCCCCCC D D Learn anyF programming D\nD $ BBBB CCCCCCCCCCCCCCC D D                        D D languages not leaving  D\nD $ CCCC BBBBBBCCCCCCCCC D D                        D D your shell             D\nD                        D D                        D D FF any of 60           D\nD                        D D                        D D                        D\nDDDEEEEEEEEEEEEEEEEEEEDDDD DD EEEEEEEEEEEEEEEEEEE DDD DD EEEEEEEEEEEEEEEEEEEE DD\nDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDD\nD $ CCCCCCCCCCCBBBBBBBBBBD D $ CCCCCC BBBBBBB       D D $ CCCCCC BBBBBBBBBBBB  D\nD go/for   go/func       D D HHHHHHH help           D D ask any question using D\nD $ cht.sh go/for        D D ...                    D D cht.sh or curl cht.sh: D\nD ...                    D D $ BBBB CCCCCCCCCCCCCCC D D /goHzipHlists          D\nD                        D D                        D D (use H,H when curling) D\nD                        D D                        D D                        D\nDDDDDEEEEEEEEEEEEEEEEDDDDD DDDEEEEEEEEEEEEEEEEEEEDDDD DDEEEEEEEEEEEEEEEEEEEEEEDD\nDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDD\nD $ CCCCCCCCCCCCBBBBB    D D $ BBB CCCCCC           D D $ BBBB curl cht.sh/    D\nD see HHHHHH and HHHHHHH D D ...                    D D ...                    D\nD for usage information  D D zip lists _            D D real    HHHHHHHH       D\nD and readme.md on CCCCCCD D HHHHHHHHHH             D D                        D\nD for the details        D D            * awesome * D D                        D\nD            FFFFFFFFFFFFD D                        D D                        D\nDDDD EEEEEEEEEEEEEEE DDDDD DD EEEEEEEEEEEEEEEEEEEE DD DDDDD EEEEEEEEEEEEEEE DDDD\n\nDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\n==[code]==\n\nset_color A green\nset_color B white\nset_color C gray\nset_color D cyan\nset_color E yellow\n\nset_color A #00cc00\nset_color B #00cc00\nset_color C #00aacc\nset_color D #888888\nset_color E #cccc00\nset_color F #ff0000\nset_color H #22aa22\nset_color I #cc0000\nset_color J #000000\n  \nset_bg_color G #555555\nset_bg_color J #555555\n\n"
  },
  {
    "path": "share/firstpage-v2.txt",
    "content": "      _                _         _    \u001b[38;2;0;204;0m_\u001b[0m\u001b[38;2;0;204;0m_\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m \u001b[0m                                     \n  ___| |__   ___  __ _| |_   ___| |__ \u001b[38;2;0;204;0m\\\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m\\\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m \u001b[0m \u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85mT\u001b[0m\u001b[48;2;85;85;85mh\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85mo\u001b[0m\u001b[48;2;85;85;85mn\u001b[0m\u001b[48;2;85;85;85ml\u001b[0m\u001b[48;2;85;85;85my\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85mc\u001b[0m\u001b[48;2;85;85;85mh\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85ma\u001b[0m\u001b[48;2;85;85;85mt\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85ms\u001b[0m\u001b[48;2;85;85;85mh\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85mt\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85my\u001b[0m\u001b[48;2;85;85;85mo\u001b[0m\u001b[48;2;85;85;85mu\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85mn\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85md\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85m \u001b[0m \n / __| '_ \\ / _ \\/ _` | __| / __| '_ \\ \u001b[38;2;0;204;0m\\\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m\\\u001b[0m\u001b[38;2;0;204;0m \u001b[0m    \u001b[38;2;136;136;136mU\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mf\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136ma\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mb\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m   \n| (__| | | |  __/ (_| | |_ _\\__ \\ | | |\u001b[38;2;0;204;0m/\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m/\u001b[0m\u001b[38;2;0;204;0m \u001b[0m    \u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mm\u001b[0m\u001b[38;2;136;136;136mm\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136my\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mv\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mm\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136ma\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m   \n \\___|_| |_|\\___|\\__,_|\\__(_)___/_| |_\u001b[38;2;0;204;0m/\u001b[0m\u001b[38;2;0;204;0m_\u001b[0m\u001b[38;2;0;204;0m/\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m \u001b[0m    \u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136mp\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mf\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mw\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136ml\u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m   \n                                                                                \n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mu\u001b[0m\u001b[38;2;0;204;0mr\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204me\u001b[0m\u001b[38;2;0;170;204ma\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0m.\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m \u001b[38;2;0;170;204mb\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204mf\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204mu\u001b[0m\u001b[38;2;0;170;204ma\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;204;0m:\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m\u001b[38;2;0;204;0me\u001b[0m\u001b[38;2;0;204;0ma\u001b[0m\u001b[38;2;0;204;0mr\u001b[0m\u001b[38;2;0;204;0mn\u001b[0m    \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mu\u001b[0m\u001b[38;2;0;204;0mr\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204mb\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204mf\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0m.\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m \u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204ma\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204m~\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204mi\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m Learn any\u001b[38;2;255;0;0m*\u001b[0m programming \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mu\u001b[0m\u001b[38;2;0;204;0mr\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204ma\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204m~\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204mi\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m language not leaving   \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mu\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m \u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0mp\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0m:\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m your shell             \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;255;0;0m*\u001b[0m\u001b[38;2;255;0;0m)\u001b[0m any of 60           \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mq\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mw\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mh\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mw\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mp\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m,\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m,\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m!\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204mg\u001b[0m\u001b[38;2;0;170;204mo\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204mf\u001b[0m\u001b[38;2;0;204;0m<\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0ma\u001b[0m\u001b[38;2;0;204;0mb\u001b[0m\u001b[38;2;0;204;0m>\u001b[0m\u001b[38;2;0;204;0m<\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0ma\u001b[0m\u001b[38;2;0;204;0mb\u001b[0m\u001b[38;2;0;204;0m>\u001b[0m\u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m \u001b[38;2;0;204;0m-\u001b[0m\u001b[38;2;0;204;0m-\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0me\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m       \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m \u001b[38;2;0;204;0mg\u001b[0m\u001b[38;2;0;204;0mo\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0mz\u001b[0m\u001b[38;2;0;204;0mi\u001b[0m\u001b[38;2;0;204;0mp\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0ml\u001b[0m\u001b[38;2;0;204;0mi\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m  \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m go/for   go/func       \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;34;170;34mc\u001b[0m\u001b[38;2;34;170;34mh\u001b[0m\u001b[38;2;34;170;34mt\u001b[0m\u001b[38;2;34;170;34m.\u001b[0m\u001b[38;2;34;170;34ms\u001b[0m\u001b[38;2;34;170;34mh\u001b[0m\u001b[38;2;34;170;34m>\u001b[0m help           \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m Ask any question using \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ cht.sh go/for        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m ...                    \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m cht.sh or curl cht.sh: \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m ...                    \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m /go\u001b[38;2;34;170;34m/\u001b[0mzip\u001b[38;2;34;170;34m+\u001b[0mlists          \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m (use \u001b[38;2;34;170;34m/\u001b[0m,\u001b[38;2;34;170;34m+\u001b[0m when curling) \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mT\u001b[0m\u001b[38;2;204;204;0mA\u001b[0m\u001b[38;2;204;204;0mB\u001b[0m\u001b[38;2;204;204;0m-\u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0mp\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mv\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0mh\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mp\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mg\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mg\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mq\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mu\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;204;0m:\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0me\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m\u001b[38;2;0;204;0mp\u001b[0m    \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mv\u001b[0m\u001b[38;2;0;204;0mi\u001b[0m\u001b[38;2;0;204;0mm\u001b[0m \u001b[38;2;0;170;204mp\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204mg\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204mp\u001b[0m\u001b[38;2;0;170;204my\u001b[0m           \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0mi\u001b[0m\u001b[38;2;0;204;0mm\u001b[0m\u001b[38;2;0;204;0me\u001b[0m curl cht.sh/    \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m see \u001b[38;2;34;170;34m/\u001b[0m\u001b[38;2;34;170;34m:\u001b[0m\u001b[38;2;34;170;34mh\u001b[0m\u001b[38;2;34;170;34me\u001b[0m\u001b[38;2;34;170;34ml\u001b[0m\u001b[38;2;34;170;34mp\u001b[0m and \u001b[38;2;34;170;34m/\u001b[0m\u001b[38;2;34;170;34m:\u001b[0m\u001b[38;2;34;170;34mi\u001b[0m\u001b[38;2;34;170;34mn\u001b[0m\u001b[38;2;34;170;34mt\u001b[0m\u001b[38;2;34;170;34mr\u001b[0m\u001b[38;2;34;170;34mo\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m ...                    \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m ...                    \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m for usage information  \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m zip lists _            \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m real    \u001b[38;2;34;170;34m0\u001b[0m\u001b[38;2;34;170;34mm\u001b[0m\u001b[38;2;34;170;34m0\u001b[0m\u001b[38;2;34;170;34m.\u001b[0m\u001b[38;2;34;170;34m0\u001b[0m\u001b[38;2;34;170;34m7\u001b[0m\u001b[38;2;34;170;34m5\u001b[0m\u001b[38;2;34;170;34ms\u001b[0m       \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m and README.md on \u001b[38;2;0;170;204mG\u001b[0m\u001b[38;2;0;170;204mi\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204mH\u001b[0m\u001b[38;2;0;170;204mu\u001b[0m\u001b[38;2;0;170;204mb\u001b[0m\u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;34;170;34m<\u001b[0m\u001b[38;2;34;170;34ml\u001b[0m\u001b[38;2;34;170;34me\u001b[0m\u001b[38;2;34;170;34ma\u001b[0m\u001b[38;2;34;170;34md\u001b[0m\u001b[38;2;34;170;34me\u001b[0m\u001b[38;2;34;170;34mr\u001b[0m\u001b[38;2;34;170;34m>\u001b[0m\u001b[38;2;34;170;34mK\u001b[0m\u001b[38;2;34;170;34mK\u001b[0m             \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m for the details        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m             *awesome*  \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m            \u001b[38;2;255;0;0m*\u001b[0m\u001b[38;2;255;0;0ms\u001b[0m\u001b[38;2;255;0;0mt\u001b[0m\u001b[38;2;255;0;0ma\u001b[0m\u001b[38;2;255;0;0mr\u001b[0m\u001b[38;2;255;0;0mt\u001b[0m\u001b[38;2;255;0;0m \u001b[0m\u001b[38;2;255;0;0mh\u001b[0m\u001b[38;2;255;0;0me\u001b[0m\u001b[38;2;255;0;0mr\u001b[0m\u001b[38;2;255;0;0me\u001b[0m\u001b[38;2;255;0;0m*\u001b[0m\u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0mf\u001b[0m\u001b[38;2;204;204;0m-\u001b[0m\u001b[38;2;204;204;0md\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0md\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0mq\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mf\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0md\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0m!\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0mw\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n                                                                                \n\u001b[38;2;136;136;136m[\u001b[0m\u001b[38;2;136;136;136mF\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136ml\u001b[0m\u001b[38;2;136;136;136ml\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mw\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m@\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mg\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136m_\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mb\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mf\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mp\u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136ma\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136m]\u001b[0m\u001b[38;2;136;136;136m[\u001b[0m\u001b[38;2;136;136;136mg\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mb\u001b[0m\u001b[38;2;136;136;136m.\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mm\u001b[0m\u001b[38;2;136;136;136m/\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mb\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136m/\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ma\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136m.\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136m]\u001b[0m                   \n"
  },
  {
    "path": "share/fish.txt",
    "content": "# add it to your ~/.config/fish/config.fish\n\n# retrieve command cheat sheets from cheat.sh\n# fish version by @tobiasreischmann\n\nfunction cheat.sh\n    curl cheat.sh/$argv\nend\n\n# register completions (on-the-fly, non-cached, because the actual command won't be cached anyway\ncomplete -c cheat.sh -xa '(curl -s cheat.sh/:list)'\n\n"
  },
  {
    "path": "share/help.txt",
    "content": "Usage:\n\n    $ curl cheat.sh/TOPIC       show cheat sheet on the TOPIC\n    $ curl cheat.sh/TOPIC/SUB   show cheat sheet on the SUB topic in TOPIC\n    $ curl cheat.sh/~KEYWORD    search cheat sheets for KEYWORD\n\nOptions:\n\n    ?OPTIONS\n\n    q                  quiet mode, don't show github/twitter buttons\n    T                  text only, no ANSI sequences\n    style=STYLE        color style\n\n    c                  do not comment text, do not shift code (QUERY+ only)\n    C                  do not comment text, shift code (QUERY+ only)\n    Q                  code only, don't show text (QUERY+ only)\n\nOptions can be combined together in this way:\n\n    curl 'cheat.sh/for?qT&style=bw'\n\n(when using & in shell, don't forget to specify the quotes or escape & with \\)\n\nSpecial pages:\n\n    :help               this page\n    :list               list all cheat sheets\n    :post               how to post new cheat sheet\n    :cht.sh             shell client (cht.sh)\n    :bash_completion    bash function for tab completion\n    :styles             list of color styles\n    :styles-demo        show color styles usage examples\n    :random             fetches a random cheat sheet\n\nShell client:\n\n    $ curl https://cht.sh/:cht.sh > ~/bin/cht.sh\n    $ chmod +x ~/bin/cht.sh\n    $ cht.sh python :learn\n    $ cht.sh --shell\n\nTab completion:\n\n    $ mkdir -p ~/.bash.d/\n    $ curl cheat.sh/:bash_completion > ~/.bash.d/cht.sh\n    $ . ~/.bash.d/cht.sh\n    $ echo '. ~/.bash.d/cht.sh' >> ~/.bashrc\n\nEditor integration:\n\n    :emacs              see the page for the Emacs configuration\n    :vim                see the page for the Vim configuration\n\nSearch:\n\n    /~snapshot          look for \"snapshot\" in the first level cheat sheets\n    /~ssh~passphrase    several keywords can be combined together using ~\n    /scala/~closure     look for \"closure\" in scala cheat sheets\n    /~snapshot/r        look for \"snapshot\" in all cheat sheets recursively\n\nYou can use special search options after the closing slash:\n\n    /~shot/bi           case insensitive (i), word boundaries (b)\n\nList of search options:\n\n    b   word boundaries\n    i   case insensitive search\n    r   recursive\n\nProgramming languages topics:\n\nEach programming language topic has the following subtopics:\n\n    hello               hello world + how to start the program\n    :learn              big cheat sheet for learning language from scratch\n    :list               list of topics\n    :random             fetches a random cheat sheet belonging to the topic\n"
  },
  {
    "path": "share/intro.txt",
    "content": "## curl cht.sh\n\nTo access a cheat sheet you can simply issue a plain HTTP or HTTPS request\nspecifying the topic name in the query URL:\n\n    {1curl cheat.sh}{2/tar}\n    {1curl https://cheat.sh}{2/tar}\n\nYou can use the full service name, {2cheat.sh}, or the shorter variant, {2cht.sh}.\nThey are equivalent:\n\n    {1curl https://}{2cht.sh}{1/tar}\n    {1curl https://}{2cheat.sh}{1/tar}\n\nThe preferred access protocol is HTTPS, and you should always use it when possible.\n\nCheat sheets in the root namespaces cover UNIX/Linux commands.\n\nCheat sheets covering programming languages are located in subsections:\n\n    {1curl cht.sh/}{2go/func}\n\nAll cheat sheets in a subsection can be listed using a special query {2:list} :\n\n    {1curl cht.sh/go/}{2:list}\n\nThere are several other special queries. All of them start with a {2colon}.\nSee {2/:help} for the full list of the special queries.\n\n\n## Search\n\nIf a cheat sheet is too large, you can cut the needed part out using an\nadditional search parameter. In this case, only the paragraph that contains the\nsearch term will be displayed:\n\n    {1curl cht.sh/tar}{2~extract}\n\nIf the name of the cheat sheet is omitted, and only the search query is specified,\nall cheat sheets in the namespace are scanned, and the found occurrences\nare displayed:\n\n    {1curl cht.sh/}{2~extract}\n\n\n## Options\n\ncheat.sh queries as well as search queries have many options.\nThey can be specified as a part of the query string in the URL, after {2?}.\nShort single letter options can be joined together. Long options are\nseparated with {2&}. For example, to switch syntax highlighting off\nthe {2T} switch is used:\n\n    {1curl cht.sh/tar}{2?T}\n\nA full list of all available cheat.sh options as well as description of all modes\nof operation can be found in {2/:help}.\n\n    {1curl cht.sh}{2/:help}\n\n\n## cht.sh client\n\nThough it's perfectly possible to access cheat.sh using {1curl} (or any other\nHTTP client) alone, there is a special client that has several advantages\nover plain curling: {2cht.sh}.\n\nTo install the client in {2~/bin}:\n\n    {1curl} {2https://cht.sh/:cht.sh} {1> ~/bin/cht.sh}\n    {1chmod +x ~/bin/cht.sh}\n\nQueries look the same, but you can use {1spaces} to separate words in addition to {1+}\nused with curl.\n\n    {1cht.sh} {2python zip lists}\n\n\n## cht.sh shell\n\nIf you're always issuing queries about the same programming language, it can be\nmore convenient to run the client in the shell mode and specify the query's\ncontext:\n\n    {1$} {2cht.sh --shell python}\n    {1cht.sh/python> zip lists}\n\nOf course, you can start the shell without the context too:\n\n    {1$} {2cht.sh --shell}\n    {1cht.sh> python zip lists}\n    {1cht.sh> go http query}\n    {1cht.sh> js iterate list}\n\nIf you use one language predominantly, but sometimes issue queries about others,\nyou may prepend the query with {2/}:\n\n    {1cht.sh/python>} {2zip lists}\n    {1cht.sh/python>} {2/go http query}\n    {1cht.sh/python>} {2/js iterate list}\n\n\n## :learn\n\nIf you are just starting to learn a new programming language and you have no\ndistinct queries for the moment, cheat.sh can be a good starting point. As\nyou know, it exports cheat sheets from the best cheat sheet repositories, \nlike {1Learn X in Y}, a repository of concise documentation devoted\n(but not limited) to learning programming languages from scratch.\n\nIf you want start learning a new programming language, do (use less -R because\nthe output could be quite big): \n\n    {1curl cht.sh/elixir/}{2:learn} {1| less -R}\n\nOr simply {2:learn} with cht.sh (you don't need {2less -R} here, because\n{1cht.sh} starts pager if needed automatically):\n\n    {4cht.sh/elixir>} {2:learn}\n\n\n## Programming languages questions\n\nOne of the most important features of cheat.sh is that you can ask it any\nquestions about programming languages and instantly get answers. You\ncan use either direct HTTP queries or the cht.sh client:\n\n    {1curl cht.sh/}{2python/reverse+list}\n    \n    {4cht.sh/python>} {2reverse list}\n\nIn the latter case you don't need + to separate the words in the query, you can\ndo it in a more natural way, with spaces.\n\nIf context in the cht.sh shell is not specified, you have to write the\nprogramming language name as the first word in the query:\n\n    {4cht.sh>} {2python reverse list}\n\nBut if you are using only one programming language and all queries are about\nit, it's better to change the current context.\n\n\n## Comments\n\nText in the answers is syntactically formatted as a comment in the corresponding\nprogramming language\n\nWhen using cht.sh, you can copy the result of the last query into the selection\nbuffer (you may also call it \"clipboard\") using {2C} (or {2c}, with text):\n\n    {1cht.sh/python> reverse list}\n    {4...}\n    {1cht.sh/python>} {2C}\n    {4=1 lines copied}\n\n\n## bash TAB-completion for cht.sh\n\nOne of the advantages of the {1cht.sh} client comparing to plain curl is that you\ncan use TAB completion when writing its queries in {1bash}\n(other supported shells: {1zsh} and {1fish}).\n\nTo install the TAB completion script, assuming you use bash, you have to do:\n\n    {1mkdir -p ~/.bash.d/}\n    {1curl} {2https://cht.sh/:bash_completion} {1> ~/.bash.d/cht.sh}\n    {1echo 'source ~/.bash.d/cht.sh' >> ~/.bashrc}\n    {1source ~/.bash.d/cht.sh}\n\n\n## Editor\n\nYou can access cheat.sh directly from editors: {1Vim} and {1Emacs}.\nIt's a very important feature! You will absolutely like it.\n\n{1Imagine:}\ninstead of switching to your browser, googling, browsing Stack Overflow\nand eventually copying the code snippets you need and later pasting them into\nthe editor, you can achieve the same instantly and without leaving\nthe editor at all!\n\nHere is how it works:\n\n1. In Vim, if you have a question while editing a program, you can just type\nyour question {1directly in the buffer} and press {2<leader>KK}. You will get\nthe answer to your question in {1pager}. (with {2<leader>KB} you'll get the answer\nin a separate {1buffer}).\n\n2. If you like the answer. You can manually paste it from the buffer or\nthe pager, or if you are lazy you can use {2<leader>KP} to paste it under\nyour question ({2<leader>KR} will replace your question). If you want the\nanswer without the comments, {2<leader>KC} replays the last query\ntoggling them.\n\nYou have to install cheat.sh {1Vim/Emacs plugins} for the editor support.\nSee {2/:vim} or {2/:emacs} for detailed installation instructions.\n\n\n## Feature requests, feedback and contribution\n\nIf you want to submit a new community driver repository for cheat.sh please\nopen a ticket on the project page on GitHub.\n\nIf you want to modify an existing cheat sheet, please check the source of the\ncheat sheet (it is always displayed in the cheat sheet bottom line).\n\nIf you want to add a new cheat sheet, add it here:\n{1https://github.com/chubin/cheat.sheets}\n\nIf you want to suggest a new feature for cheat.sh, or if you've found a bug,\nplease open a new issue on github:\n{1https://github.com/chubin/cheat.sh}\n\nIf you want to get the major project updates, follow @igor_chubin in Twitter\nor this RSS feed: {1https://twitrss.me/twitter_user_to_rss/?user=igor_chubin}\n"
  },
  {
    "path": "share/post.txt",
    "content": "You can add a new entry to a cheat sheet or create a new cheat sheet\nin one of the following ways (your cheat sheet will be eventually added\nto chubin/cheat.sheets):\n\n1. With curl:\n\n    cat ${cheatsheet} | curl -F 'newcmd=<-' cheat.sh\n    curl --data-binary @${cheatsheet} cheat.sh/newcmd\n    \n   newcmd is the the name of the command you want to post\n   (use your @twitter or email@ in the post).\n    \n2. With git:\n\n~~~\n    # clone chubin/cheat.sheets\n    git pull https://github.com/${you}/cheat.sheets && cd cheat.sheets\n    cp ${cheatsheet} newcmd\n    git add newcmd\n    git commit -m 'added newcmd cheat sheet' newcmd\n    git push\n    # send pull request \n~~~\n\n3. With a browser:\n    \n    Go to the end of the cheat sheet, click the dollar sign with the mouse\n    and post your cheat sheet. It will be saved automatically and reviewed.\n\nWhen writing an entry for a cheat sheet, please keep in mind:\n\n    1. We don't try to repeat manuals and documentation sites\n    2. We don't try to document each and every special usage case of a tool\n    3. We try to find and gather the most interesting usage cases\n\nIf you want contribute to the project, but you have no idea what \ncheat sheet you should post, check the list of the most wanted cheat sheets:\n\n    cheat.sh/:wanted\n\n"
  },
  {
    "path": "share/scripts/cacheCleanup.go",
    "content": "package main\n\n// Remove invalid cache entries.\n// Cache entry is invalid, if it contains a special substring.\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"strings\"\n\n\t\"github.com/go-redis/redis\"\n)\n\nvar invalidEntrySubstr = \"Unknown cheat sheet\"\n\nfunc removeInvalidEntries() error {\n\trdb := redis.NewClient(&redis.Options{\n\t\tAddr:     \"localhost:6379\",\n\t\tPassword: \"\",\n\t\tDB:       0,\n\t})\n\n\tctx := context.Background()\n\tallKeys, err := rdb.Keys(ctx, \"*\").Result()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar counter int\n\tfor _, key := range allKeys {\n\t\tval, err := rdb.Get(ctx, key).Result()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif strings.Contains(val, invalidEntrySubstr) {\n\t\t\terr = rdb.Del(ctx, key).Err()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcounter++\n\t\t}\n\t}\n\tlog.Println(\"invalid entries removed:\", counter)\n\treturn nil\n}\n\nfunc main() {\n\terr := removeInvalidEntries()\n\tif err != nil {\n\t\tlog.Println(err)\n\t}\n}\n"
  },
  {
    "path": "share/scripts/remove-from-cache.sh",
    "content": "#!/usr/bin/env bash\n\nremove_by_name()\n{\n  local query; query=\"$1\"\n  local q\n\n  redis-cli KEYS \"$query\" | while read -r q; do\n    redis-cli DEL \"$q\"\n  done\n}\n\nif [ -z \"$1\" ]; then\n  echo Usage:\n  echo\n  echo \"    $0 QUERY\"\n  exit 1\nfi\n\nremove_by_name \"$1\"\n"
  },
  {
    "path": "share/static/1.html",
    "content": "<!doctype html>\n<html>\n    <head>\n      <link rel=\"stylesheet\" href=\"bower_components/xterm.js/dist/xterm.css\" />\n      <script src=\"bower_components/xterm.js/dist/xterm.js\"></script>\n    </head>\n    <body>\n      <div id=\"terminal\"></div>\n      <script>\n\nfunction httpGet(theUrl)\n{\n    var xmlHttp = new XMLHttpRequest();\n    xmlHttp.open( \"GET\", theUrl, false ); // false for synchronous request\n    xmlHttp.send( null );\n    return xmlHttp.responseText;\n};\n\n      \tvar term = new Terminal();\n        term.open(document.getElementById('terminal'));\n        var s = httpGet(\"/tar\").replace(/\\n/g, \"\\r\\n\");\n        term.write(s);\n      </script>\n    </body>\n</html>\n"
  },
  {
    "path": "share/static/malformed-response.html",
    "content": "<html>\n<title>cheat.sh</title>\n<head>\n<script async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\n</head>\n<body style='background:black'>\n<pre style='color:#bbbbbb'>\n#  Sorry, we are experiencing extremely high load now.\n#  We are working on the problem and hope to get it fixed soon.\n#  Please come back in several hours or try some other queries:\n#  \n#  For example:\n\n curl cht.sh/:list               to list available cheat sheets\n curl cht.sh/LANGUAGE/:list      to list available cheat sheets for LANGUAGE\n curl cht.sh/LANGUAGE/:learn     to learn the LANGUAGE\n\n<a href=\"https://twitter.com/igor_chubin\" class=\"twitter-follow-button\" data-show-count=\"false\" data-button=\"grey\">Follow @igor_chubin</a> <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script><span style='position: relative; bottom: 6px;'>for the updates. </span>\n\nIf you do not use Twitter, drop a short email to Igor Chubin (igor@chub.in),\nand you will be notified as soon as the service is fixed.\nIf you have any feature requests, wishes, ideas, criticism,\nyou can use them as the payload for this email.\n\nIf you like to code (and you surely do), you can check the <span style='position: relative; bottom: -6px;'><a aria-label=\"Star chubin/cheat.sh on GitHub\" data-count-aria-label=\"# stargazers on GitHub\" data-count-api=\"/repos/chubin/cheat.sh#stargazers_count\" data-count-href=\"/chubin/cheat.sh/stargazers\" data-icon=\"octicon-star\" href=\"https://github.com/chubin/cheat.sh\" class=\"github-button\">cheat.sh</a></span> repository\nto see how the scalability problem is (not yet) solved.\n\n</pre>\n<blockquote class=\"twitter-tweet\" data-theme=\"dark\" data-lang=\"en\"><p lang=\"en\" dir=\"ltr\">How to get an instant answer to any question on (almost) any programming language from the command line:<br>$ curl <a href=\"https://t.co/9A97GQdoKB\">https://t.co/9A97GQdoKB</a><br>$ curl <a href=\"https://t.co/F2XAJAIzDJ\">https://t.co/F2XAJAIzDJ</a><br>$ curl <a href=\"https://t.co/XAKEDhzWjL\">https://t.co/XAKEDhzWjL</a> <a href=\"https://t.co/HRr3mQGCJB\">pic.twitter.com/HRr3mQGCJB</a></p>&mdash; Igor Chubin (@igor_chubin) <a href=\"https://twitter.com/igor_chubin/status/1014590497330028551?ref_src=twsrc%5Etfw\">July 4, 2018</a></blockquote>\n<script async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\n\n<script async defer id=\"github-bjs\" src=\"https://buttons.github.io/buttons.js\"></script>\n</body>\n</html>\n\n"
  },
  {
    "path": "share/static/opensearch.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<OpenSearchDescription xmlns=\"http://a9.com/-/spec/opensearch/1.1/\" xmlns:moz=\"http://www.mozilla.org/2006/browser/search/\">\n<ShortName>cheat.sh</ShortName>\n<Description>The only cheat sheet you need. Unified access to the best community driven documentation repositories of the world.</Description>\n<Url type=\"text/html\" template=\"https://cheat.sh/{searchTerms}\" />\n<Url type=\"application/opensearchdescription+xml\" rel=\"self\" template=\"https://cheat.sh/files/opensearch.xml\" />\n<Tags>cheatsheet curl terminal command-line cli examples documentation help tldr</Tags>\n<Language>en-US</Language>\n<moz:SearchForm>https://cheat.sh</moz:SearchForm>\n</OpenSearchDescription>\n"
  },
  {
    "path": "share/static/style.css",
    "content": "body {\n    background: black;\n    color: #bbbbbb;\n}\n.pre,\npre {\n/*    font-family: source_code_proregular; */\n\n/*\nfont-family: Courier New,Courier,Lucida Sans Typewriter,Lucida Typewriter,monospace;\nfont-size: 70%;\n*/\n\n/*font-family: Lucida Console,Lucida Sans Typewriter,monaco,Bitstream Vera Sans Mono,monospace; */\n/*Droid Sans Mono*/\nfont-family: \"DejaVu Sans Mono\", Menlo, \"Lucida Sans Typewriter\", \"Lucida Console\", monaco, \"Bitstream Vera Sans Mono\", monospace;\n/*font-family: bitstream_vera_sans_monoroman;*/\nfont-size: 75%;\n}\n\ninput[type=\"text\"]{\n    border: none;\n    background: transparent;\n    color: #bbbbbb;\n}\n"
  },
  {
    "path": "share/styles-demo.txt",
    "content": "--------\nabap\n--------\n\u001b[38;5;102m# basic loop\u001b[39m\n\u001b[38;5;21mfor\u001b[39m i in \u001b[38;5;75m1\u001b[39m \u001b[38;5;75m2\u001b[39m \u001b[38;5;75m3\u001b[39m \u001b[38;5;75m4\u001b[39m \u001b[38;5;75m5\u001b[39m \u001b[38;5;75m6\u001b[39m \u001b[38;5;75m7\u001b[39m \u001b[38;5;75m8\u001b[39m \u001b[38;5;75m9\u001b[39m \u001b[38;5;75m10\u001b[39m\n\u001b[38;5;21mdo\u001b[39m\n  \u001b[38;5;0mecho\u001b[39m \u001b[38;5;0m$i\u001b[39m\n\u001b[38;5;21mdone\u001b[39m\n\n--------\nalgol\n--------\n\u001b[38;5;102m# basic loop\u001b[39m\n\u001b[01;04mfor\u001b[00m i in 1 2 3 4 5 6 7 8 9 10\n\u001b[01;04mdo\u001b[00m\n  \u001b[01mecho\u001b[00m \u001b[38;5;241;01m$i\u001b[39;00m\n\u001b[01;04mdone\u001b[00m\n\n--------\nalgol_nu\n--------\n\u001b[38;5;102m# basic loop\u001b[39m\n\u001b[01mfor\u001b[00m i in 1 2 3 4 5 6 7 8 9 10\n\u001b[01mdo\u001b[00m\n  \u001b[01mecho\u001b[00m \u001b[38;5;241;01m$i\u001b[39;00m\n\u001b[01mdone\u001b[00m\n\n--------\narduino\n--------\n\u001b[38;5;247m# basic loop\u001b[39m\n\u001b[38;5;64mfor\u001b[39m i in \u001b[38;5;101m1\u001b[39m \u001b[38;5;101m2\u001b[39m \u001b[38;5;101m3\u001b[39m \u001b[38;5;101m4\u001b[39m \u001b[38;5;101m5\u001b[39m \u001b[38;5;101m6\u001b[39m \u001b[38;5;101m7\u001b[39m \u001b[38;5;101m8\u001b[39m \u001b[38;5;101m9\u001b[39m \u001b[38;5;101m10\u001b[39m\n\u001b[38;5;64mdo\u001b[39m\n  \u001b[38;5;64mecho\u001b[39m \u001b[38;5;239m$i\u001b[39m\n\u001b[38;5;64mdone\u001b[39m\n\n--------\nautumn\n--------\n\u001b[38;5;248m# basic loop\u001b[39m\n\u001b[38;5;19mfor\u001b[39m i in \u001b[38;5;30m1\u001b[39m \u001b[38;5;30m2\u001b[39m \u001b[38;5;30m3\u001b[39m \u001b[38;5;30m4\u001b[39m \u001b[38;5;30m5\u001b[39m \u001b[38;5;30m6\u001b[39m \u001b[38;5;30m7\u001b[39m \u001b[38;5;30m8\u001b[39m \u001b[38;5;30m9\u001b[39m \u001b[38;5;30m10\u001b[39m\n\u001b[38;5;19mdo\u001b[39m\n  \u001b[38;5;37mecho\u001b[39m \u001b[38;5;124m$i\u001b[39m\n\u001b[38;5;19mdone\u001b[39m\n\n--------\nborland\n--------\n\u001b[38;5;28m# basic loop\u001b[39m\n\u001b[38;5;18;01mfor\u001b[39;00m i in \u001b[38;5;21m1\u001b[39m \u001b[38;5;21m2\u001b[39m \u001b[38;5;21m3\u001b[39m \u001b[38;5;21m4\u001b[39m \u001b[38;5;21m5\u001b[39m \u001b[38;5;21m6\u001b[39m \u001b[38;5;21m7\u001b[39m \u001b[38;5;21m8\u001b[39m \u001b[38;5;21m9\u001b[39m \u001b[38;5;21m10\u001b[39m\n\u001b[38;5;18;01mdo\u001b[39;00m\n  echo $i\n\u001b[38;5;18;01mdone\u001b[39;00m\n\n--------\nbw\n--------\n# basic loop\n\u001b[01mfor\u001b[00m i in 1 2 3 4 5 6 7 8 9 10\n\u001b[01mdo\u001b[00m\n  echo $i\n\u001b[01mdone\u001b[00m\n\n--------\ncolorful\n--------\n\u001b[38;5;102m# basic loop\u001b[39m\n\u001b[38;5;28;01mfor\u001b[39;00m i in \u001b[38;5;57;01m1\u001b[39;00m \u001b[38;5;57;01m2\u001b[39;00m \u001b[38;5;57;01m3\u001b[39;00m \u001b[38;5;57;01m4\u001b[39;00m \u001b[38;5;57;01m5\u001b[39;00m \u001b[38;5;57;01m6\u001b[39;00m \u001b[38;5;57;01m7\u001b[39;00m \u001b[38;5;57;01m8\u001b[39;00m \u001b[38;5;57;01m9\u001b[39;00m \u001b[38;5;57;01m10\u001b[39;00m\n\u001b[38;5;28;01mdo\u001b[39;00m\n  \u001b[38;5;22mecho\u001b[39m \u001b[38;5;95m$i\u001b[39m\n\u001b[38;5;28;01mdone\u001b[39;00m\n\n--------\ndefault\n--------\n\u001b[38;5;66m# basic loop\u001b[39m\n\u001b[38;5;28;01mfor\u001b[39;00m i in \u001b[38;5;241m1\u001b[39m \u001b[38;5;241m2\u001b[39m \u001b[38;5;241m3\u001b[39m \u001b[38;5;241m4\u001b[39m \u001b[38;5;241m5\u001b[39m \u001b[38;5;241m6\u001b[39m \u001b[38;5;241m7\u001b[39m \u001b[38;5;241m8\u001b[39m \u001b[38;5;241m9\u001b[39m \u001b[38;5;241m10\u001b[39m\n\u001b[38;5;28;01mdo\u001b[39;00m\n  \u001b[38;5;28mecho\u001b[39m \u001b[38;5;18m$i\u001b[39m\n\u001b[38;5;28;01mdone\u001b[39;00m\n\n--------\nemacs\n--------\n\u001b[38;5;28m# basic loop\u001b[39m\n\u001b[38;5;129;01mfor\u001b[39;00m i in \u001b[38;5;241m1\u001b[39m \u001b[38;5;241m2\u001b[39m \u001b[38;5;241m3\u001b[39m \u001b[38;5;241m4\u001b[39m \u001b[38;5;241m5\u001b[39m \u001b[38;5;241m6\u001b[39m \u001b[38;5;241m7\u001b[39m \u001b[38;5;241m8\u001b[39m \u001b[38;5;241m9\u001b[39m \u001b[38;5;241m10\u001b[39m\n\u001b[38;5;129;01mdo\u001b[39;00m\n  \u001b[38;5;129mecho\u001b[39m \u001b[38;5;136m$i\u001b[39m\n\u001b[38;5;129;01mdone\u001b[39;00m\n\n--------\nfriendly\n--------\n\u001b[38;5;73m# basic loop\u001b[39m\n\u001b[38;5;22;01mfor\u001b[39;00m i in \u001b[38;5;71m1\u001b[39m \u001b[38;5;71m2\u001b[39m \u001b[38;5;71m3\u001b[39m \u001b[38;5;71m4\u001b[39m \u001b[38;5;71m5\u001b[39m \u001b[38;5;71m6\u001b[39m \u001b[38;5;71m7\u001b[39m \u001b[38;5;71m8\u001b[39m \u001b[38;5;71m9\u001b[39m \u001b[38;5;71m10\u001b[39m\n\u001b[38;5;22;01mdo\u001b[39;00m\n  \u001b[38;5;22mecho\u001b[39m \u001b[38;5;134m$i\u001b[39m\n\u001b[38;5;22;01mdone\u001b[39;00m\n\n--------\nfruity\n--------\n\u001b[38;5;28;48;5;233m# basic loop\u001b[39;49m\n\u001b[38;5;202;01mfor\u001b[39;00m\u001b[38;5;15m \u001b[39m\u001b[38;5;15mi\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;15min\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;33;01m1\u001b[39;00m\u001b[38;5;15m \u001b[39m\u001b[38;5;33;01m2\u001b[39;00m\u001b[38;5;15m \u001b[39m\u001b[38;5;33;01m3\u001b[39;00m\u001b[38;5;15m \u001b[39m\u001b[38;5;33;01m4\u001b[39;00m\u001b[38;5;15m \u001b[39m\u001b[38;5;33;01m5\u001b[39;00m\u001b[38;5;15m \u001b[39m\u001b[38;5;33;01m6\u001b[39;00m\u001b[38;5;15m \u001b[39m\u001b[38;5;33;01m7\u001b[39;00m\u001b[38;5;15m \u001b[39m\u001b[38;5;33;01m8\u001b[39;00m\u001b[38;5;15m \u001b[39m\u001b[38;5;33;01m9\u001b[39;00m\u001b[38;5;15m \u001b[39m\u001b[38;5;33;01m10\u001b[39;00m\n\u001b[38;5;202;01mdo\u001b[39;00m\n\u001b[38;5;15m  \u001b[39m\u001b[38;5;15mecho\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;202m$i\u001b[39m\n\u001b[38;5;202;01mdone\u001b[39;00m\n\n--------\nigor\n--------\n\u001b[38;5;9m# basic loop\u001b[39m\n\u001b[38;5;21mfor\u001b[39m i in 1 2 3 4 5 6 7 8 9 10\n\u001b[38;5;21mdo\u001b[39m\n  echo $i\n\u001b[38;5;21mdone\u001b[39m\n\n--------\nlovelace\n--------\n\u001b[38;5;102m# basic loop\u001b[39m\n\u001b[38;5;25mfor\u001b[39m i in \u001b[38;5;238m1\u001b[39m \u001b[38;5;238m2\u001b[39m \u001b[38;5;238m3\u001b[39m \u001b[38;5;238m4\u001b[39m \u001b[38;5;238m5\u001b[39m \u001b[38;5;238m6\u001b[39m \u001b[38;5;238m7\u001b[39m \u001b[38;5;238m8\u001b[39m \u001b[38;5;238m9\u001b[39m \u001b[38;5;238m10\u001b[39m\n\u001b[38;5;25mdo\u001b[39m\n  \u001b[38;5;65mecho\u001b[39m \u001b[38;5;131m$i\u001b[39m\n\u001b[38;5;25mdone\u001b[39m\n\n--------\nmanni\n--------\n\u001b[38;5;33m# basic loop\u001b[39m\n\u001b[38;5;24;01mfor\u001b[39;00m i in \u001b[38;5;202m1\u001b[39m \u001b[38;5;202m2\u001b[39m \u001b[38;5;202m3\u001b[39m \u001b[38;5;202m4\u001b[39m \u001b[38;5;202m5\u001b[39m \u001b[38;5;202m6\u001b[39m \u001b[38;5;202m7\u001b[39m \u001b[38;5;202m8\u001b[39m \u001b[38;5;202m9\u001b[39m \u001b[38;5;202m10\u001b[39m\n\u001b[38;5;24;01mdo\u001b[39;00m\n  \u001b[38;5;240mecho\u001b[39m \u001b[38;5;235m$i\u001b[39m\n\u001b[38;5;24;01mdone\u001b[39;00m\n\n--------\nmonokai\n--------\n\u001b[38;5;242m# basic loop\u001b[39m\n\u001b[38;5;81mfor\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;15mi\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;15min\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;141m1\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;141m2\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;141m3\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;141m4\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;141m5\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;141m6\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;141m7\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;141m8\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;141m9\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;141m10\u001b[39m\n\u001b[38;5;81mdo\u001b[39m\n\u001b[38;5;15m  \u001b[39m\u001b[38;5;15mecho\u001b[39m\u001b[38;5;15m \u001b[39m\u001b[38;5;15m$i\u001b[39m\n\u001b[38;5;81mdone\u001b[39m\n\n--------\nmurphy\n--------\n\u001b[38;5;241m# basic loop\u001b[39m\n\u001b[38;5;30;01mfor\u001b[39;00m i in \u001b[38;5;57;01m1\u001b[39;00m \u001b[38;5;57;01m2\u001b[39;00m \u001b[38;5;57;01m3\u001b[39;00m \u001b[38;5;57;01m4\u001b[39;00m \u001b[38;5;57;01m5\u001b[39;00m \u001b[38;5;57;01m6\u001b[39;00m \u001b[38;5;57;01m7\u001b[39;00m \u001b[38;5;57;01m8\u001b[39;00m \u001b[38;5;57;01m9\u001b[39;00m \u001b[38;5;57;01m10\u001b[39;00m\n\u001b[38;5;30;01mdo\u001b[39;00m\n  \u001b[38;5;28mecho\u001b[39m \u001b[38;5;23m$i\u001b[39m\n\u001b[38;5;30;01mdone\u001b[39;00m\n\n--------\nnative\n--------\n\u001b[38;5;246m# basic loop\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252min\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m7\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m8\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m9\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\n\u001b[38;5;70;01mdo\u001b[39;00m\n\u001b[38;5;252m  \u001b[39m\u001b[38;5;31mecho\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;87m$i\u001b[39m\n\u001b[38;5;70;01mdone\u001b[39;00m\n\n--------\nparaiso-dark\n--------\n\u001b[38;5;243m# basic loop\u001b[39m\n\u001b[38;5;97mfor\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;7mi\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;7min\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;208m1\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;208m2\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;208m3\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;208m4\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;208m5\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;208m6\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;208m7\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;208m8\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;208m9\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;208m10\u001b[39m\n\u001b[38;5;97mdo\u001b[39m\n\u001b[38;5;7m  \u001b[39m\u001b[38;5;7mecho\u001b[39m\u001b[38;5;7m \u001b[39m\u001b[38;5;203m$i\u001b[39m\n\u001b[38;5;97mdone\u001b[39m\n\n--------\nparaiso-light\n--------\n\u001b[38;5;245m# basic loop\u001b[39m\n\u001b[38;5;97mfor\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;235mi\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;235min\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;208m1\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;208m2\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;208m3\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;208m4\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;208m5\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;208m6\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;208m7\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;208m8\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;208m9\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;208m10\u001b[39m\n\u001b[38;5;97mdo\u001b[39m\n\u001b[38;5;235m  \u001b[39m\u001b[38;5;235mecho\u001b[39m\u001b[38;5;235m \u001b[39m\u001b[38;5;203m$i\u001b[39m\n\u001b[38;5;97mdone\u001b[39m\n\n--------\npastie\n--------\n\u001b[38;5;102m# basic loop\u001b[39m\n\u001b[38;5;28;01mfor\u001b[39;00m i in \u001b[38;5;20;01m1\u001b[39;00m \u001b[38;5;20;01m2\u001b[39;00m \u001b[38;5;20;01m3\u001b[39;00m \u001b[38;5;20;01m4\u001b[39;00m \u001b[38;5;20;01m5\u001b[39;00m \u001b[38;5;20;01m6\u001b[39;00m \u001b[38;5;20;01m7\u001b[39;00m \u001b[38;5;20;01m8\u001b[39;00m \u001b[38;5;20;01m9\u001b[39;00m \u001b[38;5;20;01m10\u001b[39;00m\n\u001b[38;5;28;01mdo\u001b[39;00m\n  \u001b[38;5;24mecho\u001b[39m \u001b[38;5;60m$i\u001b[39m\n\u001b[38;5;28;01mdone\u001b[39;00m\n\n--------\nperldoc\n--------\n\u001b[38;5;28m# basic loop\u001b[39m\n\u001b[38;5;90;01mfor\u001b[39;00m i in \u001b[38;5;134m1\u001b[39m \u001b[38;5;134m2\u001b[39m \u001b[38;5;134m3\u001b[39m \u001b[38;5;134m4\u001b[39m \u001b[38;5;134m5\u001b[39m \u001b[38;5;134m6\u001b[39m \u001b[38;5;134m7\u001b[39m \u001b[38;5;134m8\u001b[39m \u001b[38;5;134m9\u001b[39m \u001b[38;5;134m10\u001b[39m\n\u001b[38;5;90;01mdo\u001b[39;00m\n  \u001b[38;5;64mecho\u001b[39m \u001b[38;5;24m$i\u001b[39m\n\u001b[38;5;90;01mdone\u001b[39;00m\n\n--------\nrainbow_dash\n--------\n\u001b[38;5;33m# basic loop\u001b[39m\n\u001b[38;5;26;01mfor\u001b[39;00m\u001b[38;5;239m \u001b[39m\u001b[38;5;239mi\u001b[39m\u001b[38;5;239m \u001b[39m\u001b[38;5;239min\u001b[39m\u001b[38;5;239m \u001b[39m\u001b[38;5;55;01m1\u001b[39;00m\u001b[38;5;239m \u001b[39m\u001b[38;5;55;01m2\u001b[39;00m\u001b[38;5;239m \u001b[39m\u001b[38;5;55;01m3\u001b[39;00m\u001b[38;5;239m \u001b[39m\u001b[38;5;55;01m4\u001b[39;00m\u001b[38;5;239m \u001b[39m\u001b[38;5;55;01m5\u001b[39;00m\u001b[38;5;239m \u001b[39m\u001b[38;5;55;01m6\u001b[39;00m\u001b[38;5;239m \u001b[39m\u001b[38;5;55;01m7\u001b[39;00m\u001b[38;5;239m \u001b[39m\u001b[38;5;55;01m8\u001b[39;00m\u001b[38;5;239m \u001b[39m\u001b[38;5;55;01m9\u001b[39;00m\u001b[38;5;239m \u001b[39m\u001b[38;5;55;01m10\u001b[39;00m\n\u001b[38;5;26;01mdo\u001b[39;00m\n\u001b[38;5;239m  \u001b[39m\u001b[38;5;55;01mecho\u001b[39;00m\u001b[38;5;239m \u001b[39m$i\n\u001b[38;5;26;01mdone\u001b[39;00m\n\n--------\nrrt\n--------\n\u001b[38;5;10m# basic loop\u001b[39m\n\u001b[38;5;9mfor\u001b[39m i in 1 2 3 4 5 6 7 8 9 10\n\u001b[38;5;9mdo\u001b[39m\n  echo \u001b[38;5;222m$i\u001b[39m\n\u001b[38;5;9mdone\u001b[39m\n\n--------\ntango\n--------\n\u001b[38;5;94m# basic loop\u001b[39m\n\u001b[38;5;24;01mfor\u001b[39;00m i in \u001b[38;5;20;01m1\u001b[39;00m \u001b[38;5;20;01m2\u001b[39;00m \u001b[38;5;20;01m3\u001b[39;00m \u001b[38;5;20;01m4\u001b[39;00m \u001b[38;5;20;01m5\u001b[39;00m \u001b[38;5;20;01m6\u001b[39;00m \u001b[38;5;20;01m7\u001b[39;00m \u001b[38;5;20;01m8\u001b[39;00m \u001b[38;5;20;01m9\u001b[39;00m \u001b[38;5;20;01m10\u001b[39;00m\n\u001b[38;5;24;01mdo\u001b[39;00m\n  \u001b[38;5;24mecho\u001b[39m \u001b[38;5;0m$i\u001b[39m\n\u001b[38;5;24;01mdone\u001b[39;00m\n\n--------\ntrac\n--------\n\u001b[38;5;246m# basic loop\u001b[39m\n\u001b[01mfor\u001b[00m i in \u001b[38;5;30m1\u001b[39m \u001b[38;5;30m2\u001b[39m \u001b[38;5;30m3\u001b[39m \u001b[38;5;30m4\u001b[39m \u001b[38;5;30m5\u001b[39m \u001b[38;5;30m6\u001b[39m \u001b[38;5;30m7\u001b[39m \u001b[38;5;30m8\u001b[39m \u001b[38;5;30m9\u001b[39m \u001b[38;5;30m10\u001b[39m\n\u001b[01mdo\u001b[00m\n  \u001b[38;5;246mecho\u001b[39m \u001b[38;5;30m$i\u001b[39m\n\u001b[01mdone\u001b[00m\n\n--------\nvim\n--------\n\u001b[38;5;18m# basic loop\u001b[39m\n\u001b[38;5;3mfor\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252min\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;5m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;5m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;5m3\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;5m4\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;5m5\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;5m6\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;5m7\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;5m8\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;5m9\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;5m10\u001b[39m\n\u001b[38;5;3mdo\u001b[39m\n\u001b[38;5;252m  \u001b[39m\u001b[38;5;5mecho\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;6m$i\u001b[39m\n\u001b[38;5;3mdone\u001b[39m\n\n--------\nvs\n--------\n\u001b[38;5;28m# basic loop\u001b[39m\n\u001b[38;5;21mfor\u001b[39m i in 1 2 3 4 5 6 7 8 9 10\n\u001b[38;5;21mdo\u001b[39m\n  echo $i\n\u001b[38;5;21mdone\u001b[39m\n\n--------\nxcode\n--------\n\u001b[38;5;28m# basic loop\u001b[39m\n\u001b[38;5;126mfor\u001b[39m i in \u001b[38;5;20m1\u001b[39m \u001b[38;5;20m2\u001b[39m \u001b[38;5;20m3\u001b[39m \u001b[38;5;20m4\u001b[39m \u001b[38;5;20m5\u001b[39m \u001b[38;5;20m6\u001b[39m \u001b[38;5;20m7\u001b[39m \u001b[38;5;20m8\u001b[39m \u001b[38;5;20m9\u001b[39m \u001b[38;5;20m10\u001b[39m\n\u001b[38;5;126mdo\u001b[39m\n  \u001b[38;5;126mecho\u001b[39m \u001b[38;5;0m$i\u001b[39m\n\u001b[38;5;126mdone\u001b[39m\n\n------------------------------------\n\nYou can test color styles with other cheat sheets using this script:\n\n    c=\"python/Advanced\"\n    for s in $(curl -s cheat.sh/:styles); do\n      echo\n      echo --------\n      echo $s\n      echo --------\n      curl -s cheat.sh/$c?style=$s | head -5\n    done\n\n"
  },
  {
    "path": "share/vim/.vimrc",
    "content": "filetype plugin on\n\nset expandtab\nset sts=4\nset ts=4\nset sw=4\nset smartindent\nsyn on\ncolorscheme desert\nmap ds :.,/^--/-1 d<CR>\nset nojs\nset viminfo='10,\\\"100,:20,%,n~/.viminfo\n\nlet g:NERDSpaceDelims = 1\nlet g:NERDCommentEmptyLines = 1\n\n"
  },
  {
    "path": "share/vim.txt",
    "content": "\" To use cheat.sh from your vim, install the cheat.sh-vim plugin from David Beniamine\n\" located at https://github.com/dbeniamine/cheat.sh-vim.\n\" See the page for the configuration options and the magic key combinations.\n\"\n\" ## Vizardry\n\"\n\" If you have Vizardry installed, you can run from vim:\n\" \n\"     Invoke -u dbeniamine cheat.sh-vim\n\" \n\" ## Vundle\n\"\n\" Add the following to your Vundle Plugin list and do InstallPlugins:\n\" \n\"     Plugin 'dbeniamine/cheat.sh-vim'\n\" \n\" ## Pathogen\n\"\n\" If you are using Pathogen, Run the following command in shell:\n\"\n\"     git clone https://github.com/dbeniamine/cheat.sh-vim.git ~/.vim/bundle/cheat.sh-vim\n\" \n\" ## Quick install\n\" \n\"     git clone https://github.com/dbeniamine/cheat.sh-vim.git\n\"     cd cheat.sh-vim/\n\"     cp -r ./* ~/.vim\n\n"
  },
  {
    "path": "share/zsh.txt",
    "content": "#compdef cht.sh\n\n__CHTSH_LANGS=($(curl -s cheat.sh/:list))\n_arguments -C \\\n  '--help[show this help message and exit]: :->noargs' \\\n  '--shell[enter shell repl]: :->noargs' \\\n  '1:Cheat Sheet:->lang' \\\n  '*::: :->noargs' && return 0\n\nif [[ CURRENT -ge 1 ]]; then\n    case $state in\n        noargs)\n             _message \"nothing to complete\";;\n        lang)\n             compadd -X \"Cheat Sheets\" ${__CHTSH_LANGS[@]};;\n        *)\n             _message \"Unknown state, error in autocomplete\";;\n    esac\n\n    return\nfi\n\n"
  },
  {
    "path": "tests/README.md",
    "content": "To run unit tests.\n\n    python3 -m pytest -v ../lib/\n\nTo run input/output tests.\n\n    ./run-tests.sh\n"
  },
  {
    "path": "tests/results/1",
    "content": "1_Inheritance\n1line\n2_Multiple_Inheritance\n:learn\n:list\nAdvanced\nClasses\nComments\nControl_Flow_and_Iterables\nFunctions\nModules\nPrimitive_Datatypes_and_Operators\nVariables_and_Collections\ndoc\nfunc\nhello\nlambda\nlist_comprehension\nloops\nrecursion\nrosetta/\n"
  },
  {
    "path": "tests/results/10",
    "content": "\u001b[38;5;246;03m#  How do I copy a file in Python?\u001b[39;00m\n\u001b[38;5;246;03m#  \u001b[39;00m\n\u001b[38;5;246;03m#  shutil (http://docs.python.org/3/library/shutil.html) has many methods\u001b[39;00m\n\u001b[38;5;246;03m#  you can use. One of which is:\u001b[39;00m\n\n\u001b[38;5;70;01mfrom\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mshutil\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mimport\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcopyfile\u001b[39m\n\n\u001b[38;5;252mcopyfile\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msrc\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdst\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;246;03m#  Copy the contents of the file named src to a file named dst. The\u001b[39;00m\n\u001b[38;5;246;03m#  destination location must be writable; otherwise, an IOError exception\u001b[39;00m\n\u001b[38;5;246;03m#  will be raised. If dst already exists, it will be replaced. Special\u001b[39;00m\n\u001b[38;5;246;03m#  files such as character or block devices and pipes cannot be copied\u001b[39;00m\n\u001b[38;5;246;03m#  with this function. src and dst are path names given as strings.\u001b[39;00m\n\u001b[38;5;246;03m#  \u001b[39;00m\n\u001b[38;5;246;03m#  [Swati] [so/q/123198] [cc by-sa 3.0]\u001b[39;00m\n"
  },
  {
    "path": "tests/results/11",
    "content": "\u001b[38;5;70;01mfrom\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mshutil\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mimport\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcopyfile\u001b[39m\n\n\u001b[38;5;252mcopyfile\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msrc\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdst\u001b[39m\u001b[38;5;252m)\u001b[39m\n"
  },
  {
    "path": "tests/results/12",
    "content": "from shutil import copyfile\n\ncopyfile(src, dst)\n"
  },
  {
    "path": "tests/results/13",
    "content": "      _                _         _    \u001b[38;2;0;204;0m_\u001b[0m\u001b[38;2;0;204;0m_\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m \u001b[0m                                     \n  ___| |__   ___  __ _| |_   ___| |__ \u001b[38;2;0;204;0m\\\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m\\\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m \u001b[0m \u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85mT\u001b[0m\u001b[48;2;85;85;85mh\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85mo\u001b[0m\u001b[48;2;85;85;85mn\u001b[0m\u001b[48;2;85;85;85ml\u001b[0m\u001b[48;2;85;85;85my\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85mc\u001b[0m\u001b[48;2;85;85;85mh\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85ma\u001b[0m\u001b[48;2;85;85;85mt\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85ms\u001b[0m\u001b[48;2;85;85;85mh\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85mt\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85my\u001b[0m\u001b[48;2;85;85;85mo\u001b[0m\u001b[48;2;85;85;85mu\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85mn\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85md\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85m \u001b[0m \n / __| '_ \\ / _ \\/ _` | __| / __| '_ \\ \u001b[38;2;0;204;0m\\\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m\\\u001b[0m\u001b[38;2;0;204;0m \u001b[0m    \u001b[38;2;136;136;136mU\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mf\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136ma\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mb\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m   \n| (__| | | |  __/ (_| | |_ _\\__ \\ | | |\u001b[38;2;0;204;0m/\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m/\u001b[0m\u001b[38;2;0;204;0m \u001b[0m    \u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mm\u001b[0m\u001b[38;2;136;136;136mm\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136my\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mv\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mm\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136ma\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m   \n \\___|_| |_|\\___|\\__,_|\\__(_)___/_| |_\u001b[38;2;0;204;0m/\u001b[0m\u001b[38;2;0;204;0m_\u001b[0m\u001b[38;2;0;204;0m/\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m \u001b[0m    \u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136mp\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mf\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mw\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136ml\u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m   \n                                                                                \n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mu\u001b[0m\u001b[38;2;0;204;0mr\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204me\u001b[0m\u001b[38;2;0;170;204ma\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0m.\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m \u001b[38;2;0;170;204mb\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204mf\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204mu\u001b[0m\u001b[38;2;0;170;204ma\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;204;0m:\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m\u001b[38;2;0;204;0me\u001b[0m\u001b[38;2;0;204;0ma\u001b[0m\u001b[38;2;0;204;0mr\u001b[0m\u001b[38;2;0;204;0mn\u001b[0m    \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mu\u001b[0m\u001b[38;2;0;204;0mr\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204mb\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204mf\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0m.\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m \u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204ma\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204m~\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204mi\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m Learn any\u001b[38;2;255;0;0m*\u001b[0m programming \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mu\u001b[0m\u001b[38;2;0;204;0mr\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204ma\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204m~\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204mi\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m language not leaving   \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mu\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m \u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0mp\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0m:\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m your shell             \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;255;0;0m*\u001b[0m\u001b[38;2;255;0;0m)\u001b[0m any of 60           \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mq\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mw\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mh\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mw\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mp\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m,\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m,\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m!\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204mg\u001b[0m\u001b[38;2;0;170;204mo\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204mf\u001b[0m\u001b[38;2;0;204;0m<\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0ma\u001b[0m\u001b[38;2;0;204;0mb\u001b[0m\u001b[38;2;0;204;0m>\u001b[0m\u001b[38;2;0;204;0m<\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0ma\u001b[0m\u001b[38;2;0;204;0mb\u001b[0m\u001b[38;2;0;204;0m>\u001b[0m\u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m \u001b[38;2;0;204;0m-\u001b[0m\u001b[38;2;0;204;0m-\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0me\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m       \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m \u001b[38;2;0;204;0mg\u001b[0m\u001b[38;2;0;204;0mo\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0mz\u001b[0m\u001b[38;2;0;204;0mi\u001b[0m\u001b[38;2;0;204;0mp\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0ml\u001b[0m\u001b[38;2;0;204;0mi\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m  \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m go/for   go/func       \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;34;170;34mc\u001b[0m\u001b[38;2;34;170;34mh\u001b[0m\u001b[38;2;34;170;34mt\u001b[0m\u001b[38;2;34;170;34m.\u001b[0m\u001b[38;2;34;170;34ms\u001b[0m\u001b[38;2;34;170;34mh\u001b[0m\u001b[38;2;34;170;34m>\u001b[0m help           \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m Ask any question using \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ cht.sh go/for        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m ...                    \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m cht.sh or curl cht.sh: \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m ...                    \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m /go\u001b[38;2;34;170;34m/\u001b[0mzip\u001b[38;2;34;170;34m+\u001b[0mlists          \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m (use \u001b[38;2;34;170;34m/\u001b[0m,\u001b[38;2;34;170;34m+\u001b[0m when curling) \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mT\u001b[0m\u001b[38;2;204;204;0mA\u001b[0m\u001b[38;2;204;204;0mB\u001b[0m\u001b[38;2;204;204;0m-\u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0mp\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mv\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0mh\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mp\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mg\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mg\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mq\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mu\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;204;0m:\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0me\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m\u001b[38;2;0;204;0mp\u001b[0m    \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mv\u001b[0m\u001b[38;2;0;204;0mi\u001b[0m\u001b[38;2;0;204;0mm\u001b[0m \u001b[38;2;0;170;204mp\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204mg\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204mp\u001b[0m\u001b[38;2;0;170;204my\u001b[0m           \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0mi\u001b[0m\u001b[38;2;0;204;0mm\u001b[0m\u001b[38;2;0;204;0me\u001b[0m curl cht.sh/    \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m see \u001b[38;2;34;170;34m/\u001b[0m\u001b[38;2;34;170;34m:\u001b[0m\u001b[38;2;34;170;34mh\u001b[0m\u001b[38;2;34;170;34me\u001b[0m\u001b[38;2;34;170;34ml\u001b[0m\u001b[38;2;34;170;34mp\u001b[0m and \u001b[38;2;34;170;34m/\u001b[0m\u001b[38;2;34;170;34m:\u001b[0m\u001b[38;2;34;170;34mi\u001b[0m\u001b[38;2;34;170;34mn\u001b[0m\u001b[38;2;34;170;34mt\u001b[0m\u001b[38;2;34;170;34mr\u001b[0m\u001b[38;2;34;170;34mo\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m ...                    \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m ...                    \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m for usage information  \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m zip lists _            \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m real    \u001b[38;2;34;170;34m0\u001b[0m\u001b[38;2;34;170;34mm\u001b[0m\u001b[38;2;34;170;34m0\u001b[0m\u001b[38;2;34;170;34m.\u001b[0m\u001b[38;2;34;170;34m0\u001b[0m\u001b[38;2;34;170;34m7\u001b[0m\u001b[38;2;34;170;34m5\u001b[0m\u001b[38;2;34;170;34ms\u001b[0m       \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m and README.md on \u001b[38;2;0;170;204mG\u001b[0m\u001b[38;2;0;170;204mi\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204mH\u001b[0m\u001b[38;2;0;170;204mu\u001b[0m\u001b[38;2;0;170;204mb\u001b[0m\u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;34;170;34m<\u001b[0m\u001b[38;2;34;170;34ml\u001b[0m\u001b[38;2;34;170;34me\u001b[0m\u001b[38;2;34;170;34ma\u001b[0m\u001b[38;2;34;170;34md\u001b[0m\u001b[38;2;34;170;34me\u001b[0m\u001b[38;2;34;170;34mr\u001b[0m\u001b[38;2;34;170;34m>\u001b[0m\u001b[38;2;34;170;34mK\u001b[0m\u001b[38;2;34;170;34mK\u001b[0m             \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m for the details        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m             *awesome*  \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m            \u001b[38;2;255;0;0m*\u001b[0m\u001b[38;2;255;0;0ms\u001b[0m\u001b[38;2;255;0;0mt\u001b[0m\u001b[38;2;255;0;0ma\u001b[0m\u001b[38;2;255;0;0mr\u001b[0m\u001b[38;2;255;0;0mt\u001b[0m\u001b[38;2;255;0;0m \u001b[0m\u001b[38;2;255;0;0mh\u001b[0m\u001b[38;2;255;0;0me\u001b[0m\u001b[38;2;255;0;0mr\u001b[0m\u001b[38;2;255;0;0me\u001b[0m\u001b[38;2;255;0;0m*\u001b[0m\u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0mf\u001b[0m\u001b[38;2;204;204;0m-\u001b[0m\u001b[38;2;204;204;0md\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0md\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0mq\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mf\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0md\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0m!\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0mw\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n                                                                                \n\u001b[38;2;136;136;136m[\u001b[0m\u001b[38;2;136;136;136mF\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136ml\u001b[0m\u001b[38;2;136;136;136ml\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mw\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m@\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mg\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136m_\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mb\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mf\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mp\u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136ma\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136m]\u001b[0m\u001b[38;2;136;136;136m[\u001b[0m\u001b[38;2;136;136;136mg\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mb\u001b[0m\u001b[38;2;136;136;136m.\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mm\u001b[0m\u001b[38;2;136;136;136m/\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mb\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136m/\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ma\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136m.\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136m]\u001b[0m                   \n"
  },
  {
    "path": "tests/results/14",
    "content": "      _                _         _    \u001b[38;2;0;204;0m_\u001b[0m\u001b[38;2;0;204;0m_\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m \u001b[0m                                     \n  ___| |__   ___  __ _| |_   ___| |__ \u001b[38;2;0;204;0m\\\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m\\\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m \u001b[0m \u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85mT\u001b[0m\u001b[48;2;85;85;85mh\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85mo\u001b[0m\u001b[48;2;85;85;85mn\u001b[0m\u001b[48;2;85;85;85ml\u001b[0m\u001b[48;2;85;85;85my\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85mc\u001b[0m\u001b[48;2;85;85;85mh\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85ma\u001b[0m\u001b[48;2;85;85;85mt\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85ms\u001b[0m\u001b[48;2;85;85;85mh\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85mt\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85my\u001b[0m\u001b[48;2;85;85;85mo\u001b[0m\u001b[48;2;85;85;85mu\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85mn\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85me\u001b[0m\u001b[48;2;85;85;85md\u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85m \u001b[0m\u001b[48;2;85;85;85m \u001b[0m \n / __| '_ \\ / _ \\/ _` | __| / __| '_ \\ \u001b[38;2;0;204;0m\\\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m\\\u001b[0m\u001b[38;2;0;204;0m \u001b[0m    \u001b[38;2;136;136;136mU\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mf\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136ma\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mb\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m   \n| (__| | | |  __/ (_| | |_ _\\__ \\ | | |\u001b[38;2;0;204;0m/\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m/\u001b[0m\u001b[38;2;0;204;0m \u001b[0m    \u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mm\u001b[0m\u001b[38;2;136;136;136mm\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136my\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mv\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mm\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136ma\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m   \n \\___|_| |_|\\___|\\__,_|\\__(_)___/_| |_\u001b[38;2;0;204;0m/\u001b[0m\u001b[38;2;0;204;0m_\u001b[0m\u001b[38;2;0;204;0m/\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0m \u001b[0m    \u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136mp\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mf\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mw\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136ml\u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m \u001b[0m   \n                                                                                \n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mu\u001b[0m\u001b[38;2;0;204;0mr\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204me\u001b[0m\u001b[38;2;0;170;204ma\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0m.\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m \u001b[38;2;0;170;204mb\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204mf\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204mu\u001b[0m\u001b[38;2;0;170;204ma\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;204;0m:\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m\u001b[38;2;0;204;0me\u001b[0m\u001b[38;2;0;204;0ma\u001b[0m\u001b[38;2;0;204;0mr\u001b[0m\u001b[38;2;0;204;0mn\u001b[0m    \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mu\u001b[0m\u001b[38;2;0;204;0mr\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204mb\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204mf\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0m.\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m \u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204ma\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204m~\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204mi\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m Learn any\u001b[38;2;255;0;0m*\u001b[0m programming \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mc\u001b[0m\u001b[38;2;0;204;0mu\u001b[0m\u001b[38;2;0;204;0mr\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204ma\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204m~\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204mi\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m language not leaving   \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mu\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m \u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0mp\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0m:\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m \u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m your shell             \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;255;0;0m*\u001b[0m\u001b[38;2;255;0;0m)\u001b[0m any of 60           \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mq\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mw\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mh\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mw\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mp\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m,\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m,\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m!\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204mg\u001b[0m\u001b[38;2;0;170;204mo\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;170;204mf\u001b[0m\u001b[38;2;0;204;0m<\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0ma\u001b[0m\u001b[38;2;0;204;0mb\u001b[0m\u001b[38;2;0;204;0m>\u001b[0m\u001b[38;2;0;204;0m<\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0ma\u001b[0m\u001b[38;2;0;204;0mb\u001b[0m\u001b[38;2;0;204;0m>\u001b[0m\u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m \u001b[38;2;0;204;0m-\u001b[0m\u001b[38;2;0;204;0m-\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0me\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m       \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m \u001b[38;2;0;204;0mg\u001b[0m\u001b[38;2;0;204;0mo\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0mz\u001b[0m\u001b[38;2;0;204;0mi\u001b[0m\u001b[38;2;0;204;0mp\u001b[0m\u001b[38;2;0;204;0m \u001b[0m\u001b[38;2;0;204;0ml\u001b[0m\u001b[38;2;0;204;0mi\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m\u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0ms\u001b[0m  \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m go/for   go/func       \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;34;170;34mc\u001b[0m\u001b[38;2;34;170;34mh\u001b[0m\u001b[38;2;34;170;34mt\u001b[0m\u001b[38;2;34;170;34m.\u001b[0m\u001b[38;2;34;170;34ms\u001b[0m\u001b[38;2;34;170;34mh\u001b[0m\u001b[38;2;34;170;34m>\u001b[0m help           \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m Ask any question using \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ cht.sh go/for        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m ...                    \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m cht.sh or curl cht.sh: \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m ...                    \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m /go\u001b[38;2;34;170;34m/\u001b[0mzip\u001b[38;2;34;170;34m+\u001b[0mlists          \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m (use \u001b[38;2;34;170;34m/\u001b[0m,\u001b[38;2;34;170;34m+\u001b[0m when curling) \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mT\u001b[0m\u001b[38;2;204;204;0mA\u001b[0m\u001b[38;2;204;204;0mB\u001b[0m\u001b[38;2;204;204;0m-\u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0mp\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mv\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0mh\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mp\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mg\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mg\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mq\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mu\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204ml\u001b[0m\u001b[38;2;0;170;204m \u001b[0m\u001b[38;2;0;170;204mc\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204ms\u001b[0m\u001b[38;2;0;170;204mh\u001b[0m\u001b[38;2;0;170;204m/\u001b[0m\u001b[38;2;0;204;0m:\u001b[0m\u001b[38;2;0;204;0mh\u001b[0m\u001b[38;2;0;204;0me\u001b[0m\u001b[38;2;0;204;0ml\u001b[0m\u001b[38;2;0;204;0mp\u001b[0m    \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mv\u001b[0m\u001b[38;2;0;204;0mi\u001b[0m\u001b[38;2;0;204;0mm\u001b[0m \u001b[38;2;0;170;204mp\u001b[0m\u001b[38;2;0;170;204mr\u001b[0m\u001b[38;2;0;170;204mg\u001b[0m\u001b[38;2;0;170;204m.\u001b[0m\u001b[38;2;0;170;204mp\u001b[0m\u001b[38;2;0;170;204my\u001b[0m           \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m $ \u001b[38;2;0;204;0mt\u001b[0m\u001b[38;2;0;204;0mi\u001b[0m\u001b[38;2;0;204;0mm\u001b[0m\u001b[38;2;0;204;0me\u001b[0m curl cht.sh/    \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m see \u001b[38;2;34;170;34m/\u001b[0m\u001b[38;2;34;170;34m:\u001b[0m\u001b[38;2;34;170;34mh\u001b[0m\u001b[38;2;34;170;34me\u001b[0m\u001b[38;2;34;170;34ml\u001b[0m\u001b[38;2;34;170;34mp\u001b[0m and \u001b[38;2;34;170;34m/\u001b[0m\u001b[38;2;34;170;34m:\u001b[0m\u001b[38;2;34;170;34mi\u001b[0m\u001b[38;2;34;170;34mn\u001b[0m\u001b[38;2;34;170;34mt\u001b[0m\u001b[38;2;34;170;34mr\u001b[0m\u001b[38;2;34;170;34mo\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m ...                    \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m ...                    \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m for usage information  \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m zip lists _            \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m real    \u001b[38;2;34;170;34m0\u001b[0m\u001b[38;2;34;170;34mm\u001b[0m\u001b[38;2;34;170;34m0\u001b[0m\u001b[38;2;34;170;34m.\u001b[0m\u001b[38;2;34;170;34m0\u001b[0m\u001b[38;2;34;170;34m7\u001b[0m\u001b[38;2;34;170;34m5\u001b[0m\u001b[38;2;34;170;34ms\u001b[0m       \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m and README.md on \u001b[38;2;0;170;204mG\u001b[0m\u001b[38;2;0;170;204mi\u001b[0m\u001b[38;2;0;170;204mt\u001b[0m\u001b[38;2;0;170;204mH\u001b[0m\u001b[38;2;0;170;204mu\u001b[0m\u001b[38;2;0;170;204mb\u001b[0m\u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;34;170;34m<\u001b[0m\u001b[38;2;34;170;34ml\u001b[0m\u001b[38;2;34;170;34me\u001b[0m\u001b[38;2;34;170;34ma\u001b[0m\u001b[38;2;34;170;34md\u001b[0m\u001b[38;2;34;170;34me\u001b[0m\u001b[38;2;34;170;34mr\u001b[0m\u001b[38;2;34;170;34m>\u001b[0m\u001b[38;2;34;170;34mK\u001b[0m\u001b[38;2;34;170;34mK\u001b[0m             \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m for the details        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m             *awesome*  \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m|\u001b[0m            \u001b[38;2;255;0;0m*\u001b[0m\u001b[38;2;255;0;0ms\u001b[0m\u001b[38;2;255;0;0mt\u001b[0m\u001b[38;2;255;0;0ma\u001b[0m\u001b[38;2;255;0;0mr\u001b[0m\u001b[38;2;255;0;0mt\u001b[0m\u001b[38;2;255;0;0m \u001b[0m\u001b[38;2;255;0;0mh\u001b[0m\u001b[38;2;255;0;0me\u001b[0m\u001b[38;2;255;0;0mr\u001b[0m\u001b[38;2;255;0;0me\u001b[0m\u001b[38;2;255;0;0m*\u001b[0m\u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m \u001b[38;2;136;136;136m|\u001b[0m                        \u001b[38;2;136;136;136m|\u001b[0m\n\u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ml\u001b[0m\u001b[38;2;204;204;0mf\u001b[0m\u001b[38;2;204;204;0m-\u001b[0m\u001b[38;2;204;204;0md\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mc\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0md\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0mq\u001b[0m\u001b[38;2;204;204;0mu\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0mf\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mm\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0md\u001b[0m\u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0mo\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0m!\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m \u001b[38;2;136;136;136m+\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m \u001b[38;2;204;204;0mi\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0mt\u001b[0m\u001b[38;2;204;204;0m \u001b[0m\u001b[38;2;204;204;0ma\u001b[0m\u001b[38;2;204;204;0mn\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m\u001b[38;2;204;204;0mw\u001b[0m\u001b[38;2;204;204;0me\u001b[0m\u001b[38;2;204;204;0mr\u001b[0m\u001b[38;2;204;204;0ms\u001b[0m \u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m-\u001b[0m\u001b[38;2;136;136;136m+\u001b[0m\n                                                                                \n\u001b[38;2;136;136;136m[\u001b[0m\u001b[38;2;136;136;136mF\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136ml\u001b[0m\u001b[38;2;136;136;136ml\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mw\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136m@\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mg\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136m_\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mb\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mf\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mr\u001b[0m\u001b[38;2;136;136;136m \u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mp\u001b[0m\u001b[38;2;136;136;136md\u001b[0m\u001b[38;2;136;136;136ma\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136m]\u001b[0m\u001b[38;2;136;136;136m[\u001b[0m\u001b[38;2;136;136;136mg\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mb\u001b[0m\u001b[38;2;136;136;136m.\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mo\u001b[0m\u001b[38;2;136;136;136mm\u001b[0m\u001b[38;2;136;136;136m/\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136mu\u001b[0m\u001b[38;2;136;136;136mb\u001b[0m\u001b[38;2;136;136;136mi\u001b[0m\u001b[38;2;136;136;136mn\u001b[0m\u001b[38;2;136;136;136m/\u001b[0m\u001b[38;2;136;136;136mc\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136me\u001b[0m\u001b[38;2;136;136;136ma\u001b[0m\u001b[38;2;136;136;136mt\u001b[0m\u001b[38;2;136;136;136m.\u001b[0m\u001b[38;2;136;136;136ms\u001b[0m\u001b[38;2;136;136;136mh\u001b[0m\u001b[38;2;136;136;136m]\u001b[0m                   \n"
  },
  {
    "path": "tests/results/15",
    "content": "\u001b[38;5;246;03m# Single line comments start with a number symbol.\u001b[39;00m\n\n\u001b[38;5;214m\"\"\" Multiline strings can be written\u001b[39m\n\u001b[38;5;214m    using three \"s, and are often used\u001b[39m\n\u001b[38;5;214m    as documentation.\u001b[39m\n\u001b[38;5;214m\"\"\"\u001b[39m\n\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\u001b[38;5;246;03m## 1. Primitive Datatypes and Operators\u001b[39;00m\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\n\u001b[38;5;246;03m# You have numbers\u001b[39;00m\n\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 3\u001b[39;00m\n\n\u001b[38;5;246;03m# Math is what you would expect\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => 2\u001b[39;00m\n\u001b[38;5;67m8\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => 7\u001b[39;00m\n\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 20\u001b[39;00m\n\u001b[38;5;67m35\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 7.0\u001b[39;00m\n\n\u001b[38;5;246;03m# Integer division rounds down for both positive and negative numbers.\u001b[39;00m\n\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m       \u001b[39m\u001b[38;5;246;03m# => 1\u001b[39;00m\n\u001b[38;5;252m-\u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m      \u001b[39m\u001b[38;5;246;03m# => -2\u001b[39;00m\n\u001b[38;5;67m5.0\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3.0\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => 1.0 # works on floats too\u001b[39;00m\n\u001b[38;5;252m-\u001b[39m\u001b[38;5;67m5.0\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3.0\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => -2.0\u001b[39;00m\n\n\u001b[38;5;246;03m# The result of division is always a float\u001b[39;00m\n\u001b[38;5;67m10.0\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 3.3333333333333335\u001b[39;00m\n\n\u001b[38;5;246;03m# Modulo operation\u001b[39;00m\n\u001b[38;5;67m7\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m%\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => 1\u001b[39;00m\n\u001b[38;5;246;03m# i % j have the same sign as j, unlike C\u001b[39;00m\n\u001b[38;5;252m-\u001b[39m\u001b[38;5;67m7\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m%\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 2\u001b[39;00m\n\n\u001b[38;5;246;03m# Exponentiation (x**y, x to the yth power)\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 8\u001b[39;00m\n\n\u001b[38;5;246;03m# Enforce precedence with parentheses\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# => 7\u001b[39;00m\n\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 8\u001b[39;00m\n\n\u001b[38;5;246;03m# Boolean values are primitives (Note: the capitalization)\u001b[39;00m\n\u001b[38;5;70;01mTrue\u001b[39;00m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;70;01mFalse\u001b[39;00m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\n\u001b[38;5;246;03m# negate with not\u001b[39;00m\n\u001b[38;5;70;01mnot\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mTrue\u001b[39;00m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\u001b[38;5;70;01mnot\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mFalse\u001b[39;00m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\n\u001b[38;5;246;03m# Boolean Operators\u001b[39;00m\n\u001b[38;5;246;03m# Note \"and\" and \"or\" are case-sensitive\u001b[39;00m\n\u001b[38;5;70;01mTrue\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mand\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mFalse\u001b[39;00m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\u001b[38;5;70;01mFalse\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mTrue\u001b[39;00m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\n\u001b[38;5;246;03m# True and False are actually 1 and 0 but with different keywords\u001b[39;00m\n\u001b[38;5;70;01mTrue\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mTrue\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# => 2\u001b[39;00m\n\u001b[38;5;70;01mTrue\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m8\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# => 8\u001b[39;00m\n\u001b[38;5;70;01mFalse\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => -5\u001b[39;00m\n\n\u001b[38;5;246;03m# Comparison operators look at the numerical value of True and False\u001b[39;00m\n\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mFalse\u001b[39;00m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mTrue\u001b[39;00m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mTrue\u001b[39;00m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\u001b[38;5;252m-\u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m!=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mFalse\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\n\u001b[38;5;246;03m# Using boolean logical operators on ints casts them to booleans for evaluation, but their non-cast value is returned\u001b[39;00m\n\u001b[38;5;246;03m# Don't mix up with bool(ints) and bitwise and/or (&,|)\u001b[39;00m\n\u001b[38;5;31mbool\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m     \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\u001b[38;5;31mbool\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m     \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;31mbool\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mand\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m     \u001b[39m\u001b[38;5;246;03m# => 0\u001b[39;00m\n\u001b[38;5;252m-\u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m     \u001b[39m\u001b[38;5;246;03m# => -5\u001b[39;00m\n\n\u001b[38;5;246;03m# Equality is ==\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\n\u001b[38;5;246;03m# Inequality is !=\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m!=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m!=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\n\u001b[38;5;246;03m# More comparisons\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\n\u001b[38;5;246;03m# Seeing whether a value is in a range\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mand\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mand\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\u001b[38;5;246;03m# Chaining makes this look nicer\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\n\u001b[38;5;246;03m# (is vs. ==) is checks if two variables refer to the same object, but == checks\u001b[39;00m\n\u001b[38;5;246;03m# if the objects pointed to have the same values.\u001b[39;00m\n\u001b[38;5;252ma\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Point a at a new list, [1, 2, 3, 4]\u001b[39;00m\n\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ma\u001b[39m\u001b[38;5;252m             \u001b[39m\u001b[38;5;246;03m# Point b at what a is pointing to\u001b[39;00m\n\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mis\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ma\u001b[39m\u001b[38;5;252m            \u001b[39m\u001b[38;5;246;03m# => True, a and b refer to the same object\u001b[39;00m\n\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ma\u001b[39m\u001b[38;5;252m            \u001b[39m\u001b[38;5;246;03m# => True, a's and b's objects are equal\u001b[39;00m\n\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Point b at a new list, [1, 2, 3, 4]\u001b[39;00m\n\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mis\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ma\u001b[39m\u001b[38;5;252m            \u001b[39m\u001b[38;5;246;03m# => False, a and b do not refer to the same object\u001b[39;00m\n\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ma\u001b[39m\u001b[38;5;252m            \u001b[39m\u001b[38;5;246;03m# => True, a's and b's objects are equal\u001b[39;00m\n\n\u001b[38;5;246;03m# Strings are created with \" or '\u001b[39;00m\n\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mThis is a string.\u001b[39m\u001b[38;5;214m\"\u001b[39m\n\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mThis is also a string.\u001b[39m\u001b[38;5;214m'\u001b[39m\n\n\u001b[38;5;246;03m# Strings can be added too\u001b[39;00m\n\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mHello \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mworld!\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => \"Hello world!\"\u001b[39;00m\n\u001b[38;5;246;03m# String literals (but not variables) can be concatenated without using '+'\u001b[39;00m\n\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mHello \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mworld!\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# => \"Hello world!\"\u001b[39;00m\n\n\u001b[38;5;246;03m# A string can be treated like a list of characters\u001b[39;00m\n\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mHello world!\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 'H'\u001b[39;00m\n\n\u001b[38;5;246;03m# You can find the length of a string\u001b[39;00m\n\u001b[38;5;31mlen\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mThis is a string\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 16\u001b[39;00m\n\n\u001b[38;5;246;03m# You can also format using f-strings or formatted string literals (in Python 3.6+)\u001b[39;00m\n\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mReiko\u001b[39m\u001b[38;5;214m\"\u001b[39m\n\u001b[38;5;214mf\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mShe said her name is \u001b[39m\u001b[38;5;214m{\u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;214m}\u001b[39m\u001b[38;5;214m.\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# => \"She said her name is Reiko\"\u001b[39;00m\n\u001b[38;5;246;03m# You can basically put any Python expression inside the braces and it will be output in the string.\u001b[39;00m\n\u001b[38;5;214mf\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m{\u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;214m}\u001b[39m\u001b[38;5;214m is \u001b[39m\u001b[38;5;214m{\u001b[39m\u001b[38;5;31mlen\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;214m}\u001b[39m\u001b[38;5;214m characters long.\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# => \"Reiko is 5 characters long.\"\u001b[39;00m\n\n\u001b[38;5;246;03m# None is an object\u001b[39;00m\n\u001b[38;5;70;01mNone\u001b[39;00m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => None\u001b[39;00m\n\n\u001b[38;5;246;03m# Don't use the equality \"==\" symbol to compare objects to None\u001b[39;00m\n\u001b[38;5;246;03m# Use \"is\" instead. This checks for equality of object identity.\u001b[39;00m\n\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214metc\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mis\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mNone\u001b[39;00m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\u001b[38;5;70;01mNone\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mis\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mNone\u001b[39;00m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\n\u001b[38;5;246;03m# None, 0, and empty strings/lists/dicts/tuples all evaluate to False.\u001b[39;00m\n\u001b[38;5;246;03m# All other values are True\u001b[39;00m\n\u001b[38;5;31mbool\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\u001b[38;5;31mbool\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\u001b[38;5;31mbool\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\u001b[38;5;31mbool\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\u001b[38;5;31mbool\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\u001b[38;5;246;03m## 2. Variables and Collections\u001b[39;00m\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\n\u001b[38;5;246;03m# Python has a print function\u001b[39;00m\n\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mI\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mm Python. Nice to meet you!\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => I'm Python. Nice to meet you!\u001b[39;00m\n\n\u001b[38;5;246;03m# By default the print function also prints out a newline at the end.\u001b[39;00m\n\u001b[38;5;246;03m# Use the optional argument end to change the end string.\u001b[39;00m\n\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mHello, World\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mend\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m!\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => Hello, World!\u001b[39;00m\n\n\u001b[38;5;246;03m# Simple way to get input data from console\u001b[39;00m\n\u001b[38;5;252minput_string_var\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;31minput\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mEnter some data: \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# Returns the data as a string\u001b[39;00m\n\n\u001b[38;5;246;03m# There are no declarations, only assignments.\u001b[39;00m\n\u001b[38;5;246;03m# Convention is to use lower_case_with_underscores\u001b[39;00m\n\u001b[38;5;252msome_var\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\n\u001b[38;5;252msome_var\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 5\u001b[39;00m\n\n\u001b[38;5;246;03m# Accessing a previously unassigned variable is an exception.\u001b[39;00m\n\u001b[38;5;246;03m# See Control Flow to learn more about exception handling.\u001b[39;00m\n\u001b[38;5;252msome_unknown_var\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Raises a NameError\u001b[39;00m\n\n\u001b[38;5;246;03m# if can be used as an expression\u001b[39;00m\n\u001b[38;5;246;03m# Equivalent of C's '?:' ternary operator\u001b[39;00m\n\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214myay!\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01melse\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mnay!\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => \"nay!\"\u001b[39;00m\n\n\u001b[38;5;246;03m# Lists store sequences\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252m]\u001b[39m\n\u001b[38;5;246;03m# You can start with a prefilled list\u001b[39;00m\n\u001b[38;5;252mother_li\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m]\u001b[39m\n\n\u001b[38;5;246;03m# Add stuff to the end of a list with append\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mappend\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# li is now [1]\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mappend\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# li is now [1, 2]\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mappend\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# li is now [1, 2, 4]\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mappend\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# li is now [1, 2, 4, 3]\u001b[39;00m\n\u001b[38;5;246;03m# Remove from the end with pop\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mpop\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# => 3 and li is now [1, 2, 4]\u001b[39;00m\n\u001b[38;5;246;03m# Let's put it back\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mappend\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# li is now [1, 2, 4, 3] again.\u001b[39;00m\n\n\u001b[38;5;246;03m# Access a list like you would any array\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => 1\u001b[39;00m\n\u001b[38;5;246;03m# Look at the last element\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 3\u001b[39;00m\n\n\u001b[38;5;246;03m# Looking out of bounds is an IndexError\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Raises an IndexError\u001b[39;00m\n\n\u001b[38;5;246;03m# You can look at ranges with slice syntax.\u001b[39;00m\n\u001b[38;5;246;03m# The start index is included, the end index is not\u001b[39;00m\n\u001b[38;5;246;03m# (It's a closed/open range for you mathy types.)\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# Return list from index 1 to 3 => [2, 4]\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Return list starting from index 2 => [4, 3]\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Return list from beginning until index 3  => [1, 2, 4]\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# Return list selecting every second entry => [1, 4]\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Return list in reverse order => [3, 4, 2, 1]\u001b[39;00m\n\u001b[38;5;246;03m# Use any combination of these to make advanced slices\u001b[39;00m\n\u001b[38;5;246;03m# li[start:end:step]\u001b[39;00m\n\n\u001b[38;5;246;03m# Make a one layer deep copy using slices\u001b[39;00m\n\u001b[38;5;252mli2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => li2 = [1, 2, 4, 3] but (li2 is li) will result in false.\u001b[39;00m\n\n\u001b[38;5;246;03m# Remove arbitrary elements from a list with \"del\"\u001b[39;00m\n\u001b[38;5;70;01mdel\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# li is now [1, 2, 3]\u001b[39;00m\n\n\u001b[38;5;246;03m# Remove first occurrence of a value\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mremove\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# li is now [1, 3]\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mremove\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Raises a ValueError as 2 is not in the list\u001b[39;00m\n\n\u001b[38;5;246;03m# Insert an element at a specific index\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252minsert\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# li is now [1, 2, 3] again\u001b[39;00m\n\n\u001b[38;5;246;03m# Get the index of the first item found matching the argument\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mindex\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 1\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mindex\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Raises a ValueError as 4 is not in the list\u001b[39;00m\n\n\u001b[38;5;246;03m# You can add lists\u001b[39;00m\n\u001b[38;5;246;03m# Note: values for li and for other_li are not modified.\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mother_li\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => [1, 2, 3, 4, 5, 6]\u001b[39;00m\n\n\u001b[38;5;246;03m# Concatenate lists with \"extend()\"\u001b[39;00m\n\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mextend\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mother_li\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Now li is [1, 2, 3, 4, 5, 6]\u001b[39;00m\n\n\u001b[38;5;246;03m# Check for existence in a list with \"in\"\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\n\u001b[38;5;246;03m# Examine the length with \"len()\"\u001b[39;00m\n\u001b[38;5;31mlen\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mli\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 6\u001b[39;00m\n\n\n\u001b[38;5;246;03m# Tuples are like lists but are immutable.\u001b[39;00m\n\u001b[38;5;252mtup\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252mtup\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m      \u001b[39m\u001b[38;5;246;03m# => 1\u001b[39;00m\n\u001b[38;5;252mtup\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Raises a TypeError\u001b[39;00m\n\n\u001b[38;5;246;03m# Note that a tuple of length one has to have a comma after the last element but\u001b[39;00m\n\u001b[38;5;246;03m# tuples of other lengths, even zero, do not.\u001b[39;00m\n\u001b[38;5;31mtype\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => <class 'int'>\u001b[39;00m\n\u001b[38;5;31mtype\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => <class 'tuple'>\u001b[39;00m\n\u001b[38;5;31mtype\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# => <class 'tuple'>\u001b[39;00m\n\n\u001b[38;5;246;03m# You can do most of the list operations on tuples too\u001b[39;00m\n\u001b[38;5;31mlen\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mtup\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m         \u001b[39m\u001b[38;5;246;03m# => 3\u001b[39;00m\n\u001b[38;5;252mtup\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => (1, 2, 3, 4, 5, 6)\u001b[39;00m\n\u001b[38;5;252mtup\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m          \u001b[39m\u001b[38;5;246;03m# => (1, 2)\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtup\u001b[39m\u001b[38;5;252m         \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\n\u001b[38;5;246;03m# You can unpack tuples (or lists) into variables\u001b[39;00m\n\u001b[38;5;252ma\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# a is now 1, b is now 2 and c is now 3\u001b[39;00m\n\u001b[38;5;246;03m# You can also do extended unpacking\u001b[39;00m\n\u001b[38;5;252ma\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# a is now 1, b is now [2, 3] and c is now 4\u001b[39;00m\n\u001b[38;5;246;03m# Tuples are created by default if you leave out the parentheses\u001b[39;00m\n\u001b[38;5;252md\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252me\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mf\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# tuple 4, 5, 6 is unpacked into variables d, e and f\u001b[39;00m\n\u001b[38;5;246;03m# respectively such that d = 4, e = 5 and f = 6\u001b[39;00m\n\u001b[38;5;246;03m# Now look how easy it is to swap two values\u001b[39;00m\n\u001b[38;5;252me\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252md\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252md\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252me\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# d is now 5 and e is now 4\u001b[39;00m\n\n\n\u001b[38;5;246;03m# Dictionaries store mappings from keys to values\u001b[39;00m\n\u001b[38;5;252mempty_dict\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;246;03m# Here is a prefilled dictionary\u001b[39;00m\n\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mone\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mtwo\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mthree\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m# Note keys for dictionaries have to be immutable types. This is to ensure that\u001b[39;00m\n\u001b[38;5;246;03m# the key can be converted to a constant hash value for quick look-ups.\u001b[39;00m\n\u001b[38;5;246;03m# Immutable types include ints, floats, strings, tuples.\u001b[39;00m\n\u001b[38;5;252minvalid_dict\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m123\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => Raises a TypeError: unhashable type: 'list'\u001b[39;00m\n\u001b[38;5;252mvalid_dict\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# Values can be of any type, however.\u001b[39;00m\n\n\u001b[38;5;246;03m# Look up values with []\u001b[39;00m\n\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mone\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 1\u001b[39;00m\n\n\u001b[38;5;246;03m# Get all keys as an iterable with \"keys()\". We need to wrap the call in list()\u001b[39;00m\n\u001b[38;5;246;03m# to turn it into a list. We'll talk about those later.  Note - for Python\u001b[39;00m\n\u001b[38;5;246;03m# versions <3.7, dictionary key ordering is not guaranteed. Your results might\u001b[39;00m\n\u001b[38;5;246;03m# not match the example below exactly. However, as of Python 3.7, dictionary\u001b[39;00m\n\u001b[38;5;246;03m# items maintain the order at which they are inserted into the dictionary.\u001b[39;00m\n\u001b[38;5;31mlist\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mkeys\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => [\"three\", \"two\", \"one\"] in Python <3.7\u001b[39;00m\n\u001b[38;5;31mlist\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mkeys\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => [\"one\", \"two\", \"three\"] in Python 3.7+\u001b[39;00m\n\n\n\u001b[38;5;246;03m# Get all values as an iterable with \"values()\". Once again we need to wrap it\u001b[39;00m\n\u001b[38;5;246;03m# in list() to get it out of the iterable. Note - Same as above regarding key\u001b[39;00m\n\u001b[38;5;246;03m# ordering.\u001b[39;00m\n\u001b[38;5;31mlist\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mvalues\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => [3, 2, 1]  in Python <3.7\u001b[39;00m\n\u001b[38;5;31mlist\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mvalues\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => [1, 2, 3] in Python 3.7+\u001b[39;00m\n\n\u001b[38;5;246;03m# Check for existence of keys in a dictionary with \"in\"\u001b[39;00m\n\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mone\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m      \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\n\u001b[38;5;246;03m# Looking up a non-existing key is a KeyError\u001b[39;00m\n\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mfour\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# KeyError\u001b[39;00m\n\n\u001b[38;5;246;03m# Use \"get()\" method to avoid the KeyError\u001b[39;00m\n\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mget\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mone\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m      \u001b[39m\u001b[38;5;246;03m# => 1\u001b[39;00m\n\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mget\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mfour\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m     \u001b[39m\u001b[38;5;246;03m# => None\u001b[39;00m\n\u001b[38;5;246;03m# The get method supports a default argument when the value is missing\u001b[39;00m\n\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mget\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mone\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => 1\u001b[39;00m\n\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mget\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mfour\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 4\u001b[39;00m\n\n\u001b[38;5;246;03m# \"setdefault()\" inserts into a dictionary only if the given key isn't present\u001b[39;00m\n\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msetdefault\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mfive\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# filled_dict[\"five\"] is set to 5\u001b[39;00m\n\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msetdefault\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mfive\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# filled_dict[\"five\"] is still 5\u001b[39;00m\n\n\u001b[38;5;246;03m# Adding to a dictionary\u001b[39;00m\n\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mupdate\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mfour\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => {\"one\": 1, \"two\": 2, \"three\": 3, \"four\": 4}\u001b[39;00m\n\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mfour\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m         \u001b[39m\u001b[38;5;246;03m# another way to add to dict\u001b[39;00m\n\n\u001b[38;5;246;03m# Remove keys from a dictionary with del\u001b[39;00m\n\u001b[38;5;70;01mdel\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mone\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Removes the key \"one\" from filled dict\u001b[39;00m\n\n\u001b[38;5;246;03m# From Python 3.5 you can also use the additional unpacking options\u001b[39;00m\n\u001b[38;5;252m{\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214ma\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mb\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => {'a': 1, 'b': 2}\u001b[39;00m\n\u001b[38;5;252m{\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214ma\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214ma\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => {'a': 2}\u001b[39;00m\n\n\n\n\u001b[38;5;246;03m# Sets store ... well sets\u001b[39;00m\n\u001b[38;5;252mempty_set\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mset\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;246;03m# Initialize a set with a bunch of values. Yeah, it looks a bit like a dict. Sorry.\u001b[39;00m\n\u001b[38;5;252msome_set\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# some_set is now {1, 2, 3, 4}\u001b[39;00m\n\n\u001b[38;5;246;03m# Similar to keys of a dictionary, elements of a set have to be immutable.\u001b[39;00m\n\u001b[38;5;252minvalid_set\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => Raises a TypeError: unhashable type: 'list'\u001b[39;00m\n\u001b[38;5;252mvalid_set\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m# Add one more item to the set\u001b[39;00m\n\u001b[38;5;252mfilled_set\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msome_set\u001b[39m\n\u001b[38;5;252mfilled_set\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252madd\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# filled_set is now {1, 2, 3, 4, 5}\u001b[39;00m\n\u001b[38;5;246;03m# Sets do not have duplicate elements\u001b[39;00m\n\u001b[38;5;252mfilled_set\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252madd\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# it remains as before {1, 2, 3, 4, 5}\u001b[39;00m\n\n\u001b[38;5;246;03m# Do set intersection with &\u001b[39;00m\n\u001b[38;5;252mother_set\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252mfilled_set\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m&\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mother_set\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => {3, 4, 5}\u001b[39;00m\n\n\u001b[38;5;246;03m# Do set union with |\u001b[39;00m\n\u001b[38;5;252mfilled_set\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m|\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mother_set\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => {1, 2, 3, 4, 5, 6}\u001b[39;00m\n\n\u001b[38;5;246;03m# Do set difference with -\u001b[39;00m\n\u001b[38;5;252m{\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => {1, 4}\u001b[39;00m\n\n\u001b[38;5;246;03m# Do set symmetric difference with ^\u001b[39;00m\n\u001b[38;5;252m{\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m^\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => {1, 4, 5}\u001b[39;00m\n\n\u001b[38;5;246;03m# Check if set on the left is a superset of set on the right\u001b[39;00m\n\u001b[38;5;252m{\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\n\u001b[38;5;246;03m# Check if set on the left is a subset of set on the right\u001b[39;00m\n\u001b[38;5;252m{\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\n\u001b[38;5;246;03m# Check for existence in a set with in\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfilled_set\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfilled_set\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\n\u001b[38;5;246;03m# Make a one layer deep copy\u001b[39;00m\n\u001b[38;5;252mfilled_set\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msome_set\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcopy\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# filled_set is {1, 2, 3, 4, 5}\u001b[39;00m\n\u001b[38;5;252mfilled_set\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mis\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msome_set\u001b[39m\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# => False\u001b[39;00m\n\n\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\u001b[38;5;246;03m## 3. Control Flow and Iterables\u001b[39;00m\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\n\u001b[38;5;246;03m# Let's just make a variable\u001b[39;00m\n\u001b[38;5;252msome_var\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\n\n\u001b[38;5;246;03m# Here is an if statement. Indentation is significant in Python!\u001b[39;00m\n\u001b[38;5;246;03m# Convention is to use four spaces, not tabs.\u001b[39;00m\n\u001b[38;5;246;03m# This prints \"some_var is smaller than 10\"\u001b[39;00m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msome_var\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214msome_var is totally bigger than 10.\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;70;01melif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msome_var\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# This elif clause is optional.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214msome_var is smaller than 10.\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;70;01melse\u001b[39;00m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m                  \u001b[39m\u001b[38;5;246;03m# This is optional too.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214msome_var is indeed 10.\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;214mFor loops iterate over lists\u001b[39m\n\u001b[38;5;214mprints:\u001b[39m\n\u001b[38;5;214m    dog is a mammal\u001b[39m\n\u001b[38;5;214m    cat is a mammal\u001b[39m\n\u001b[38;5;214m    mouse is a mammal\u001b[39m\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252manimal\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mdog\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mcat\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mmouse\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# You can use format() to interpolate formatted strings\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m{}\u001b[39m\u001b[38;5;214m is a mammal\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mformat\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252manimal\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;214m\"range(number)\" returns an iterable of numbers\u001b[39m\n\u001b[38;5;214mfrom zero to the given number\u001b[39m\n\u001b[38;5;214mprints:\u001b[39m\n\u001b[38;5;214m    0\u001b[39m\n\u001b[38;5;214m    1\u001b[39m\n\u001b[38;5;214m    2\u001b[39m\n\u001b[38;5;214m    3\u001b[39m\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mrange\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;214m\"range(lower, upper)\" returns an iterable of numbers\u001b[39m\n\u001b[38;5;214mfrom the lower number to the upper number\u001b[39m\n\u001b[38;5;214mprints:\u001b[39m\n\u001b[38;5;214m    4\u001b[39m\n\u001b[38;5;214m    5\u001b[39m\n\u001b[38;5;214m    6\u001b[39m\n\u001b[38;5;214m    7\u001b[39m\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mrange\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m8\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;214m\"range(lower, upper, step)\" returns an iterable of numbers\u001b[39m\n\u001b[38;5;214mfrom the lower number to the upper number, while incrementing\u001b[39m\n\u001b[38;5;214mby step. If step is not indicated, the default value is 1.\u001b[39m\n\u001b[38;5;214mprints:\u001b[39m\n\u001b[38;5;214m    4\u001b[39m\n\u001b[38;5;214m    6\u001b[39m\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mrange\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m8\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;214mTo loop over a list, and retrieve both the index and the value of each item in the list\u001b[39m\n\u001b[38;5;214mprints:\u001b[39m\n\u001b[38;5;214m    0 dog\u001b[39m\n\u001b[38;5;214m    1 cat\u001b[39m\n\u001b[38;5;214m    2 mouse\u001b[39m\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;252manimals\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mdog\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mcat\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mmouse\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m]\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvalue\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31menumerate\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252manimals\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvalue\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;214mWhile loops go until a condition is no longer met.\u001b[39m\n\u001b[38;5;214mprints:\u001b[39m\n\u001b[38;5;214m    0\u001b[39m\n\u001b[38;5;214m    1\u001b[39m\n\u001b[38;5;214m    2\u001b[39m\n\u001b[38;5;214m    3\u001b[39m\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\n\u001b[38;5;70;01mwhile\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Shorthand for x = x + 1\u001b[39;00m\n\n\u001b[38;5;246;03m# Handle exceptions with a try/except block\u001b[39;00m\n\u001b[38;5;70;01mtry\u001b[39;00m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Use \"raise\" to raise an error\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mraise\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;250mIndexError\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mThis is an index error\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;70;01mexcept\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;250mIndexError\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mas\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252me\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mpass\u001b[39;00m\u001b[38;5;252m                 \u001b[39m\u001b[38;5;246;03m# Pass is just a no-op. Usually you would do recovery here.\u001b[39;00m\n\u001b[38;5;70;01mexcept\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;250mTypeError\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;250mNameError\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mpass\u001b[39;00m\u001b[38;5;252m                 \u001b[39m\u001b[38;5;246;03m# Multiple exceptions can be handled together, if required.\u001b[39;00m\n\u001b[38;5;70;01melse\u001b[39;00m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m                    \u001b[39m\u001b[38;5;246;03m# Optional clause to the try/except block. Must follow all except blocks\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mAll good!\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# Runs only if the code in try raises no exceptions\u001b[39;00m\n\u001b[38;5;70;01mfinally\u001b[39;00m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m                 \u001b[39m\u001b[38;5;246;03m# Execute under all circumstances\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mWe can clean up resources here\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;246;03m# Instead of try/finally to cleanup resources you can use a with statement\u001b[39;00m\n\u001b[38;5;70;01mwith\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mopen\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mmyfile.txt\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mas\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mf\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mline\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mf\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mline\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;246;03m# Writing to a file\u001b[39;00m\n\u001b[38;5;252mcontents\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214maa\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m12\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mbb\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m21\u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;70;01mwith\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mopen\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mmyfile1.txt\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mw+\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mas\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfile\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mfile\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mwrite\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mstr\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mcontents\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# writes a string to a file\u001b[39;00m\n\n\u001b[38;5;70;01mwith\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mopen\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mmyfile2.txt\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mw+\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mas\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfile\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mfile\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mwrite\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mjson\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mdumps\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mcontents\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# writes an object to a file\u001b[39;00m\n\n\u001b[38;5;246;03m# Reading from a file\u001b[39;00m\n\u001b[38;5;70;01mwith\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mopen\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mmyfile1.txt\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mr+\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mas\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfile\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mcontents\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfile\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mread\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m           \u001b[39m\u001b[38;5;246;03m# reads a string from a file\u001b[39;00m\n\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mcontents\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;246;03m# print: {\"aa\": 12, \"bb\": 21}\u001b[39;00m\n\n\u001b[38;5;70;01mwith\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mopen\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mmyfile2.txt\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mr+\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mas\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfile\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mcontents\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mjson\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mload\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mfile\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m       \u001b[39m\u001b[38;5;246;03m# reads a json object from a file\u001b[39;00m\n\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mcontents\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;246;03m# print: {\"aa\": 12, \"bb\": 21}\u001b[39;00m\n\n\n\u001b[38;5;246;03m# Python offers a fundamental abstraction called the Iterable.\u001b[39;00m\n\u001b[38;5;246;03m# An iterable is an object that can be treated as a sequence.\u001b[39;00m\n\u001b[38;5;246;03m# The object returned by the range function, is an iterable.\u001b[39;00m\n\n\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mone\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mtwo\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mthree\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252mour_iterable\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfilled_dict\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mkeys\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mour_iterable\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => dict_keys(['one', 'two', 'three']). This is an object that implements our Iterable interface.\u001b[39;00m\n\n\u001b[38;5;246;03m# We can loop over it.\u001b[39;00m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mour_iterable\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Prints one, two, three\u001b[39;00m\n\n\u001b[38;5;246;03m# However we cannot address elements by index.\u001b[39;00m\n\u001b[38;5;252mour_iterable\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Raises a TypeError\u001b[39;00m\n\n\u001b[38;5;246;03m# An iterable is an object that knows how to create an iterator.\u001b[39;00m\n\u001b[38;5;252mour_iterator\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;31miter\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mour_iterable\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;246;03m# Our iterator is an object that can remember the state as we traverse through it.\u001b[39;00m\n\u001b[38;5;246;03m# We get the next object with \"next()\".\u001b[39;00m\n\u001b[38;5;31mnext\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mour_iterator\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => \"one\"\u001b[39;00m\n\n\u001b[38;5;246;03m# It maintains state as we iterate.\u001b[39;00m\n\u001b[38;5;31mnext\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mour_iterator\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => \"two\"\u001b[39;00m\n\u001b[38;5;31mnext\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mour_iterator\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => \"three\"\u001b[39;00m\n\n\u001b[38;5;246;03m# After the iterator has returned all of its data, it raises a StopIteration exception\u001b[39;00m\n\u001b[38;5;31mnext\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mour_iterator\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Raises StopIteration\u001b[39;00m\n\n\u001b[38;5;246;03m# We can also loop over it, in fact, \"for\" does this implicitly!\u001b[39;00m\n\u001b[38;5;252mour_iterator\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;31miter\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mour_iterable\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mour_iterator\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Prints one, two, three\u001b[39;00m\n\n\u001b[38;5;246;03m# You can grab all the elements of an iterable or iterator by calling list() on it.\u001b[39;00m\n\u001b[38;5;31mlist\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mour_iterable\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => Returns [\"one\", \"two\", \"three\"]\u001b[39;00m\n\u001b[38;5;31mlist\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mour_iterator\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => Returns [] because state is saved\u001b[39;00m\n\n\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\u001b[38;5;246;03m## 4. Functions\u001b[39;00m\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\n\u001b[38;5;246;03m# Use \"def\" to create new functions\u001b[39;00m\n\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68madd\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252my\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mx is \u001b[39m\u001b[38;5;214m{}\u001b[39m\u001b[38;5;214m and y is \u001b[39m\u001b[38;5;214m{}\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mformat\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252my\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252my\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Return values with a return statement\u001b[39;00m\n\n\u001b[38;5;246;03m# Calling functions with parameters\u001b[39;00m\n\u001b[38;5;252madd\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => prints out \"x is 5 and y is 6\" and returns 11\u001b[39;00m\n\n\u001b[38;5;246;03m# Another way to call functions is with keyword arguments\u001b[39;00m\n\u001b[38;5;252madd\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252my\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Keyword arguments can arrive in any order.\u001b[39;00m\n\n\u001b[38;5;246;03m# You can define functions that take a variable number of\u001b[39;00m\n\u001b[38;5;246;03m# positional arguments\u001b[39;00m\n\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mvarargs\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252margs\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252margs\u001b[39m\n\n\u001b[38;5;252mvarargs\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => (1, 2, 3)\u001b[39;00m\n\n\u001b[38;5;246;03m# You can define functions that take a variable number of\u001b[39;00m\n\u001b[38;5;246;03m# keyword arguments, as well\u001b[39;00m\n\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mkeyword_args\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252mkwargs\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mkwargs\u001b[39m\n\n\u001b[38;5;246;03m# Let's call it to see what happens\u001b[39;00m\n\u001b[38;5;252mkeyword_args\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mbig\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mfoot\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mloch\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mness\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => {\"big\": \"foot\", \"loch\": \"ness\"}\u001b[39;00m\n\n\n\u001b[38;5;246;03m# You can do both at once, if you like\u001b[39;00m\n\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mall_the_args\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252margs\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252mkwargs\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252margs\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mkwargs\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;214m\"\"\"\u001b[39m\n\u001b[38;5;214mall_the_args(1, 2, a=3, b=4) prints:\u001b[39m\n\u001b[38;5;214m    (1, 2)\u001b[39m\n\u001b[38;5;214m    {\"a\": 3, \"b\": 4}\u001b[39m\n\u001b[38;5;214m\"\"\"\u001b[39m\n\n\u001b[38;5;246;03m# When calling functions, you can do the opposite of args/kwargs!\u001b[39;00m\n\u001b[38;5;246;03m# Use * to expand tuples and use ** to expand kwargs.\u001b[39;00m\n\u001b[38;5;252margs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252mkwargs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214ma\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mb\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252mall_the_args\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252margs\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m            \u001b[39m\u001b[38;5;246;03m# equivalent to all_the_args(1, 2, 3, 4)\u001b[39;00m\n\u001b[38;5;252mall_the_args\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252mkwargs\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m         \u001b[39m\u001b[38;5;246;03m# equivalent to all_the_args(a=3, b=4)\u001b[39;00m\n\u001b[38;5;252mall_the_args\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252margs\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252mkwargs\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# equivalent to all_the_args(1, 2, 3, 4, a=3, b=4)\u001b[39;00m\n\n\u001b[38;5;246;03m# Returning multiple values (with tuple assignments)\u001b[39;00m\n\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mswap\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252my\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252my\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Return multiple values as a tuple without the parenthesis.\u001b[39;00m\n\u001b[38;5;252m                 \u001b[39m\u001b[38;5;246;03m# (Note: parenthesis have been excluded but can be included)\u001b[39;00m\n\n\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\n\u001b[38;5;252my\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\n\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252my\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mswap\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252my\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m     \u001b[39m\u001b[38;5;246;03m# => x = 2, y = 1\u001b[39;00m\n\u001b[38;5;246;03m# (x, y) = swap(x,y)  # Again parenthesis have been excluded but can be included.\u001b[39;00m\n\n\u001b[38;5;246;03m# Function Scope\u001b[39;00m\n\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\n\n\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mset_x\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mnum\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Local var x not the same as global variable x\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mnum\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# => 43\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => 43\u001b[39;00m\n\n\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mset_global_x\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mnum\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mglobal\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => 5\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mnum\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# global var x is now set to 6\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => 6\u001b[39;00m\n\n\u001b[38;5;252mset_x\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m43\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252mset_global_x\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\n\u001b[38;5;246;03m# Python has first class functions\u001b[39;00m\n\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mcreate_adder\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68madder\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252my\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252my\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252madder\u001b[39m\n\n\u001b[38;5;252madd_10\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcreate_adder\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252madd_10\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => 13\u001b[39;00m\n\n\u001b[38;5;246;03m# There are also anonymous functions\u001b[39;00m\n\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mlambda\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m                  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mlambda\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252my\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252my\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 5\u001b[39;00m\n\n\u001b[38;5;246;03m# There are built-in higher order functions\u001b[39;00m\n\u001b[38;5;31mlist\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mmap\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252madd_10\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m          \u001b[39m\u001b[38;5;246;03m# => [11, 12, 13]\u001b[39;00m\n\u001b[38;5;31mlist\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mmap\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mmax\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => [4, 2, 3]\u001b[39;00m\n\n\u001b[38;5;31mlist\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mfilter\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mlambda\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m7\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => [6, 7]\u001b[39;00m\n\n\u001b[38;5;246;03m# We can use list comprehensions for nice maps and filters\u001b[39;00m\n\u001b[38;5;246;03m# List comprehension stores the output as a list which can itself be a nested list\u001b[39;00m\n\u001b[38;5;252m[\u001b[39m\u001b[38;5;252madd_10\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m         \u001b[39m\u001b[38;5;246;03m# => [11, 12, 13]\u001b[39;00m\n\u001b[38;5;252m[\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m7\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => [6, 7]\u001b[39;00m\n\n\u001b[38;5;246;03m# You can construct set and dict comprehensions as well.\u001b[39;00m\n\u001b[38;5;252m{\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mabcddeef\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mnot\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mabc\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => {'d', 'e', 'f'}\u001b[39;00m\n\u001b[38;5;252m{\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mrange\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}\u001b[39;00m\n\n\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\u001b[38;5;246;03m## 5. Modules\u001b[39;00m\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\n\u001b[38;5;246;03m# You can import modules\u001b[39;00m\n\u001b[38;5;70;01mimport\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mmath\u001b[39;00m\n\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmath\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msqrt\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m16\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 4.0\u001b[39;00m\n\n\u001b[38;5;246;03m# You can get specific functions from a module\u001b[39;00m\n\u001b[38;5;70;01mfrom\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mmath\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mimport\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mceil\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfloor\u001b[39m\n\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mceil\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m3.7\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m# => 4.0\u001b[39;00m\n\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mfloor\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m3.7\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => 3.0\u001b[39;00m\n\n\u001b[38;5;246;03m# You can import all functions from a module.\u001b[39;00m\n\u001b[38;5;246;03m# Warning: this is not recommended\u001b[39;00m\n\u001b[38;5;70;01mfrom\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mmath\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mimport\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\n\n\u001b[38;5;246;03m# You can shorten module names\u001b[39;00m\n\u001b[38;5;70;01mimport\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mmath\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mas\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mm\u001b[39;00m\n\u001b[38;5;252mmath\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msqrt\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m16\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mm\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msqrt\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m16\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => True\u001b[39;00m\n\n\u001b[38;5;246;03m# Python modules are just ordinary Python files. You\u001b[39;00m\n\u001b[38;5;246;03m# can write your own, and import them. The name of the\u001b[39;00m\n\u001b[38;5;246;03m# module is the same as the name of the file.\u001b[39;00m\n\n\u001b[38;5;246;03m# You can find out which functions and attributes\u001b[39;00m\n\u001b[38;5;246;03m# are defined in a module.\u001b[39;00m\n\u001b[38;5;70;01mimport\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mmath\u001b[39;00m\n\u001b[38;5;31mdir\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmath\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;246;03m# If you have a Python script named math.py in the same\u001b[39;00m\n\u001b[38;5;246;03m# folder as your current script, the file math.py will\u001b[39;00m\n\u001b[38;5;246;03m# be loaded instead of the built-in Python module.\u001b[39;00m\n\u001b[38;5;246;03m# This happens because the local folder has priority\u001b[39;00m\n\u001b[38;5;246;03m# over Python's built-in libraries.\u001b[39;00m\n\n\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\u001b[38;5;246;03m## 6. Classes\u001b[39;00m\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\n\u001b[38;5;246;03m# We use the \"class\" statement to create a class\u001b[39;00m\n\u001b[38;5;70;01mclass\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mHuman\u001b[39;00m\u001b[38;5;252m:\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# A class attribute. It is shared by all instances of this class\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mspecies\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mH. sapiens\u001b[39m\u001b[38;5;214m\"\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Basic initializer, this is called when this class is instantiated.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Note that the double leading and trailing underscores denote objects\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# or attributes that are used by Python but that live in user-controlled\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# namespaces. Methods(or objects or attributes) like: __init__, __str__,\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# __repr__ etc. are called special methods (or sometimes called dunder methods)\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# You should not invent such names on your own.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68m__init__\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# Assign the argument to the instance's name attribute\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mname\u001b[39m\n\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# Initialize property\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252m_age\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# An instance method. All methods take \"self\" as the first argument\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmsg\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m{name}\u001b[39m\u001b[38;5;214m: \u001b[39m\u001b[38;5;214m{message}\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mformat\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmessage\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252mmsg\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Another instance method\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68msing\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214myo... yo... microphone check... one two... one two...\u001b[39m\u001b[38;5;214m'\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# A class method is shared among all instances\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# They are called with the calling class as the first argument\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;214m@classmethod\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mget_species\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mcls\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mcls\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mspecies\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# A static method is called without a class or instance reference\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;214m@staticmethod\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mgrunt\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m*grunt*\u001b[39m\u001b[38;5;214m\"\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# A property is just like a getter.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# It turns the method age() into a read-only attribute of the same name.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# There's no need to write trivial getters and setters in Python, though.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;214m@property\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mage\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252m_age\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# This allows the property to be set\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;214m@age\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msetter\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mage\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mage\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252m_age\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mage\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# This allows the property to be deleted\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;214m@age\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mdeleter\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mage\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mdel\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252m_age\u001b[39m\n\n\n\u001b[38;5;246;03m# When a Python interpreter reads a source file it executes all its code.\u001b[39;00m\n\u001b[38;5;246;03m# This __name__ check makes sure this code block is only executed when this\u001b[39;00m\n\u001b[38;5;246;03m# module is the main program.\u001b[39;00m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;87m__name__\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214m__main__\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Instantiate a class\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mHuman\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mIan\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mhi\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m                     \u001b[39m\u001b[38;5;246;03m# \"Ian: hi\"\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mHuman\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mJoel\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mhello\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m                  \u001b[39m\u001b[38;5;246;03m# \"Joel: hello\"\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# i and j are instances of type Human, or in other words: they are Human objects\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Call our class method\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mget_species\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m          \u001b[39m\u001b[38;5;246;03m# \"Ian: H. sapiens\"\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Change the shared attribute\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mHuman\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mspecies\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mH. neanderthalensis\u001b[39m\u001b[38;5;214m\"\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mget_species\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m          \u001b[39m\u001b[38;5;246;03m# => \"Ian: H. neanderthalensis\"\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mget_species\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m          \u001b[39m\u001b[38;5;246;03m# => \"Joel: H. neanderthalensis\"\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Call the static method\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mHuman\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mgrunt\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m            \u001b[39m\u001b[38;5;246;03m# => \"*grunt*\"\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Static methods can be called by instances too\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mgrunt\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m                \u001b[39m\u001b[38;5;246;03m# => \"*grunt*\"\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Update the property for this instance\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m42\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Get the property\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mage\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m                    \u001b[39m\u001b[38;5;246;03m# => \"Ian: 42\"\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mage\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m                    \u001b[39m\u001b[38;5;246;03m# => \"Joel: 0\"\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Delete the property\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdel\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mage\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# i.age                         # => this would raise an AttributeError\u001b[39;00m\n\n\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\u001b[38;5;246;03m## 6.1 Inheritance\u001b[39;00m\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\n\u001b[38;5;246;03m# Inheritance allows new child classes to be defined that inherit methods and\u001b[39;00m\n\u001b[38;5;246;03m# variables from their parent class.\u001b[39;00m\n\n\u001b[38;5;246;03m# Using the Human class defined above as the base or parent class, we can\u001b[39;00m\n\u001b[38;5;246;03m# define a child class, Superhero, which inherits the class variables like\u001b[39;00m\n\u001b[38;5;246;03m# \"species\", \"name\", and \"age\", as well as methods, like \"sing\" and \"grunt\"\u001b[39;00m\n\u001b[38;5;246;03m# from the Human class, but can also have its own unique properties.\u001b[39;00m\n\n\u001b[38;5;246;03m# To take advantage of modularization by file you could place the classes above in their own files,\u001b[39;00m\n\u001b[38;5;246;03m# say, human.py\u001b[39;00m\n\n\u001b[38;5;246;03m# To import functions from other files use the following format\u001b[39;00m\n\u001b[38;5;246;03m# from \"filename-without-extension\" import \"function-or-class\"\u001b[39;00m\n\n\u001b[38;5;70;01mfrom\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mhuman\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mimport\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mHuman\u001b[39m\n\n\n\u001b[38;5;246;03m# Specify the parent class(es) as parameters to the class definition\u001b[39;00m\n\u001b[38;5;70;01mclass\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mSuperhero\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mHuman\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# If the child class should inherit all of the parent's definitions without\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# any modifications, you can just use the \"pass\" keyword (and nothing else)\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# but in this case it is commented out to allow for a unique child class:\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# pass\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Child classes can override their parents' attributes\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mspecies\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mSuperhuman\u001b[39m\u001b[38;5;214m'\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Children automatically inherit their parent class's constructor including\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# its arguments, but can also define additional arguments or definitions\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# and override its methods such as the class constructor.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# This constructor inherits the \"name\" argument from the \"Human\" class and\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# adds the \"superpower\" and \"movie\" arguments:\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68m__init__\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmovie\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;70;01mFalse\u001b[39;00m\u001b[38;5;252m,\u001b[39m\n\u001b[38;5;252m                 \u001b[39m\u001b[38;5;252msuperpowers\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214msuper strength\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mbulletproofing\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# add additional class attributes:\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mfictional\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mTrue\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmovie\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmovie\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# be aware of mutable default values, since defaults are shared\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msuperpowers\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msuperpowers\u001b[39m\n\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# The \"super\" function lets you access the parent class's methods\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# that are overridden by the child, in this case, the __init__ method.\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# This calls the parent class constructor:\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31msuper\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;68m__init__\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# override the sing method\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68msing\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mDun, dun, DUN!\u001b[39m\u001b[38;5;214m'\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# add an additional instance method\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mboast\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpower\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msuperpowers\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m            \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mI wield the power of \u001b[39m\u001b[38;5;214m{pow}\u001b[39m\u001b[38;5;214m!\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mformat\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mpow\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252mpower\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;87m__name__\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214m__main__\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mSuperhero\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mTick\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Instance type checks\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31misinstance\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mHuman\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mI am human\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mtype\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mis\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mSuperhero\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mI am a superhero\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Get the Method Resolution search Order used by both getattr() and super()\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# This attribute is dynamic and can be updated\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mSuperhero\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;87m__mro__\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# => (<class '__main__.Superhero'>,\u001b[39;00m\n\u001b[38;5;252m                                \u001b[39m\u001b[38;5;246;03m# => <class 'human.Human'>, <class 'object'>)\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Calls parent method but uses its own class attribute\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mget_species\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# => Superhuman\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Calls overridden method\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msing\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m           \u001b[39m\u001b[38;5;246;03m# => Dun, dun, DUN!\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Calls method from Human\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mSpoon\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m            \u001b[39m\u001b[38;5;246;03m# => Tick: Spoon\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Call method that exists only in Superhero\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mboast\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m                 \u001b[39m\u001b[38;5;246;03m# => I wield the power of super strength!\u001b[39;00m\n\u001b[38;5;252m                                \u001b[39m\u001b[38;5;246;03m# => I wield the power of bulletproofing!\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Inherited class attribute\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m31\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mage\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m              \u001b[39m\u001b[38;5;246;03m# => 31\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Attribute that only exists within Superhero\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mAm I Oscar eligible? \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mstr\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmovie\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\u001b[38;5;246;03m## 6.2 Multiple Inheritance\u001b[39;00m\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\n\u001b[38;5;246;03m# Another class definition\u001b[39;00m\n\u001b[38;5;246;03m# bat.py\u001b[39;00m\n\u001b[38;5;70;01mclass\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mBat\u001b[39;00m\u001b[38;5;252m:\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mspecies\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mBaty\u001b[39m\u001b[38;5;214m'\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68m__init__\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcan_fly\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;70;01mTrue\u001b[39;00m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mfly\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcan_fly\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# This class also has a say method\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmsg\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;252mmsg\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214m... ... ...\u001b[39m\u001b[38;5;214m'\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmsg\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# And its own method as well\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68msonar\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214m))) ... (((\u001b[39m\u001b[38;5;214m'\u001b[39m\n\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;87m__name__\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214m__main__\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mBat\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mhello\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mfly\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\n\u001b[38;5;246;03m# And yet another class definition that inherits from Superhero and Bat\u001b[39;00m\n\u001b[38;5;246;03m# superhero.py\u001b[39;00m\n\u001b[38;5;70;01mfrom\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04msuperhero\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mimport\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mSuperhero\u001b[39m\n\u001b[38;5;70;01mfrom\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mbat\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mimport\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mBat\u001b[39m\n\n\u001b[38;5;246;03m# Define Batman as a child that inherits from both Superhero and Bat\u001b[39;00m\n\u001b[38;5;70;01mclass\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mBatman\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mSuperhero\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mBat\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68m__init__\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252margs\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252mkwargs\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# Typically to inherit attributes you have to call super:\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# super(Batman, self).__init__(*args, **kwargs)\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# However we are dealing with multiple inheritance here, and super()\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# only works with the next base class in the MRO list.\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# So instead we explicitly call __init__ for all ancestors.\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# The use of *args and **kwargs allows for a clean way to pass arguments,\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# with each parent \"peeling a layer of the onion\".\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;252mSuperhero\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;68m__init__\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214manonymous\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmovie\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;70;01mTrue\u001b[39;00m\u001b[38;5;252m,\u001b[39m\n\u001b[38;5;252m                           \u001b[39m\u001b[38;5;252msuperpowers\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mWealthy\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252margs\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252mkwargs\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;252mBat\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;68m__init__\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252margs\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcan_fly\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;70;01mFalse\u001b[39;00m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252mkwargs\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m# override the value for the name attribute\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mSad Affleck\u001b[39m\u001b[38;5;214m'\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68msing\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mself\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mnan nan nan nan nan batman!\u001b[39m\u001b[38;5;214m'\u001b[39m\n\n\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;87m__name__\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214m__main__\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mBatman\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Get the Method Resolution search Order used by both getattr() and super().\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# This attribute is dynamic and can be updated\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mBatman\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;87m__mro__\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m       \u001b[39m\u001b[38;5;246;03m# => (<class '__main__.Batman'>,\u001b[39;00m\n\u001b[38;5;252m                                \u001b[39m\u001b[38;5;246;03m# => <class 'superhero.Superhero'>,\u001b[39;00m\n\u001b[38;5;252m                                \u001b[39m\u001b[38;5;246;03m# => <class 'human.Human'>,\u001b[39;00m\n\u001b[38;5;252m                                \u001b[39m\u001b[38;5;246;03m# => <class 'bat.Bat'>, <class 'object'>)\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Calls parent method but uses its own class attribute\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mget_species\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# => Superhuman\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Calls overridden method\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msing\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m           \u001b[39m\u001b[38;5;246;03m# => nan nan nan nan nan batman!\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Calls method from Human, because inheritance order matters\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mI agree\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m          \u001b[39m\u001b[38;5;246;03m# => Sad Affleck: I agree\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Call method that exists only in 2nd ancestor\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msonar\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m          \u001b[39m\u001b[38;5;246;03m# => ))) ... (((\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Inherited class attribute\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m100\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mage\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m              \u001b[39m\u001b[38;5;246;03m# => 100\u001b[39;00m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m# Inherited attribute from 2nd ancestor whose default value was overridden.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mCan I fly? \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mstr\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msup\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mfly\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# => Can I fly? False\u001b[39;00m\n\n\n\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\u001b[38;5;246;03m## 7. Advanced\u001b[39;00m\n\u001b[38;5;246;03m####################################################\u001b[39;00m\n\n\u001b[38;5;246;03m# Generators help you make lazy code.\u001b[39;00m\n\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mdouble_numbers\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252miterable\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252miterable\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01myield\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\n\n\u001b[38;5;246;03m# Generators are memory-efficient because they only load the data needed to\u001b[39;00m\n\u001b[38;5;246;03m# process the next value in the iterable. This allows them to perform\u001b[39;00m\n\u001b[38;5;246;03m# operations on otherwise prohibitively large value ranges.\u001b[39;00m\n\u001b[38;5;246;03m# NOTE: `range` replaces `xrange` in Python 3.\u001b[39;00m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdouble_numbers\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mrange\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m900000000\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# `range` is a generator.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m30\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mbreak\u001b[39;00m\n\n\u001b[38;5;246;03m# Just as you can create a list comprehension, you can create generator\u001b[39;00m\n\u001b[38;5;246;03m# comprehensions as well.\u001b[39;00m\n\u001b[38;5;252mvalues\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvalues\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# prints -1 -2 -3 -4 -5 to console/terminal\u001b[39;00m\n\n\u001b[38;5;246;03m# You can also cast a generator comprehension directly to a list.\u001b[39;00m\n\u001b[38;5;252mvalues\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252mgen_to_list\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mlist\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mvalues\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mgen_to_list\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# => [-1, -2, -3, -4, -5]\u001b[39;00m\n\n\n\u001b[38;5;246;03m# Decorators\u001b[39;00m\n\u001b[38;5;246;03m# In this example `beg` wraps `say`. If say_please is True then it\u001b[39;00m\n\u001b[38;5;246;03m# will change the returned message.\u001b[39;00m\n\u001b[38;5;70;01mfrom\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mfunctools\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mimport\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mwraps\u001b[39m\n\n\n\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mbeg\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mtarget_function\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;214m@wraps\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mtarget_function\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68mwrapper\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252margs\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252mkwargs\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;252mmsg\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msay_please\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtarget_function\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252margs\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252mkwargs\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msay_please\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m            \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m{}\u001b[39m\u001b[38;5;214m \u001b[39m\u001b[38;5;214m{}\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mformat\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmsg\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mPlease! I am poor :(\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmsg\u001b[39m\n\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mwrapper\u001b[39m\n\n\n\u001b[38;5;214m@beg\u001b[39m\n\u001b[38;5;70;01mdef\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msay_please\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;70;01mFalse\u001b[39;00m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmsg\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mCan you buy me a beer?\u001b[39m\u001b[38;5;214m\"\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmsg\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msay_please\u001b[39m\n\n\n\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m                 \u001b[39m\u001b[38;5;246;03m# Can you buy me a beer?\u001b[39;00m\n\u001b[38;5;31mprint\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msay\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msay_please\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;70;01mTrue\u001b[39;00m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m# Can you buy me a beer? Please! I am poor :(\u001b[39;00m\n"
  },
  {
    "path": "tests/results/16",
    "content": "\u001b[38;5;242m# Latency numbers every programmer should know \u001b[m\n\n1ns                          Main memory reference:       Send 2,000 bytes             Read 1,000,000 bytes         \n\u001b[37m▗▖                           \u001b[m100ns                        over commodity network:      sequentially from SSD:       \n                             \u001b[34m▗▖                           \u001b[m31ns                         38.876us                     \nL1 cache reference: 1ns                                   \u001b[32m▗                            \u001b[m\u001b[31m▗                            \u001b[m\n\u001b[37m▗▖                           \u001b[m1.0us                                                                                  \n                             \u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[mSSD random read: 16.0us      Disk seek: 2.332582ms        \nBranch mispredict: 3ns       \u001b[34m                             \u001b[m\u001b[32m▗▖▗                          \u001b[m\u001b[31m▗▖▗▖                         \u001b[m\n\u001b[37m▗▖▗▖▗▖                       \u001b[m                                                                                       \n                             Compress 1KB wth Snappy:     Read 1,000,000 bytes         Read 1,000,000 bytes         \nL2 cache reference: 4ns      2.0us                        sequentially from memory:    sequentially from disk:      \n\u001b[37m▗▖▗▖▗▖▗▖                     \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m2.355us                      717.936us                    \n                             \u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗                            \u001b[m\u001b[31m▗                            \u001b[m\nMutex lock/unlock: 16ns      \u001b[34m                             \u001b[m                                                          \n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m                             Round trip                   Packet roundtrip             \n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗                \u001b[m10.0us = \u001b[32m▗▖\u001b[m                  in same datacenter: 500.0us  CA to Netherlands: 150.0ms   \n                             \u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n100ns = \u001b[34m▗▖\u001b[m                   \u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m                             \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m                             \u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m1.0ms = \u001b[31m▗▖\u001b[m                   \u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m                             \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m                             \u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m                             \u001b[m                             \u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n                                                          \u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[38;5;242m# [github.com/chubin/late.nz] [MIT License]               \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[38;5;242m# Console port of \"Jeff Dean's latency numbers\"           \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m                             \u001b[m\n\u001b[38;5;242m# from [github.com/colin-scott/interactive_latencies]     \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m                             \n\u001b[38;5;242m                                                          \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m                             \n"
  },
  {
    "path": "tests/results/17",
    "content": "\u001b[48;5;8m\u001b[24m cheat.sheets:az \u001b[24m\u001b[0m\n\u001b[38;5;246;03m# Microsoft Azure CLI 2.0\u001b[39;00m\n\u001b[38;5;246;03m# Command-line tools for Azure\u001b[39;00m\n\n\u001b[38;5;246;03m# Install Azure CLI 2.0 with one curl command.\u001b[39;00m\n\u001b[38;5;252mcurl\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-L\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mhttps://aka.ms/InstallAzureCli\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m|\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbash\u001b[39m\n\n\u001b[38;5;246;03m# create a resource group named \"MyRG\" in the 'westus2' region\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mgroup\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-n\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyRG\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-l\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mwestus2\u001b[39m\n\n\u001b[38;5;246;03m# create a Linux VM using the UbuntuTLS image,\u001b[39;00m\n\u001b[38;5;246;03m# with two attached storage disks of 10 GB and 20 GB\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-n\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyLinuxVM\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-g\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyRG\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m--ssh-key-value\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;87m$HOME\u001b[39m\u001b[38;5;252m/.ssh/id_rsa.pub\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--image\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mUbuntuLTS\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m--data-disk-sizes-gb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m20\u001b[39m\n\n\u001b[38;5;246;03m# list VMs\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--output\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtable\u001b[39m\n\n\u001b[38;5;246;03m# list only VMs having distinct state\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-d\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--query\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"[?powerState=='VM running']\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--output\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtable\u001b[39m\n\n\u001b[38;5;246;03m# delete VM (with the name MyLinuxVM in the group MyRG)\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdelete\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-g\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyRG\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-n\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyLinuxVM\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--yes\u001b[39m\n\n\u001b[38;5;246;03m# Delete all VMs in a resource group\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdelete\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--ids\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01m$(\u001b[39;00m\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-g\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyRG\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--query\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"[].id\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-o\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtsv\u001b[39m\u001b[38;5;70;01m)\u001b[39;00m\n\n\u001b[38;5;246;03m# Create an Image based on a running VM\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdeallocate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-g\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyRG\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-n\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyLinuxVM\u001b[39m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mgeneralize\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-g\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyRG\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-n\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyLinuxVM\u001b[39m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mimage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--resource-group\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyRG\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyTestImage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--source\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyLinuxVM\u001b[39m\n\n\u001b[38;5;246;03m# Running VM based on a VHD\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mstorage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mblob\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mupload\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--account-name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m${\u001b[39m\u001b[38;5;87maccount_name\u001b[39m\u001b[38;5;214m}\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m   \u001b[39m\u001b[38;5;252m--account-key\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m${\u001b[39m\u001b[38;5;87maccount_key\u001b[39m\u001b[38;5;214m}\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--container-name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m${\u001b[39m\u001b[38;5;87mcontainer\u001b[39m\u001b[38;5;214m}\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--type\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m   \u001b[39m\u001b[38;5;252m--file\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m${\u001b[39m\u001b[38;5;87mfile\u001b[39m\u001b[38;5;214m}\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m${\u001b[39m\u001b[38;5;87mvhd\u001b[39m\u001b[38;5;214m}\u001b[39m\u001b[38;5;214m\"\u001b[39m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdisk\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m   \u001b[39m\u001b[38;5;252m--resource-group\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214m${\u001b[39m\u001b[38;5;87mresource_group\u001b[39m\u001b[38;5;214m}\u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m   \u001b[39m\u001b[38;5;252m--name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyManagedDisk\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m   \u001b[39m\u001b[38;5;252m--source\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\u001b[39m\u001b[38;5;214mhttps://\u001b[39m\u001b[38;5;214m${\u001b[39m\u001b[38;5;87maccount_name\u001b[39m\u001b[38;5;214m}\u001b[39m\u001b[38;5;214m.blob.core.windows.net/\u001b[39m\u001b[38;5;214m${\u001b[39m\u001b[38;5;87mcontainer\u001b[39m\u001b[38;5;214m}\u001b[39m\u001b[38;5;214m/\u001b[39m\u001b[38;5;214m${\u001b[39m\u001b[38;5;87mvhd\u001b[39m\u001b[38;5;214m}\u001b[39m\u001b[38;5;214m\"\u001b[39m\n\n\u001b[38;5;246;03m# open port\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mopen-port\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--resource-group\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyRG\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyLinuxVM\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--port\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m443\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--priority\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m899\u001b[39m\n\n\u001b[38;5;246;03m# Show storage accounts\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mstorage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252maccount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--output\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtable\u001b[39m\n\n\u001b[38;5;246;03m# Show containers for an account\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mstorage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcontainer\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--account-name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmystorageaccount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--output\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtable\u001b[39m\n\n\u001b[38;5;246;03m# Show blobs in a container\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mstorage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mblob\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--account-name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmystorageaccount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m--container-name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmycontainer\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;252m--output\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtable\u001b[39m\n\n\u001b[38;5;246;03m# list account keys\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mstorage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252maccount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mkeys\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;252m--account-name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mSTORAGE_NAME\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--resource-group\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mRESOURCE_GROUP\u001b[39m\n\n\u001b[38;5;246;03m# Show own images\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mimage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--output\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtable\u001b[39m\n\n\u001b[38;5;246;03m# Configure default storage location\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mconfigure\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--defaults\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;87mlocation\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252meastus2\u001b[39m\n\n\u001b[38;5;246;03m# Show disks\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdisk\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--output\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtable\u001b[39m\n\n\u001b[38;5;246;03m# Copy blob\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mstorage\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mblob\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcopy\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mstart\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m--source-uri\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'https://xxx.blob.core.windows.net/jzwuuuzzapn0/abcd?...'\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m--account-key\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;87mXXXXXXXXXX\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m--account-name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdestaccount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m--destination-container\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvms\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m--destination-blob\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mDESTINATION-blob.vhd\u001b[39m\n\n\u001b[38;5;246;03m# List virtual networks\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mnetwork\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvnet\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--output\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtable\u001b[39m\n\n\u001b[38;5;246;03m# List virtual networks adapters\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mnetwork\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mnic\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--output\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtable\u001b[39m\n\n\u001b[38;5;246;03m# List public IP addresses used by the VMs\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist-ip-addresses\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--output\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtable\u001b[39m\n\n\u001b[38;5;246;03m# create snapshot\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msnapshot\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--resource-group\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mIC-EXASOL-001\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--source\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm1-disk1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-n\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm1-snap1\u001b[39m\n\n\u001b[38;5;246;03m# create SAS url for a snapshot\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msnapshot\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mgrant-access\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--resource-group\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mIC-EXASOL-001\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm1-snap1\u001b[39m\u001b[38;5;214m\\\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m--duration-in-seconds\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m36000\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--query\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'[accessSas]'\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-o\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtsv\u001b[39m\n\n\u001b[38;5;246;03m# attach disk\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdisk\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mattach\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--vm-name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-g\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mRESOURCE_GROUP\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--disk\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mDISK1_ID\u001b[39m\n\n\u001b[38;5;246;03m# detach disk\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdisk\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdetach\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--vm-name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-g\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mRESOURCE_GROUP\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--name\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mDISK1_ID\u001b[39m\n\n\u001b[48;5;8m\u001b[24m tldr:az \u001b[24m\u001b[0m\n\u001b[38;5;246;03m# az\u001b[39;00m\n\u001b[38;5;246;03m# The official CLI tool for Microsoft Azure.\u001b[39;00m\n\u001b[38;5;246;03m# Some subcommands such as `az login` have their own usage documentation.\u001b[39;00m\n\u001b[38;5;246;03m# More information: <https://docs.microsoft.com/cli/azure>.\u001b[39;00m\n\n\u001b[38;5;246;03m# Log in to Azure:\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlogin\u001b[39m\n\n\u001b[38;5;246;03m# Manage azure subscription information:\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252maccount\u001b[39m\n\n\u001b[38;5;246;03m# List all Azure Managed Disks:\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdisk\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\n\n\u001b[38;5;246;03m# List all Azure virtual machines:\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mvm\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\n\n\u001b[38;5;246;03m# Manage Azure Kubernetes Services:\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252maks\u001b[39m\n\n\u001b[38;5;246;03m# Manage Azure Network resources:\u001b[39;00m\n\u001b[38;5;252maz\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mnetwork\u001b[39m\n"
  },
  {
    "path": "tests/results/18",
    "content": "\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ms\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mabcdefgh\u001b[39m\u001b[38;5;214m'\u001b[39m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mn\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mm\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mchar\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mchars\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214md\u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mcd\u001b[39m\u001b[38;5;214m'\u001b[39m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# starting from n=2 characters in and m=3 in length;\u001b[39;00m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ms\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252mn\u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252mn\u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252mm\u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m]\u001b[39m\n\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mbcd\u001b[39m\u001b[38;5;214m'\u001b[39m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# starting from n characters in, up to the end of the string;\u001b[39;00m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ms\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252mn\u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m]\u001b[39m\n\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mbcdefgh\u001b[39m\u001b[38;5;214m'\u001b[39m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# whole string minus last character;\u001b[39;00m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ms\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m]\u001b[39m\n\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mabcdefg\u001b[39m\u001b[38;5;214m'\u001b[39m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# starting from a known character char=\"d\" within the string and of m length;\u001b[39;00m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mindx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ms\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mindex\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mchar\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ms\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252mindx\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252mindx\u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252mm\u001b[39m\u001b[38;5;252m]\u001b[39m\n\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mdef\u001b[39m\u001b[38;5;214m'\u001b[39m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m# starting from a known substring chars=\"cd\" within the string and of m length.\u001b[39;00m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mindx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ms\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mindex\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mchars\u001b[39m\u001b[38;5;252m)\u001b[39m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ms\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252mindx\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252mindx\u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252mm\u001b[39m\u001b[38;5;252m]\u001b[39m\n\u001b[38;5;214m'\u001b[39m\u001b[38;5;214mcde\u001b[39m\u001b[38;5;214m'\u001b[39m\n\u001b[38;5;252m>>\u001b[39m\u001b[38;5;252m>\u001b[39m\n"
  },
  {
    "path": "tests/results/19",
    "content": ">>> s = 'abcdefgh'\n>>> n, m, char, chars = 2, 3, 'd', 'cd'\n>>> # starting from n=2 characters in and m=3 in length;\n>>> s[n-1:n+m-1]\n'bcd'\n>>> # starting from n characters in, up to the end of the string;\n>>> s[n-1:]\n'bcdefgh'\n>>> # whole string minus last character;\n>>> s[:-1]\n'abcdefg'\n>>> # starting from a known character char=\"d\" within the string and of m length;\n>>> indx = s.index(char)\n>>> s[indx:indx+m]\n'def'\n>>> # starting from a known substring chars=\"cd\" within the string and of m length.\n>>> indx = s.index(chars)\n>>> s[indx:indx+m]\n'cde'\n>>>\n"
  },
  {
    "path": "tests/results/2",
    "content": "\u001b[48;5;8m\u001b[24m cheat:ls \u001b[24m\u001b[0m\n\u001b[38;5;246;03m# To display everything in <dir>, excluding hidden files:\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252mdir>\u001b[39m\n\n\u001b[38;5;246;03m# To display everything in <dir>, including hidden files:\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-a\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252mdir>\u001b[39m\n\n\u001b[38;5;246;03m# To display all files, along with the size (with unit suffixes) and timestamp\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-lh\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252mdir>\u001b[39m\n\n\u001b[38;5;246;03m# To display files, sorted by size:\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-S\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252mdir>\u001b[39m\n\n\u001b[38;5;246;03m# To display directories only:\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-d\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252mdir>\u001b[39m\n\n\u001b[38;5;246;03m# To display directories only, include hidden:\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-d\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m.*/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252mdir>\u001b[39m\n\n\u001b[48;5;8m\u001b[24m tldr:ls \u001b[24m\u001b[0m\n\u001b[38;5;246;03m# ls\u001b[39;00m\n\u001b[38;5;246;03m# List directory contents.\u001b[39;00m\n\u001b[38;5;246;03m# More information: <https://www.gnu.org/software/coreutils/ls>.\u001b[39;00m\n\n\u001b[38;5;246;03m# List files one per line:\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-1\u001b[39m\n\n\u001b[38;5;246;03m# List all files, including hidden files:\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-a\u001b[39m\n\n\u001b[38;5;246;03m# List all files, with trailing `/` added to directory names:\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-F\u001b[39m\n\n\u001b[38;5;246;03m# Long format list (permissions, ownership, size, and modification date) of all files:\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-la\u001b[39m\n\n\u001b[38;5;246;03m# Long format list with size displayed using human-readable units (KiB, MiB, GiB):\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-lh\u001b[39m\n\n\u001b[38;5;246;03m# Long format list sorted by size (descending):\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-lS\u001b[39m\n\n\u001b[38;5;246;03m# Long format list of all files, sorted by modification date (oldest first):\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-ltr\u001b[39m\n\n\u001b[38;5;246;03m# Only list directories:\u001b[39;00m\n\u001b[38;5;252mls\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-d\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*/\u001b[39m\n"
  },
  {
    "path": "tests/results/20",
    "content": "00DESCRIPTION\n100-doors\n24-game\n24-game-Solve\n9-billion-names-of-God-the-integer\n99-Bottles-of-Beer\nA+B\nABC-Problem\nAKS-test-for-primes\nAbstract-type\nAbundant,-deficient-and-perfect-number-classifications\nAccumulator-factory\nAckermann-function\nActive-Directory-Connect\nActive-Directory-Search-for-a-user\nActive-object\nAdd-a-variable-to-a-class-instance-at-runtime\nAddress-of-a-variable\nAlign-columns\nAliquot-sequence-classifications\nAlmost-prime\nAmb\nAmicable-pairs\nAnagrams\nAnagrams-Deranged-anagrams\nAnimate-a-pendulum\nAnimation\nAnonymous-recursion\nAppend-a-record-to-the-end-of-a-text-file\nApply-a-callback-to-an-array\nArbitrary-precision-integers--included-\nArithmetic-Complex\nArithmetic-Integer\nArithmetic-Rational\nArithmetic-evaluation\nArithmetic-geometric-mean\nArithmetic-geometric-mean-Calculate-Pi\nArray-concatenation\nArrays\nAssertions\nAssociative-array-Creation\nAssociative-array-Iteration\nAtomic-updates\nAverage-loop-length\nAverages-Arithmetic-mean\nAverages-Mean-angle\nAverages-Mean-time-of-day\nAverages-Median\nAverages-Mode\nAverages-Pythagorean-means\nAverages-Root-mean-square\nAverages-Simple-moving-average\nBalanced-brackets\nBalanced-ternary\nBenfords-law\nBernoulli-numbers\nBest-shuffle\nBinary-digits\nBinary-search\nBinary-strings\nBitcoin-address-validation\nBitcoin-public-point-to-address\nBitmap-B-zier-curves-Cubic\nBitmap-Bresenhams-line-algorithm\nBitmap-Flood-fill\nBitmap-Histogram\nBitmap-Midpoint-circle-algorithm\nBitmap-PPM-conversion-through-a-pipe\nBitmap-Read-a-PPM-file\nBitmap-Read-an-image-through-a-pipe\nBitmap-Write-a-PPM-file\nBitwise-IO\nBitwise-operations\nBoolean-values\nBox-the-compass\nBreak-OO-privacy\nBrownian-tree\nBulls-and-cows\nBulls-and-cows-Player\nCRC-32\nCSV-data-manipulation\nCSV-to-HTML-translation\nCaesar-cipher\nCalendar\nCalendar---for-REAL-programmers\nCall-a-foreign-language-function\nCall-a-function\nCall-a-function-in-a-shared-library\nCall-an-object-method\nCanny-edge-detector\nCarmichael-3-strong-pseudoprimes\nCase-sensitivity-of-identifiers\nCasting-out-nines\nCatalan-numbers\nCatalan-numbers-Pascals-triangle\nCatamorphism\nCatmull-Clark-subdivision-surface\nCharacter-codes\nChat-server\nCheck-Machin-like-formulas\nCheck-that-file-exists\nCheckpoint-synchronization\nChinese-remainder-theorem\nCholesky-decomposition\nCircles-of-given-radius-through-two-points\nClasses\nClosest-pair-problem\nClosures-Value-capture\nCollections\nColor-of-a-screen-pixel\nColor-quantization\nColour-bars-Display\nColour-pinstripe-Display\nColour-pinstripe-Printer\nCombinations\nCombinations-and-permutations\nCombinations-with-repetitions\nComma-quibbling\nCommand-line-arguments\nComments\nCompare-sorting-algorithms-performance\nCompound-data-type\nConcurrent-computing\nConditional-structures\nConjugate-transpose\nConstrained-random-points-on-a-circle\nContinued-fraction\nContinued-fraction-Arithmetic-Construct-from-rational-number\nContinued-fraction-Arithmetic-G-matrix-NG,-Contined-Fraction-N-\nConvert-decimal-number-to-rational\nConways-Game-of-Life\nCopy-a-string\nCount-in-factors\nCount-in-octal\nCount-occurrences-of-a-substring\nCount-the-coins\nCreate-a-file\nCreate-a-file-on-magnetic-tape\nCreate-a-two-dimensional-array-at-runtime\nCreate-an-HTML-table\nCurrying\nCut-a-rectangle\nDate-format\nDate-manipulation\nDay-of-the-week\nDeal-cards-for-FreeCell\nDeath-Star\nDeconvolution-1D\nDeconvolution-2D+\nDeepcopy\nDefine-a-primitive-data-type\nDelegates\nDelete-a-file\nDetect-division-by-zero\nDetermine-if-a-string-is-numeric\nDetermine-if-only-one-instance-is-running\nDigital-root\nDigital-root-Multiplicative-digital-root\nDinesmans-multiple-dwelling-problem\nDining-philosophers\nDiscordian-date\nDistributed-programming\nDocumentation\nDot-product\nDoubly-linked-list-Element-definition\nDoubly-linked-list-Element-insertion\nDoubly-linked-list-Traversal\nDragon-curve\nDraw-a-clock\nDraw-a-cuboid\nDraw-a-sphere\nDutch-national-flag-problem\nDynamic-variable-names\nEcho-server\nElement-wise-operations\nEmpty-directory\nEmpty-string\nEnforced-immutability\nEntropy\nEnumerations\nEnvironment-variables\nEquilibrium-index\nEthiopian-multiplication\nEuler-method\nEvaluate-binomial-coefficients\nEven-or-odd\nEvents\nEvolutionary-algorithm\nExceptions\nExceptions-Catch-an-exception-thrown-in-a-nested-call\nExecutable-library\nExecute-SNUSP\nExecute-a-Markov-algorithm\nExecute-a-system-command\nExponentiation-operator\nExtensible-prime-generator\nExtreme-floating-point-values\nFactorial\nFactors-of-a-Mersenne-number\nFactors-of-an-integer\nFast-Fourier-transform\nFibonacci-n-step-number-sequences\nFibonacci-sequence\nFibonacci-word\nFibonacci-word-fractal\nFile-input-output\nFile-modification-time\nFile-size\nFilter\nFind-common-directory-path\nFind-largest-left-truncatable-prime-in-a-given-base\nFind-limit-of-recursion\nFind-the-last-Sunday-of-each-month\nFind-the-missing-permutation\nFirst-class-environments\nFirst-class-functions\nFirst-class-functions-Use-numbers-analogously\nFive-weekends\nFizzBuzz\nFlatten-a-list\nFlipping-bits-game\nFlow-control-structures\nFloyds-triangle\nForest-fire\nFork\nFormal-power-series\nFormatted-numeric-output\nForward-difference\nFour-bit-adder\nFractal-tree\nFractran\nFunction-composition\nFunction-definition\nFunction-frequency\nGUI-Maximum-window-dimensions\nGUI-component-interaction\nGUI-enabling-disabling-of-controls\nGalton-box-animation\nGamma-function\nGaussian-elimination\nGenerate-Chess960-starting-position\nGenerate-lower-case-ASCII-alphabet\nGenerator-Exponential\nGeneric-swap\nGlobally-replace-text-in-several-files\nGray-code\nGrayscale-image\nGreatest-common-divisor\nGreatest-element-of-a-list\nGreatest-subsequential-sum\nGreyscale-bars-Display\nGuess-the-number\nGuess-the-number-With-feedback\nGuess-the-number-With-feedback--player-\nHTTP\nHTTPS\nHTTPS-Authenticated\nHTTPS-Client-authenticated\nHailstone-sequence\nHamming-numbers\nHandle-a-signal\nHappy-numbers\nHarshad-or-Niven-series\nHash-from-two-arrays\nHash-join\nHaversine-formula\nHello-world-Graphical\nHello-world-Line-printer\nHello-world-Newbie\nHello-world-Newline-omission\nHello-world-Standard-error\nHello-world-Text\nHello-world-Web-server\nHere-document\nHeronian-triangles\nHickerson-series-of-almost-integers\nHigher-order-functions\nHistory-variables\nHofstadter-Conway-$10,000-sequence\nHofstadter-Figure-Figure-sequences\nHofstadter-Q-sequence\nHolidays-related-to-Easter\nHorizontal-sundial-calculations\nHorners-rule-for-polynomial-evaluation\nHost-introspection\nHostname\nHough-transform\nHuffman-coding\nI-before-E-except-after-C\nIBAN\nIdentity-matrix\nImage-convolution\nImage-noise\nInclude-a-file\nIncrement-a-numerical-string\nInfinity\nInheritance-Multiple\nInheritance-Single\nInput-loop\nInteger-comparison\nInteger-overflow\nInteger-sequence\nInteractive-programming\nIntrospection\nInverted-index\nInverted-syntax\nIterated-digits-squaring\nJSON\nJensens-Device\nJosephus-problem\nJoystick-position\nJump-anywhere\nK-d-tree\nK-means++-clustering\nKaprekar-numbers\nKeyboard-input-Flush-the-keyboard-buffer\nKeyboard-input-Keypress-check\nKeyboard-input-Obtain-a-Y-or-N-response\nKeyboard-macros\nKnapsack-problem-0-1\nKnapsack-problem-Bounded\nKnapsack-problem-Continuous\nKnights-tour\nKnuth-shuffle\nKnuths-algorithm-S\nLU-decomposition\nLZW-compression\nLangtons-ant\nLargest-int-from-concatenated-ints\nLast-Friday-of-each-month\nLast-letter-first-letter\nLeap-year\nLeast-common-multiple\nLeft-factorials\nLetter-frequency\nLevenshtein-distance\nLinear-congruential-generator\nList-comprehensions\nLiterals-Floating-point\nLiterals-Integer\nLiterals-String\nLogical-operations\nLong-multiplication\nLongest-common-subsequence\nLongest-increasing-subsequence\nLongest-string-challenge\nLook-and-say-sequence\nLoop-over-multiple-arrays-simultaneously\nLoops-Break\nLoops-Continue\nLoops-Do-while\nLoops-Downward-for\nLoops-For\nLoops-For-with-a-specified-step\nLoops-Foreach\nLoops-Infinite\nLoops-N-plus-one-half\nLoops-Nested\nLoops-While\nLucas-Lehmer-test\nLudic-numbers\nLuhn-test-of-credit-card-numbers\nMD4\nMD5\nMD5-Implementation\nMachine-code\nMad-Libs\nMagic-squares-of-odd-order\nMain-step-of-GOST-28147-89\nMake-directory-path\nMan-or-boy-test\nMandelbrot-set\nMap-range\nMatrix-arithmetic\nMatrix-exponentiation-operator\nMatrix-multiplication\nMatrix-transposition\nMaximum-triangle-path-sum\nMaze-generation\nMaze-solving\nMedian-filter\nMemory-allocation\nMemory-layout-of-a-data-structure\nMenu\nMetaprogramming\nMetered-concurrency\nMetronome\nMiddle-three-digits\nMinesweeper-game\nModular-exponentiation\nModular-inverse\nMonte-Carlo-methods\nMonty-Hall-problem\nMorse-code\nMouse-position\nMove-to-front-algorithm\nMultifactorial\nMultiple-distinct-objects\nMultiple-regression\nMultiplication-tables\nMultiplicative-order\nMultisplit\nMunching-squares\nMutual-recursion\nN-queens-problem\nNamed-parameters\nNarcissist\nNarcissistic-decimal-number\nNatural-sorting\nNautical-bell\nNon-continuous-subsequences\nNon-decimal-radices-Convert\nNon-decimal-radices-Input\nNon-decimal-radices-Output\nNth\nNth-root\nNull-object\nNumber-reversal-game\nNumeric-error-propagation\nNumerical-integration\nNumerical-integration-Gauss-Legendre-Quadrature\nOLE-Automation\nObject-serialization\nOdd-word-problem\nOld-lady-swallowed-a-fly\nOne-dimensional-cellular-automata\nOne-of-n-lines-in-a-file\nOpenGL\nOptional-parameters\nOrder-disjoint-list-items\nOrder-two-numerical-lists\nOrdered-Partitions\nOrdered-words\nPalindrome-detection\nPangram-checker\nParaffins\nParallel-calculations\nParametrized-SQL-statement\nParse-an-IP-Address\nParsing-RPN-calculator-algorithm\nParsing-RPN-to-infix-conversion\nParsing-Shunting-yard-algorithm\nPartial-function-application\nPascals-triangle\nPascals-triangle-Puzzle\nPenneys-game\nPercentage-difference-between-images\nPercolation-Bond-percolation\nPercolation-Mean-cluster-density\nPercolation-Mean-run-density\nPercolation-Site-percolation\nPerfect-numbers\nPermutation-test\nPermutations\nPermutations-Derangements\nPermutations-Rank-of-a-permutation\nPermutations-by-swapping\nPernicious-numbers\nPhrase-reversals\nPi\nPick-random-element\nPig-the-dice-game\nPig-the-dice-game-Player\nPinstripe-Display\nPlay-recorded-sounds\nPlaying-cards\nPlot-coordinate-pairs\nPointers-and-references\nPolymorphic-copy\nPolymorphism\nPolynomial-long-division\nPolynomial-regression\nPower-set\nPragmatic-directives\nPrice-fraction\nPrimality-by-trial-division\nPrime-decomposition\nPriority-queue\nProbabilistic-choice\nProblem-of-Apollonius\nProgram-name\nProgram-termination\nPythagorean-triples\nQR-decomposition\nQuaternion-type\nQueue-Definition\nQueue-Usage\nQuickselect-algorithm\nQuine\nREADME\nRIPEMD-160\nRSA-code\nRandom-number-generator--device-\nRandom-numbers\nRange-expansion\nRange-extraction\nRanking-methods\nRate-counter\nRay-casting-algorithm\nRead-a-configuration-file\nRead-a-file-line-by-line\nRead-a-specific-line-from-a-file\nRead-entire-file\nReal-constants-and-functions\nRecord-sound\nReduced-row-echelon-form\nRegular-expressions\nRemove-duplicate-elements\nRemove-lines-from-a-file\nRename-a-file\nRep-string\nRepeat-a-string\nResistor-mesh\nRespond-to-an-unknown-method-call\nReturn-multiple-values\nReverse-a-string\nReverse-words-in-a-string\nRock-paper-scissors\nRoman-numerals-Decode\nRoman-numerals-Encode\nRoots-of-a-function\nRoots-of-a-quadratic-function\nRoots-of-unity\nRot-13\nRun-length-encoding\nRunge-Kutta-method\nRuntime-evaluation\nRuntime-evaluation-In-an-environment\nS-Expressions\nSEDOLs\nSHA-1\nSHA-256\nSOAP\nSQL-based-authentication\nSafe-addition\nSame-Fringe\nScope-modifiers\nSearch-a-list\nSecure-temporary-file\nSelf-describing-numbers\nSelf-referential-sequence\nSemiprime\nSemordnilap\nSend-an-unknown-method-call\nSend-email\nSequence-of-non-squares\nSequence-of-primes-by-Trial-Division\nSet\nSet-consolidation\nSet-of-real-numbers\nSet-puzzle\nSeven-sided-dice-from-five-sided-dice\nShell-one-liner\nShort-circuit-evaluation\nShow-the-epoch\nSierpinski-carpet\nSierpinski-triangle\nSierpinski-triangle-Graphical\nSieve-of-Eratosthenes\nSimple-database\nSimple-windowed-application\nSimulate-input-Keyboard\nSimulate-input-Mouse\nSingleton\nSingly-linked-list-Element-definition\nSingly-linked-list-Element-insertion\nSingly-linked-list-Traversal\nSleep\nSockets\nSokoban\nSolve-a-Hidato-puzzle\nSolve-a-Holy-Knights-tour\nSolve-a-Hopido-puzzle\nSolve-a-Numbrix-puzzle\nSolve-the-no-connection-puzzle\nSort-an-array-of-composite-structures\nSort-an-integer-array\nSort-disjoint-sublist\nSort-using-a-custom-comparator\nSorting-algorithms-Bead-sort\nSorting-algorithms-Bogosort\nSorting-algorithms-Bubble-sort\nSorting-algorithms-Cocktail-sort\nSorting-algorithms-Comb-sort\nSorting-algorithms-Counting-sort\nSorting-algorithms-Gnome-sort\nSorting-algorithms-Heapsort\nSorting-algorithms-Insertion-sort\nSorting-algorithms-Merge-sort\nSorting-algorithms-Pancake-sort\nSorting-algorithms-Permutation-sort\nSorting-algorithms-Quicksort\nSorting-algorithms-Radix-sort\nSorting-algorithms-Selection-sort\nSorting-algorithms-Shell-sort\nSorting-algorithms-Sleep-sort\nSorting-algorithms-Stooge-sort\nSorting-algorithms-Strand-sort\nSoundex\nSparkline-in-unicode\nSpecial-variables\nSpeech-synthesis\nSpiral-matrix\nStable-marriage-problem\nStack\nStack-traces\nStair-climbing-puzzle\nState-name-puzzle\nStatistics-Basic\nStem-and-leaf-plot\nStern-Brocot-sequence\nString-append\nString-case\nString-comparison\nString-concatenation\nString-interpolation--included-\nString-length\nString-matching\nString-prepend\nStrip-a-set-of-characters-from-a-string\nStrip-block-comments\nStrip-comments-from-a-string\nStrip-control-codes-and-extended-characters-from-a-string\nStrip-whitespace-from-a-string-Top-and-tail\nSubstring\nSubstring-Top-and-tail\nSubtractive-generator\nSudoku\nSum-and-product-of-an-array\nSum-digits-of-an-integer\nSum-multiples-of-3-and-5\nSum-of-a-series\nSum-of-squares\nSutherland-Hodgman-polygon-clipping\nSymmetric-difference\nSynchronous-concurrency\nSystem-time\nTable-creation-Postal-addresses\nTake-notes-on-the-command-line\nTemperature-conversion\nTerminal-control-Clear-the-screen\nTerminal-control-Coloured-text\nTerminal-control-Cursor-movement\nTerminal-control-Cursor-positioning\nTerminal-control-Dimensions\nTerminal-control-Display-an-extended-character\nTerminal-control-Hiding-the-cursor\nTerminal-control-Inverse-video\nTerminal-control-Positional-read\nTerminal-control-Preserve-screen\nTerminal-control-Ringing-the-terminal-bell\nTerminal-control-Unicode-output\nTernary-logic\nTest-a-function\nText-processing-1\nText-processing-2\nText-processing-Max-licenses-in-use\nTextonyms\nThe-ISAAC-Cipher\nThe-Twelve-Days-of-Christmas\nThieles-interpolation-formula\nTic-tac-toe\nTime-a-function\nTokenize-a-string\nTop-rank-per-group\nTopic-variable\nTopological-sort\nTopswops\nTotal-circles-area\nTowers-of-Hanoi\nTrabb-Pardo-Knuth-algorithm\nTree-traversal\nTrigonometric-functions\nTruncate-a-file\nTwelve-statements\nURL-decoding\nURL-encoding\nUlam-spiral--for-primes-\nUnbias-a-random-generator\nUndefined-values\nUnicode-strings\nUnicode-variable-names\nUniversal-Turing-machine\nUnix-ls\nUpdate-a-configuration-file\nUse-another-language-to-call-a-function\nUser-input-Graphical\nUser-input-Text\nVampire-number\nVan-der-Corput-sequence\nVariable-length-quantity\nVariable-size-Get\nVariables\nVariadic-function\nVector-products\nVerify-distribution-uniformity-Chi-squared-test\nVerify-distribution-uniformity-Naive\nVideo-display-modes\nVigen-re-cipher\nVigen-re-cipher-Cryptanalysis\nVisualize-a-tree\nVogels-approximation-method\nVoronoi-diagram\nWalk-a-directory-Non-recursively\nWalk-a-directory-Recursively\nWeb-scraping\nWindow-creation\nWindow-creation-X11\nWindow-management\nWireworld\nWord-wrap\nWorld-Cup-group-stage\nWrite-float-arrays-to-a-text-file\nWrite-language-name-in-3D-ASCII\nWrite-to-Windows-event-log\nXML-DOM-serialization\nXML-Input\nXML-Output\nXML-XPath\nXiaolin-Wus-line-algorithm\nY-combinator\nYahoo--search-interface\nYin-and-yang\nZebra-puzzle\nZeckendorf-arithmetic\nZeckendorf-number-representation\nZero-to-the-zero-power\nZhang-Suen-thinning-algorithm\nZig-zag-matrix\n"
  },
  {
    "path": "tests/results/21",
    "content": "\u001b[38;5;246;03m// Single-line comments start with two slashes.\u001b[39;00m\n\u001b[38;5;246;03m/* Multiline comments start with slash-star,\u001b[39;00m\n\u001b[38;5;246;03m   and end with star-slash */\u001b[39;00m\n\n\u001b[38;5;246;03m// Statements can be terminated by ;\u001b[39;00m\n\u001b[38;5;252mdoStuff\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// ... but they don't have to be, as semicolons are automatically inserted\u001b[39;00m\n\u001b[38;5;246;03m// wherever there's a newline, except in certain cases.\u001b[39;00m\n\u001b[38;5;252mdoStuff\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;246;03m// Because those cases can cause unexpected results, we'll keep on using\u001b[39;00m\n\u001b[38;5;246;03m// semicolons in this guide.\u001b[39;00m\n\n\u001b[38;5;246;03m///////////////////////////////////\u001b[39;00m\n\u001b[38;5;246;03m// 1. Numbers, Strings and Operators\u001b[39;00m\n\n\u001b[38;5;246;03m// JavaScript has one number type (which is a 64-bit IEEE 754 double).\u001b[39;00m\n\u001b[38;5;246;03m// Doubles have a 52-bit mantissa, which is enough to store integers\u001b[39;00m\n\u001b[38;5;246;03m// up to about 9✕10¹⁵ precisely.\u001b[39;00m\n\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 3\u001b[39;00m\n\u001b[38;5;67m1.5\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 1.5\u001b[39;00m\n\n\u001b[38;5;246;03m// Some basic arithmetic works as you'd expect.\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 2\u001b[39;00m\n\u001b[38;5;67m0.1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0.2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 0.30000000000000004\u001b[39;00m\n\u001b[38;5;67m8\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 7\u001b[39;00m\n\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 20\u001b[39;00m\n\u001b[38;5;67m35\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 7\u001b[39;00m\n\n\u001b[38;5;246;03m// Including uneven division.\u001b[39;00m\n\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 2.5\u001b[39;00m\n\n\u001b[38;5;246;03m// And modulo division.\u001b[39;00m\n\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m%\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 0\u001b[39;00m\n\u001b[38;5;67m30\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m%\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 2\u001b[39;00m\n\u001b[38;5;67m18.5\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m%\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m7\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 4.5\u001b[39;00m\n\n\u001b[38;5;246;03m// Bitwise operations also work; when you perform a bitwise operation your float\u001b[39;00m\n\u001b[38;5;246;03m// is converted to a signed int *up to* 32 bits.\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 4\u001b[39;00m\n\n\u001b[38;5;246;03m// Precedence is enforced with parentheses.\u001b[39;00m\n\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 8\u001b[39;00m\n\n\u001b[38;5;246;03m// There are three special not-a-real-number values:\u001b[39;00m\n\u001b[38;5;70;01mInfinity\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// result of e.g. 1/0\u001b[39;00m\n\u001b[38;5;252m-\u001b[39m\u001b[38;5;70;01mInfinity\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// result of e.g. -1/0\u001b[39;00m\n\u001b[38;5;70;01mNaN\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// result of e.g. 0/0, stands for 'Not a Number'\u001b[39;00m\n\n\u001b[38;5;246;03m// There's also a boolean type.\u001b[39;00m\n\u001b[38;5;70;01mtrue\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mfalse\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Strings are created with ' or \".\u001b[39;00m\n\u001b[38;5;214m'abc'\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;214m\"Hello, world\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Negation uses the ! symbol\u001b[39;00m\n\u001b[38;5;252m!\u001b[39m\u001b[38;5;70;01mtrue\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\u001b[38;5;252m!\u001b[39m\u001b[38;5;70;01mfalse\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// Equality is ===\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\n\u001b[38;5;246;03m// Inequality is !==\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m!==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m!==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// More comparisons\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// Strings are concatenated with +\u001b[39;00m\n\u001b[38;5;214m\"Hello \"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"world!\"\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello world!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// ... which works with more than just strings\u001b[39;00m\n\u001b[38;5;214m\"1, 2, \"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"1, 2, 3\"\u001b[39;00m\n\u001b[38;5;214m\"Hello \"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"world\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"!\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello world,!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// and are compared with < and >\u001b[39;00m\n\u001b[38;5;214m\"a\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"b\"\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// Type coercion is performed for comparisons with double equals...\u001b[39;00m\n\u001b[38;5;214m\"5\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\u001b[38;5;70;01mnull\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mundefined\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// ...unless you use ===\u001b[39;00m\n\u001b[38;5;214m\"5\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\u001b[38;5;70;01mnull\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mundefined\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\n\u001b[38;5;246;03m// ...which can result in some weird behaviour...\u001b[39;00m\n\u001b[38;5;67m13\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m!\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// 14\u001b[39;00m\n\u001b[38;5;214m\"13\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m!\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// '13true'\u001b[39;00m\n\n\u001b[38;5;246;03m// You can access characters in a string with `charAt`\u001b[39;00m\n\u001b[38;5;214m\"This is a string\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcharAt\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m// = 'T'\u001b[39;00m\n\n\u001b[38;5;246;03m// ...or use `substring` to get larger pieces.\u001b[39;00m\n\u001b[38;5;214m\"Hello world\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msubstring\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello\"\u001b[39;00m\n\n\u001b[38;5;246;03m// `length` is a property, so don't use ().\u001b[39;00m\n\u001b[38;5;214m\"Hello\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlength\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 5\u001b[39;00m\n\n\u001b[38;5;246;03m// There's also `null` and `undefined`.\u001b[39;00m\n\u001b[38;5;70;01mnull\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m      \u001b[39m\u001b[38;5;246;03m// used to indicate a deliberate non-value\u001b[39;00m\n\u001b[38;5;70;01mundefined\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// used to indicate a value is not currently present (although\u001b[39;00m\n\u001b[38;5;252m           \u001b[39m\u001b[38;5;246;03m// `undefined` is actually a value itself)\u001b[39;00m\n\n\u001b[38;5;246;03m// false, null, undefined, NaN, 0 and \"\" are falsy; everything else is truthy.\u001b[39;00m\n\u001b[38;5;246;03m// Note that 0 is falsy and \"0\" is truthy, even though 0 == \"0\".\u001b[39;00m\n\n\u001b[38;5;246;03m///////////////////////////////////\u001b[39;00m\n\u001b[38;5;246;03m// 2. Variables, Arrays and Objects\u001b[39;00m\n\n\u001b[38;5;246;03m// Variables are declared with the `var` keyword. JavaScript is dynamically\u001b[39;00m\n\u001b[38;5;246;03m// typed, so you don't need to specify type. Assignment uses a single `=`\u001b[39;00m\n\u001b[38;5;246;03m// character.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// If you leave the var keyword off, you won't get an error...\u001b[39;00m\n\u001b[38;5;252msomeOtherVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// ...but your variable will be created in the global scope, not in the scope\u001b[39;00m\n\u001b[38;5;246;03m// you defined it in.\u001b[39;00m\n\n\u001b[38;5;246;03m// Variables declared without being assigned to are set to undefined.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msomeThirdVar\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = undefined\u001b[39;00m\n\n\u001b[38;5;246;03m// If you want to declare a couple of variables, then you could use a comma\u001b[39;00m\n\u001b[38;5;246;03m// separator\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msomeFourthVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msomeFifthVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// There's shorthand for performing math operations on variables:\u001b[39;00m\n\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// equivalent to someVar = someVar + 5; someVar is 10 now\u001b[39;00m\n\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// now someVar is 100\u001b[39;00m\n\n\u001b[38;5;246;03m// and an even-shorter-hand for adding or subtracting 1\u001b[39;00m\n\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m++\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// now someVar is 101\u001b[39;00m\n\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m--\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// back to 100\u001b[39;00m\n\n\u001b[38;5;246;03m// Arrays are ordered lists of values, of any type.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"Hello\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m45\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mtrue\u001b[39;00m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Their members can be accessed using the square-brackets subscript syntax.\u001b[39;00m\n\u001b[38;5;246;03m// Array indices start at zero.\u001b[39;00m\n\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 45\u001b[39;00m\n\n\u001b[38;5;246;03m// Arrays are mutable and of variable length.\u001b[39;00m\n\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mpush\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"World\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlength\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 4\u001b[39;00m\n\n\u001b[38;5;246;03m// Add/Modify at specific index\u001b[39;00m\n\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Hello\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Add and remove element from front or back end of an array\u001b[39;00m\n\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252munshift\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// Add as the first element\u001b[39;00m\n\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mshift\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// Remove first element and return it\u001b[39;00m\n\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mpush\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// Add as the last element\u001b[39;00m\n\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mpop\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// Remove last element and return it\u001b[39;00m\n\n\u001b[38;5;246;03m// Join all elements of an array with semicolon\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyArray0\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m32\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;70;01mfalse\u001b[39;00m\u001b[38;5;252m,\u001b[39m\u001b[38;5;214m\"js\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m12\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m56\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m90\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyArray0\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mjoin\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\";\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"32;false;js;12;56;90\"\u001b[39;00m\n\n\u001b[38;5;246;03m// Get subarray of elements from index 1 (include) to 4 (exclude)\u001b[39;00m\n\u001b[38;5;252mmyArray0\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mslice\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = [false,\"js\",12]\u001b[39;00m\n\n\u001b[38;5;246;03m// Remove 4 elements starting from index 2, and insert there strings\u001b[39;00m\n\u001b[38;5;246;03m// \"hi\",\"wr\" and \"ld\"; return removed subarray\u001b[39;00m\n\u001b[38;5;252mmyArray0\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msplice\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;214m\"hi\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;214m\"wr\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;214m\"ld\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = [\"js\",12,56,90]\u001b[39;00m\n\u001b[38;5;246;03m// myArray0 === [32,false,\"hi\",\"wr\",\"ld\"]\u001b[39;00m\n\n\u001b[38;5;246;03m// JavaScript's objects are equivalent to \"dictionaries\" or \"maps\" in other\u001b[39;00m\n\u001b[38;5;246;03m// languages: an unordered collection of key-value pairs.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252mkey1\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Hello\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mkey2\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"World\"\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Keys are strings, but quotes aren't required if they're a valid\u001b[39;00m\n\u001b[38;5;246;03m// JavaScript identifier. Values can be any type.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252mmyKey\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"myValue\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"my other key\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Object attributes can also be accessed using the subscript syntax,\u001b[39;00m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"my other key\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 4\u001b[39;00m\n\n\u001b[38;5;246;03m// ... or using the dot syntax, provided the key is a valid identifier.\u001b[39;00m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyKey\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"myValue\"\u001b[39;00m\n\n\u001b[38;5;246;03m// Objects are mutable; values can be changed and new keys added.\u001b[39;00m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyThirdKey\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mtrue\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// If you try to access a value that's not yet set, you'll get undefined.\u001b[39;00m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyFourthKey\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = undefined\u001b[39;00m\n\n\u001b[38;5;246;03m///////////////////////////////////\u001b[39;00m\n\u001b[38;5;246;03m// 3. Logic and Control Structures\u001b[39;00m\n\n\u001b[38;5;246;03m// The `if` structure works as you'd expect.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mcount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// evaluated if count is 3\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01melse\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mcount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// evaluated if count is 4\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01melse\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// evaluated if it's not either 3 or 4\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// As does `while`.\u001b[39;00m\n\u001b[38;5;70;01mwhile\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mtrue\u001b[39;00m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// An infinite loop!\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// Do-while loops are like while loops, except they always run at least once.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252minput\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mdo\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252minput\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mgetInput\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mwhile\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m!\u001b[39m\u001b[38;5;252misValid\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252minput\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// The `for` loop is the same as C and Java:\u001b[39;00m\n\u001b[38;5;246;03m// initialization; continue condition; iteration.\u001b[39;00m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m++\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// will run 5 times\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// Breaking out of labeled loops is similar to Java\u001b[39;00m\n\u001b[38;5;252mouter\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m++\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m++\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m&&\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m            \u001b[39m\u001b[38;5;70;01mbreak\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mouter\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m            \u001b[39m\u001b[38;5;246;03m// breaks out of outer loop instead of only the inner one\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// The for/in statement allows iteration over properties of an object.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdescription\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mperson\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252mfname\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;214m\"Paul\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlname\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;214m\"Ken\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mage\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;67m18\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mperson\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mdescription\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mperson\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\" \"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// description = 'Paul Ken 18 '\u001b[39;00m\n\n\u001b[38;5;246;03m// The for/of statement allows iteration over iterable objects (including the built-in String, \u001b[39;00m\n\u001b[38;5;246;03m// Array, e.g. the Array-like arguments or NodeList objects, TypedArray, Map and Set, \u001b[39;00m\n\u001b[38;5;246;03m// and user-defined iterables).\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyPets\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpets\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"cat\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"dog\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"hamster\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"hedgehog\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpet\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mof\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpets\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyPets\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpet\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\" \"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// myPets = 'cat dog hamster hedgehog '\u001b[39;00m\n\n\u001b[38;5;246;03m// && is logical and, || is logical or\u001b[39;00m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mhouse\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msize\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"big\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m&&\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mhouse\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcolour\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"blue\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mhouse\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcontains\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"bear\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mcolour\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"red\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m||\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcolour\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"blue\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// colour is either red or blue\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// && and || \"short circuit\", which is useful for setting default values.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252motherName\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m||\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"default\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// The `switch` statement checks for equality with `===`.\u001b[39;00m\n\u001b[38;5;246;03m// Use 'break' after each case\u001b[39;00m\n\u001b[38;5;246;03m// or the cases after the correct one will be executed too.\u001b[39;00m\n\u001b[38;5;252mgrade\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'B'\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mswitch\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mgrade\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m  \u001b[39m\u001b[38;5;70;01mcase\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'A'\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mconsole\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlog\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"Great job\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mbreak\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m  \u001b[39m\u001b[38;5;70;01mcase\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'B'\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mconsole\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlog\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"OK job\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mbreak\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m  \u001b[39m\u001b[38;5;70;01mcase\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'C'\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mconsole\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlog\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"You can do better\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mbreak\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m  \u001b[39m\u001b[38;5;70;01mdefault\u001b[39;00m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mconsole\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlog\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"Oy vey\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mbreak\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\n\n\u001b[38;5;246;03m///////////////////////////////////\u001b[39;00m\n\u001b[38;5;246;03m// 4. Functions, Scope and Closures\u001b[39;00m\n\n\u001b[38;5;246;03m// JavaScript functions are declared with the `function` keyword.\u001b[39;00m\n\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mthing\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mthing\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mtoUpperCase\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"foo\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"FOO\"\u001b[39;00m\n\n\u001b[38;5;246;03m// Note that the value to be returned must start on the same line as the\u001b[39;00m\n\u001b[38;5;246;03m// `return` keyword, otherwise you'll always return `undefined` due to\u001b[39;00m\n\u001b[38;5;246;03m// automatic semicolon insertion. Watch out for this when using Allman style.\u001b[39;00m\n\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// <- semicolon automatically inserted here\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252mthisIsAn\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'object literal'\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = undefined\u001b[39;00m\n\n\u001b[38;5;246;03m// JavaScript functions are first class objects, so they can be reassigned to\u001b[39;00m\n\u001b[38;5;246;03m// different variable names and passed to other functions as arguments - for\u001b[39;00m\n\u001b[38;5;246;03m// example, when supplying an event handler:\u001b[39;00m\n\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// this code will be called in 5 seconds' time\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252msetTimeout\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5000\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;246;03m// Note: setTimeout isn't part of the JS language, but is provided by browsers\u001b[39;00m\n\u001b[38;5;246;03m// and Node.js.\u001b[39;00m\n\n\u001b[38;5;246;03m// Another function provided by browsers is setInterval\u001b[39;00m\n\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// this code will be called every 5 seconds\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252msetInterval\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5000\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Function objects don't even have to be declared with a name - you can write\u001b[39;00m\n\u001b[38;5;246;03m// an anonymous function definition directly into the arguments of another.\u001b[39;00m\n\u001b[38;5;252msetTimeout\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// this code will be called in 5 seconds' time\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5000\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// JavaScript has function scope; functions get their own scope but other blocks\u001b[39;00m\n\u001b[38;5;246;03m// do not.\u001b[39;00m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mtrue\u001b[39;00m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 5 - not undefined as you'd expect in a block-scoped language\u001b[39;00m\n\n\u001b[38;5;246;03m// This has led to a common pattern of \"immediately-executing anonymous\u001b[39;00m\n\u001b[38;5;246;03m// functions\", which prevent temporary variables from leaking into the global\u001b[39;00m\n\u001b[38;5;246;03m// scope.\u001b[39;00m\n\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtemporary\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// We can access the global scope by assigning to the \"global object\", which\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// in a web browser is always `window`. The global object may have a\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// different name in non-browser environments such as Node.js.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mwindow\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mpermanent\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mtemporary\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// raises ReferenceError\u001b[39;00m\n\u001b[38;5;252mpermanent\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 10\u001b[39;00m\n\n\u001b[38;5;246;03m// One of JavaScript's most powerful features is closures. If a function is\u001b[39;00m\n\u001b[38;5;246;03m// defined inside another function, the inner function has access to all the\u001b[39;00m\n\u001b[38;5;246;03m// outer function's variables, even after the outer function exits.\u001b[39;00m\n\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msayHelloInFiveSeconds\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mprompt\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Hello, \"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"!\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// Inner functions are put in the local scope by default, as if they were\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// declared with `var`.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252minner\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;252malert\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mprompt\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252msetTimeout\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252minner\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5000\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// setTimeout is asynchronous, so the sayHelloInFiveSeconds function will\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// exit immediately, and setTimeout will call inner afterwards. However,\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// because inner is \"closed over\" sayHelloInFiveSeconds, inner still has\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// access to the `prompt` variable when it is finally called.\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252msayHelloInFiveSeconds\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"Adam\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// will open a popup with \"Hello, Adam!\" in 5s\u001b[39;00m\n\n\u001b[38;5;246;03m///////////////////////////////////\u001b[39;00m\n\u001b[38;5;246;03m// 5. More about Objects; Constructors and Prototypes\u001b[39;00m\n\n\u001b[38;5;246;03m// Objects can contain functions.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Hello world!\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello world!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// When functions attached to an object are called, they can access the object\u001b[39;00m\n\u001b[38;5;246;03m// they're attached to using the `this` keyword.\u001b[39;00m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyString\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Hello world!\"\u001b[39m\u001b[38;5;252m,\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyString\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello world!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// What this is set to has to do with how the function is called, not where\u001b[39;00m\n\u001b[38;5;246;03m// it's defined. So, our function doesn't work if it isn't called in the\u001b[39;00m\n\u001b[38;5;246;03m// context of the object.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = undefined\u001b[39;00m\n\n\u001b[38;5;246;03m// Inversely, a function can be assigned to the object and gain access to it\u001b[39;00m\n\u001b[38;5;246;03m// through `this`, even if it wasn't attached when it was defined.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyOtherFunc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyString\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mtoUpperCase\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyOtherFunc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyOtherFunc\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyOtherFunc\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"HELLO WORLD!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// We can also specify a context for a function to execute in when we invoke it\u001b[39;00m\n\u001b[38;5;246;03m// using `call` or `apply`.\u001b[39;00m\n\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252manotherFunc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252ms\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyString\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ms\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252manotherFunc\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcall\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\" And Hello Moon!\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello World! And Hello Moon!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// The `apply` function is nearly identical, but takes an array for an argument\u001b[39;00m\n\u001b[38;5;246;03m// list.\u001b[39;00m\n\n\u001b[38;5;252manotherFunc\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mapply\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\" And Hello Sun!\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello World! And Hello Sun!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// This is useful when working with a function that accepts a sequence of\u001b[39;00m\n\u001b[38;5;246;03m// arguments and you want to pass an array.\u001b[39;00m\n\n\u001b[38;5;31mMath\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmin\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m42\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m27\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 6\u001b[39;00m\n\u001b[38;5;31mMath\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmin\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m42\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m27\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = NaN (uh-oh!)\u001b[39;00m\n\u001b[38;5;31mMath\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmin\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mapply\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mMath\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m42\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m27\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 6\u001b[39;00m\n\n\u001b[38;5;246;03m// But, `call` and `apply` are only temporary. When we want it to stick, we can\u001b[39;00m\n\u001b[38;5;246;03m// use `bind`.\u001b[39;00m\n\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mboundFunc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252manotherFunc\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mbind\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mboundFunc\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\" And Hello Saturn!\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello World! And Hello Saturn!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// `bind` can also be used to partially apply (curry) a function.\u001b[39;00m\n\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mproduct\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252ma\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ma\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdoubler\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mproduct\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mbind\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mdoubler\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m8\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 16\u001b[39;00m\n\n\u001b[38;5;246;03m// When you call a function with the `new` keyword, a new object is created, and\u001b[39;00m\n\u001b[38;5;246;03m// made available to the function via the `this` keyword. Functions designed to be\u001b[39;00m\n\u001b[38;5;246;03m// called like that are called constructors.\u001b[39;00m\n\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyConstructor\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyNewObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mnew\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyConstructor\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = {myNumber: 5}\u001b[39;00m\n\u001b[38;5;252mmyNewObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 5\u001b[39;00m\n\n\u001b[38;5;246;03m// Unlike most other popular object-oriented languages, JavaScript has no\u001b[39;00m\n\u001b[38;5;246;03m// concept of 'instances' created from 'class' blueprints; instead, JavaScript\u001b[39;00m\n\u001b[38;5;246;03m// combines instantiation and inheritance into a single concept: a 'prototype'.\u001b[39;00m\n\n\u001b[38;5;246;03m// Every JavaScript object has a 'prototype'. When you go to access a property\u001b[39;00m\n\u001b[38;5;246;03m// on an object that doesn't exist on the actual object, the interpreter will\u001b[39;00m\n\u001b[38;5;246;03m// look at its prototype.\u001b[39;00m\n\n\u001b[38;5;246;03m// Some JS implementations let you access an object's prototype on the magic\u001b[39;00m\n\u001b[38;5;246;03m// property `__proto__`. While this is useful for explaining prototypes it's not\u001b[39;00m\n\u001b[38;5;246;03m// part of the standard; we'll get to standard ways of using prototypes later.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyString\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Hello world!\"\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyPrototype\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmeaningOfLife\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m42\u001b[39m\u001b[38;5;252m,\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyString\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mtoLowerCase\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252m__proto__\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyPrototype\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmeaningOfLife\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 42\u001b[39;00m\n\n\u001b[38;5;246;03m// This works for functions, too.\u001b[39;00m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"hello world!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// Of course, if your property isn't on your prototype, the prototype's\u001b[39;00m\n\u001b[38;5;246;03m// prototype is searched, and so on.\u001b[39;00m\n\u001b[38;5;252mmyPrototype\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252m__proto__\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyBoolean\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mtrue\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyBoolean\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// There's no copying involved here; each object stores a reference to its\u001b[39;00m\n\u001b[38;5;246;03m// prototype. This means we can alter the prototype and our changes will be\u001b[39;00m\n\u001b[38;5;246;03m// reflected everywhere.\u001b[39;00m\n\u001b[38;5;252mmyPrototype\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmeaningOfLife\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m43\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmeaningOfLife\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 43\u001b[39;00m\n\n\u001b[38;5;246;03m// The for/in statement allows iteration over properties of an object,\u001b[39;00m\n\u001b[38;5;246;03m// walking up the prototype chain until it sees a null prototype.\u001b[39;00m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mconsole\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlog\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;246;03m///prints:\u001b[39;00m\n\u001b[38;5;246;03m// Hello world!\u001b[39;00m\n\u001b[38;5;246;03m// 43\u001b[39;00m\n\u001b[38;5;246;03m// [Function: myFunc]\u001b[39;00m\n\u001b[38;5;246;03m// true\u001b[39;00m\n\n\u001b[38;5;246;03m// To only consider properties attached to the object itself\u001b[39;00m\n\u001b[38;5;246;03m// and not its prototypes, use the `hasOwnProperty()` check.\u001b[39;00m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mhasOwnProperty\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;252mconsole\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlog\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;246;03m///prints:\u001b[39;00m\n\u001b[38;5;246;03m// Hello world!\u001b[39;00m\n\n\u001b[38;5;246;03m// We mentioned that `__proto__` was non-standard, and there's no standard way to\u001b[39;00m\n\u001b[38;5;246;03m// change the prototype of an existing object. However, there are two ways to\u001b[39;00m\n\u001b[38;5;246;03m// create a new object with a given prototype.\u001b[39;00m\n\n\u001b[38;5;246;03m// The first is Object.create, which is a recent addition to JS, and therefore\u001b[39;00m\n\u001b[38;5;246;03m// not available in all implementations yet.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mObject\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyPrototype\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmeaningOfLife\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 43\u001b[39;00m\n\n\u001b[38;5;246;03m// The second way, which works anywhere, has to do with constructors.\u001b[39;00m\n\u001b[38;5;246;03m// Constructors have a property called prototype. This is *not* the prototype of\u001b[39;00m\n\u001b[38;5;246;03m// the constructor function itself; instead, it's the prototype that new objects\u001b[39;00m\n\u001b[38;5;246;03m// are given when they're created with that constructor and the new keyword.\u001b[39;00m\n\u001b[38;5;252mMyConstructor\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mprototype\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m,\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mgetMyNumber\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNewObj2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mnew\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyConstructor\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyNewObj2\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mgetMyNumber\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 5\u001b[39;00m\n\u001b[38;5;252mmyNewObj2\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyNewObj2\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mgetMyNumber\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 6\u001b[39;00m\n\n\u001b[38;5;246;03m// Built-in types like strings and numbers also have constructors that create\u001b[39;00m\n\u001b[38;5;246;03m// equivalent wrapper objects.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m12\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNumberObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mnew\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mNumber\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m12\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNumberObj\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// Except, they aren't exactly equivalent.\u001b[39;00m\n\u001b[38;5;70;01mtypeof\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 'number'\u001b[39;00m\n\u001b[38;5;70;01mtypeof\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNumberObj\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 'object'\u001b[39;00m\n\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNumberObj\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// This code won't execute, because 0 is falsy.\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mnew\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mNumber\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m// This code will execute, because wrapped numbers are objects, and objects\u001b[39;00m\n\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m// are always truthy.\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// However, the wrapper objects and the regular builtins share a prototype, so\u001b[39;00m\n\u001b[38;5;246;03m// you can actually add functionality to a string, for instance.\u001b[39;00m\n\u001b[38;5;31mString\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mprototype\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mfirstCharacter\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcharAt\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;214m\"abc\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mfirstCharacter\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"a\"\u001b[39;00m\n\n\u001b[38;5;246;03m// This fact is often used in \"polyfilling\", which is implementing newer\u001b[39;00m\n\u001b[38;5;246;03m// features of JavaScript in an older subset of JavaScript, so that they can be\u001b[39;00m\n\u001b[38;5;246;03m// used in older environments such as outdated browsers.\u001b[39;00m\n\n\u001b[38;5;246;03m// For instance, we mentioned that Object.create isn't yet available in all\u001b[39;00m\n\u001b[38;5;246;03m// implementations, but we can still use it with this polyfill:\u001b[39;00m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mObject\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mundefined\u001b[39;00m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// don't overwrite it if it exists\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mObject\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mproto\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m// make a temporary constructor with the right prototype\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mConstructor\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;252mConstructor\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mprototype\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mproto\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m// then use it to create a new, appropriately-prototyped object\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mnew\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mConstructor\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// ES6 Additions\u001b[39;00m\n\n\u001b[38;5;246;03m// The \"let\" keyword allows you to define variables in a lexical scope, \u001b[39;00m\n\u001b[38;5;246;03m// as opposed to a block scope like the var keyword does.\u001b[39;00m\n\u001b[38;5;70;01mlet\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Billy\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Variables defined with let can be reassigned new values.\u001b[39;00m\n\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"William\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// The \"const\" keyword allows you to define a variable in a lexical scope\u001b[39;00m\n\u001b[38;5;246;03m// like with let, but you cannot reassign the value once one has been assigned.\u001b[39;00m\n\n\u001b[38;5;70;01mconst\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3.14\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;252mpi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4.13\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// You cannot do this.\u001b[39;00m\n\n\u001b[38;5;246;03m// There is a new syntax for functions in ES6 known as \"lambda syntax\".\u001b[39;00m\n\u001b[38;5;246;03m// This allows functions to be defined in a lexical scope like with variables\u001b[39;00m\n\u001b[38;5;246;03m// defined by const and let. \u001b[39;00m\n\n\u001b[38;5;70;01mconst\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252misEven\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mnumber\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mnumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m%\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;252misEven\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m7\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// false\u001b[39;00m\n\n\u001b[38;5;246;03m// The \"equivalent\" of this function in the traditional syntax would look like this:\u001b[39;00m\n\n\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252misEven\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mnumber\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mnumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m%\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// I put the word \"equivalent\" in double quotes because a function defined\u001b[39;00m\n\u001b[38;5;246;03m// using the lambda syntax cannnot be called before the definition.\u001b[39;00m\n\u001b[38;5;246;03m// The following is an example of invalid usage:\u001b[39;00m\n\n\u001b[38;5;252madd\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m8\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;70;01mconst\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252madd\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mfirstNumber\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msecondNumber\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfirstNumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msecondNumber\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n"
  },
  {
    "path": "tests/results/22",
    "content": "\u001b[38;5;246;03m// Single-line comments start with two slashes.\u001b[39;00m\n\u001b[38;5;246;03m/* Multiline comments start with slash-star,\u001b[39;00m\n\u001b[38;5;246;03m   and end with star-slash */\u001b[39;00m\n\n\u001b[38;5;246;03m// Statements can be terminated by ;\u001b[39;00m\n\u001b[38;5;252mdoStuff\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// ... but they don't have to be, as semicolons are automatically inserted\u001b[39;00m\n\u001b[38;5;246;03m// wherever there's a newline, except in certain cases.\u001b[39;00m\n\u001b[38;5;252mdoStuff\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;246;03m// Because those cases can cause unexpected results, we'll keep on using\u001b[39;00m\n\u001b[38;5;246;03m// semicolons in this guide.\u001b[39;00m\n\n\u001b[38;5;246;03m///////////////////////////////////\u001b[39;00m\n\u001b[38;5;246;03m// 1. Numbers, Strings and Operators\u001b[39;00m\n\n\u001b[38;5;246;03m// JavaScript has one number type (which is a 64-bit IEEE 754 double).\u001b[39;00m\n\u001b[38;5;246;03m// Doubles have a 52-bit mantissa, which is enough to store integers\u001b[39;00m\n\u001b[38;5;246;03m// up to about 9✕10¹⁵ precisely.\u001b[39;00m\n\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 3\u001b[39;00m\n\u001b[38;5;67m1.5\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 1.5\u001b[39;00m\n\n\u001b[38;5;246;03m// Some basic arithmetic works as you'd expect.\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 2\u001b[39;00m\n\u001b[38;5;67m0.1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0.2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 0.30000000000000004\u001b[39;00m\n\u001b[38;5;67m8\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 7\u001b[39;00m\n\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 20\u001b[39;00m\n\u001b[38;5;67m35\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 7\u001b[39;00m\n\n\u001b[38;5;246;03m// Including uneven division.\u001b[39;00m\n\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 2.5\u001b[39;00m\n\n\u001b[38;5;246;03m// And modulo division.\u001b[39;00m\n\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m%\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 0\u001b[39;00m\n\u001b[38;5;67m30\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m%\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 2\u001b[39;00m\n\u001b[38;5;67m18.5\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m%\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m7\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 4.5\u001b[39;00m\n\n\u001b[38;5;246;03m// Bitwise operations also work; when you perform a bitwise operation your float\u001b[39;00m\n\u001b[38;5;246;03m// is converted to a signed int *up to* 32 bits.\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 4\u001b[39;00m\n\n\u001b[38;5;246;03m// Precedence is enforced with parentheses.\u001b[39;00m\n\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 8\u001b[39;00m\n\n\u001b[38;5;246;03m// There are three special not-a-real-number values:\u001b[39;00m\n\u001b[38;5;70;01mInfinity\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// result of e.g. 1/0\u001b[39;00m\n\u001b[38;5;252m-\u001b[39m\u001b[38;5;70;01mInfinity\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// result of e.g. -1/0\u001b[39;00m\n\u001b[38;5;70;01mNaN\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// result of e.g. 0/0, stands for 'Not a Number'\u001b[39;00m\n\n\u001b[38;5;246;03m// There's also a boolean type.\u001b[39;00m\n\u001b[38;5;70;01mtrue\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mfalse\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Strings are created with ' or \".\u001b[39;00m\n\u001b[38;5;214m'abc'\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;214m\"Hello, world\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Negation uses the ! symbol\u001b[39;00m\n\u001b[38;5;252m!\u001b[39m\u001b[38;5;70;01mtrue\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\u001b[38;5;252m!\u001b[39m\u001b[38;5;70;01mfalse\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// Equality is ===\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\n\u001b[38;5;246;03m// Inequality is !==\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m!==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m!==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// More comparisons\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m>=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// Strings are concatenated with +\u001b[39;00m\n\u001b[38;5;214m\"Hello \"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"world!\"\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello world!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// ... which works with more than just strings\u001b[39;00m\n\u001b[38;5;214m\"1, 2, \"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"1, 2, 3\"\u001b[39;00m\n\u001b[38;5;214m\"Hello \"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"world\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"!\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello world,!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// and are compared with < and >\u001b[39;00m\n\u001b[38;5;214m\"a\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"b\"\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// Type coercion is performed for comparisons with double equals...\u001b[39;00m\n\u001b[38;5;214m\"5\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\u001b[38;5;70;01mnull\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mundefined\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// ...unless you use ===\u001b[39;00m\n\u001b[38;5;214m\"5\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\u001b[38;5;70;01mnull\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mundefined\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\n\u001b[38;5;246;03m// ...which can result in some weird behaviour...\u001b[39;00m\n\u001b[38;5;67m13\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m!\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// 14\u001b[39;00m\n\u001b[38;5;214m\"13\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m!\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// '13true'\u001b[39;00m\n\n\u001b[38;5;246;03m// You can access characters in a string with `charAt`\u001b[39;00m\n\u001b[38;5;214m\"This is a string\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcharAt\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m  \u001b[39m\u001b[38;5;246;03m// = 'T'\u001b[39;00m\n\n\u001b[38;5;246;03m// ...or use `substring` to get larger pieces.\u001b[39;00m\n\u001b[38;5;214m\"Hello world\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msubstring\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello\"\u001b[39;00m\n\n\u001b[38;5;246;03m// `length` is a property, so don't use ().\u001b[39;00m\n\u001b[38;5;214m\"Hello\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlength\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 5\u001b[39;00m\n\n\u001b[38;5;246;03m// There's also `null` and `undefined`.\u001b[39;00m\n\u001b[38;5;70;01mnull\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m      \u001b[39m\u001b[38;5;246;03m// used to indicate a deliberate non-value\u001b[39;00m\n\u001b[38;5;70;01mundefined\u001b[39;00m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// used to indicate a value is not currently present (although\u001b[39;00m\n\u001b[38;5;252m           \u001b[39m\u001b[38;5;246;03m// `undefined` is actually a value itself)\u001b[39;00m\n\n\u001b[38;5;246;03m// false, null, undefined, NaN, 0 and \"\" are falsy; everything else is truthy.\u001b[39;00m\n\u001b[38;5;246;03m// Note that 0 is falsy and \"0\" is truthy, even though 0 == \"0\".\u001b[39;00m\n\n\u001b[38;5;246;03m///////////////////////////////////\u001b[39;00m\n\u001b[38;5;246;03m// 2. Variables, Arrays and Objects\u001b[39;00m\n\n\u001b[38;5;246;03m// Variables are declared with the `var` keyword. JavaScript is dynamically\u001b[39;00m\n\u001b[38;5;246;03m// typed, so you don't need to specify type. Assignment uses a single `=`\u001b[39;00m\n\u001b[38;5;246;03m// character.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// If you leave the var keyword off, you won't get an error...\u001b[39;00m\n\u001b[38;5;252msomeOtherVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// ...but your variable will be created in the global scope, not in the scope\u001b[39;00m\n\u001b[38;5;246;03m// you defined it in.\u001b[39;00m\n\n\u001b[38;5;246;03m// Variables declared without being assigned to are set to undefined.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msomeThirdVar\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = undefined\u001b[39;00m\n\n\u001b[38;5;246;03m// If you want to declare a couple of variables, then you could use a comma\u001b[39;00m\n\u001b[38;5;246;03m// separator\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msomeFourthVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msomeFifthVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// There's shorthand for performing math operations on variables:\u001b[39;00m\n\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// equivalent to someVar = someVar + 5; someVar is 10 now\u001b[39;00m\n\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// now someVar is 100\u001b[39;00m\n\n\u001b[38;5;246;03m// and an even-shorter-hand for adding or subtracting 1\u001b[39;00m\n\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m++\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// now someVar is 101\u001b[39;00m\n\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m--\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// back to 100\u001b[39;00m\n\n\u001b[38;5;246;03m// Arrays are ordered lists of values, of any type.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"Hello\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m45\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mtrue\u001b[39;00m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Their members can be accessed using the square-brackets subscript syntax.\u001b[39;00m\n\u001b[38;5;246;03m// Array indices start at zero.\u001b[39;00m\n\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 45\u001b[39;00m\n\n\u001b[38;5;246;03m// Arrays are mutable and of variable length.\u001b[39;00m\n\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mpush\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"World\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlength\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 4\u001b[39;00m\n\n\u001b[38;5;246;03m// Add/Modify at specific index\u001b[39;00m\n\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Hello\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Add and remove element from front or back end of an array\u001b[39;00m\n\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252munshift\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// Add as the first element\u001b[39;00m\n\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mshift\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// Remove first element and return it\u001b[39;00m\n\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mpush\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// Add as the last element\u001b[39;00m\n\u001b[38;5;252msomeVar\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyArray\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mpop\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// Remove last element and return it\u001b[39;00m\n\n\u001b[38;5;246;03m// Join all elements of an array with semicolon\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyArray0\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m32\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;70;01mfalse\u001b[39;00m\u001b[38;5;252m,\u001b[39m\u001b[38;5;214m\"js\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m12\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m56\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m90\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyArray0\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mjoin\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\";\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"32;false;js;12;56;90\"\u001b[39;00m\n\n\u001b[38;5;246;03m// Get subarray of elements from index 1 (include) to 4 (exclude)\u001b[39;00m\n\u001b[38;5;252mmyArray0\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mslice\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = [false,\"js\",12]\u001b[39;00m\n\n\u001b[38;5;246;03m// Remove 4 elements starting from index 2, and insert there strings\u001b[39;00m\n\u001b[38;5;246;03m// \"hi\",\"wr\" and \"ld\"; return removed subarray\u001b[39;00m\n\u001b[38;5;252mmyArray0\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msplice\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;214m\"hi\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;214m\"wr\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;214m\"ld\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = [\"js\",12,56,90]\u001b[39;00m\n\u001b[38;5;246;03m// myArray0 === [32,false,\"hi\",\"wr\",\"ld\"]\u001b[39;00m\n\n\u001b[38;5;246;03m// JavaScript's objects are equivalent to \"dictionaries\" or \"maps\" in other\u001b[39;00m\n\u001b[38;5;246;03m// languages: an unordered collection of key-value pairs.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252mkey1\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Hello\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mkey2\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"World\"\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Keys are strings, but quotes aren't required if they're a valid\u001b[39;00m\n\u001b[38;5;246;03m// JavaScript identifier. Values can be any type.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252mmyKey\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"myValue\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"my other key\"\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Object attributes can also be accessed using the subscript syntax,\u001b[39;00m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"my other key\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 4\u001b[39;00m\n\n\u001b[38;5;246;03m// ... or using the dot syntax, provided the key is a valid identifier.\u001b[39;00m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyKey\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"myValue\"\u001b[39;00m\n\n\u001b[38;5;246;03m// Objects are mutable; values can be changed and new keys added.\u001b[39;00m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyThirdKey\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mtrue\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// If you try to access a value that's not yet set, you'll get undefined.\u001b[39;00m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyFourthKey\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = undefined\u001b[39;00m\n\n\u001b[38;5;246;03m///////////////////////////////////\u001b[39;00m\n\u001b[38;5;246;03m// 3. Logic and Control Structures\u001b[39;00m\n\n\u001b[38;5;246;03m// The `if` structure works as you'd expect.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mcount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// evaluated if count is 3\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01melse\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mcount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// evaluated if count is 4\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01melse\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// evaluated if it's not either 3 or 4\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// As does `while`.\u001b[39;00m\n\u001b[38;5;70;01mwhile\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mtrue\u001b[39;00m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// An infinite loop!\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// Do-while loops are like while loops, except they always run at least once.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252minput\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mdo\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252minput\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mgetInput\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mwhile\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m!\u001b[39m\u001b[38;5;252misValid\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252minput\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// The `for` loop is the same as C and Java:\u001b[39;00m\n\u001b[38;5;246;03m// initialization; continue condition; iteration.\u001b[39;00m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m++\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// will run 5 times\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// Breaking out of labeled loops is similar to Java\u001b[39;00m\n\u001b[38;5;252mouter\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m++\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m<\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m++\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m&&\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m            \u001b[39m\u001b[38;5;70;01mbreak\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mouter\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m            \u001b[39m\u001b[38;5;246;03m// breaks out of outer loop instead of only the inner one\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// The for/in statement allows iteration over properties of an object.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdescription\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mperson\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252mfname\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;214m\"Paul\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlname\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;214m\"Ken\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mage\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;67m18\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mperson\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mdescription\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mperson\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\" \"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// description = 'Paul Ken 18 '\u001b[39;00m\n\n\u001b[38;5;246;03m// The for/of statement allows iteration over iterable objects (including the built-in String, \u001b[39;00m\n\u001b[38;5;246;03m// Array, e.g. the Array-like arguments or NodeList objects, TypedArray, Map and Set, \u001b[39;00m\n\u001b[38;5;246;03m// and user-defined iterables).\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyPets\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpets\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\"cat\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"dog\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"hamster\"\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"hedgehog\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpet\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mof\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpets\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyPets\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpet\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\" \"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// myPets = 'cat dog hamster hedgehog '\u001b[39;00m\n\n\u001b[38;5;246;03m// && is logical and, || is logical or\u001b[39;00m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mhouse\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252msize\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"big\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m&&\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mhouse\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcolour\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"blue\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mhouse\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcontains\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"bear\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mcolour\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"red\"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m||\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcolour\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"blue\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// colour is either red or blue\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// && and || \"short circuit\", which is useful for setting default values.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252motherName\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m||\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"default\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// The `switch` statement checks for equality with `===`.\u001b[39;00m\n\u001b[38;5;246;03m// Use 'break' after each case\u001b[39;00m\n\u001b[38;5;246;03m// or the cases after the correct one will be executed too.\u001b[39;00m\n\u001b[38;5;252mgrade\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'B'\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mswitch\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mgrade\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m  \u001b[39m\u001b[38;5;70;01mcase\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'A'\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mconsole\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlog\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"Great job\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mbreak\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m  \u001b[39m\u001b[38;5;70;01mcase\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'B'\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mconsole\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlog\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"OK job\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mbreak\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m  \u001b[39m\u001b[38;5;70;01mcase\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'C'\u001b[39m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mconsole\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlog\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"You can do better\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mbreak\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m  \u001b[39m\u001b[38;5;70;01mdefault\u001b[39;00m\u001b[38;5;252m:\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mconsole\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlog\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"Oy vey\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mbreak\u001b[39;00m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\n\n\u001b[38;5;246;03m///////////////////////////////////\u001b[39;00m\n\u001b[38;5;246;03m// 4. Functions, Scope and Closures\u001b[39;00m\n\n\u001b[38;5;246;03m// JavaScript functions are declared with the `function` keyword.\u001b[39;00m\n\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mthing\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mthing\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mtoUpperCase\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"foo\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"FOO\"\u001b[39;00m\n\n\u001b[38;5;246;03m// Note that the value to be returned must start on the same line as the\u001b[39;00m\n\u001b[38;5;246;03m// `return` keyword, otherwise you'll always return `undefined` due to\u001b[39;00m\n\u001b[38;5;246;03m// automatic semicolon insertion. Watch out for this when using Allman style.\u001b[39;00m\n\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// <- semicolon automatically inserted here\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252mthisIsAn\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m'object literal'\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = undefined\u001b[39;00m\n\n\u001b[38;5;246;03m// JavaScript functions are first class objects, so they can be reassigned to\u001b[39;00m\n\u001b[38;5;246;03m// different variable names and passed to other functions as arguments - for\u001b[39;00m\n\u001b[38;5;246;03m// example, when supplying an event handler:\u001b[39;00m\n\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// this code will be called in 5 seconds' time\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252msetTimeout\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5000\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;246;03m// Note: setTimeout isn't part of the JS language, but is provided by browsers\u001b[39;00m\n\u001b[38;5;246;03m// and Node.js.\u001b[39;00m\n\n\u001b[38;5;246;03m// Another function provided by browsers is setInterval\u001b[39;00m\n\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// this code will be called every 5 seconds\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252msetInterval\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyFunction\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5000\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Function objects don't even have to be declared with a name - you can write\u001b[39;00m\n\u001b[38;5;246;03m// an anonymous function definition directly into the arguments of another.\u001b[39;00m\n\u001b[38;5;252msetTimeout\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// this code will be called in 5 seconds' time\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5000\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// JavaScript has function scope; functions get their own scope but other blocks\u001b[39;00m\n\u001b[38;5;246;03m// do not.\u001b[39;00m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mtrue\u001b[39;00m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252mi\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 5 - not undefined as you'd expect in a block-scoped language\u001b[39;00m\n\n\u001b[38;5;246;03m// This has led to a common pattern of \"immediately-executing anonymous\u001b[39;00m\n\u001b[38;5;246;03m// functions\", which prevent temporary variables from leaking into the global\u001b[39;00m\n\u001b[38;5;246;03m// scope.\u001b[39;00m\n\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mtemporary\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// We can access the global scope by assigning to the \"global object\", which\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// in a web browser is always `window`. The global object may have a\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// different name in non-browser environments such as Node.js.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mwindow\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mpermanent\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m10\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mtemporary\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// raises ReferenceError\u001b[39;00m\n\u001b[38;5;252mpermanent\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 10\u001b[39;00m\n\n\u001b[38;5;246;03m// One of JavaScript's most powerful features is closures. If a function is\u001b[39;00m\n\u001b[38;5;246;03m// defined inside another function, the inner function has access to all the\u001b[39;00m\n\u001b[38;5;246;03m// outer function's variables, even after the outer function exits.\u001b[39;00m\n\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msayHelloInFiveSeconds\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mprompt\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Hello, \"\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"!\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// Inner functions are put in the local scope by default, as if they were\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// declared with `var`.\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252minner\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;252malert\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mprompt\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252msetTimeout\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252minner\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5000\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// setTimeout is asynchronous, so the sayHelloInFiveSeconds function will\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// exit immediately, and setTimeout will call inner afterwards. However,\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// because inner is \"closed over\" sayHelloInFiveSeconds, inner still has\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// access to the `prompt` variable when it is finally called.\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252msayHelloInFiveSeconds\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\"Adam\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// will open a popup with \"Hello, Adam!\" in 5s\u001b[39;00m\n\n\u001b[38;5;246;03m///////////////////////////////////\u001b[39;00m\n\u001b[38;5;246;03m// 5. More about Objects; Constructors and Prototypes\u001b[39;00m\n\n\u001b[38;5;246;03m// Objects can contain functions.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Hello world!\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello world!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// When functions attached to an object are called, they can access the object\u001b[39;00m\n\u001b[38;5;246;03m// they're attached to using the `this` keyword.\u001b[39;00m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyString\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Hello world!\"\u001b[39m\u001b[38;5;252m,\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyString\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello world!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// What this is set to has to do with how the function is called, not where\u001b[39;00m\n\u001b[38;5;246;03m// it's defined. So, our function doesn't work if it isn't called in the\u001b[39;00m\n\u001b[38;5;246;03m// context of the object.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = undefined\u001b[39;00m\n\n\u001b[38;5;246;03m// Inversely, a function can be assigned to the object and gain access to it\u001b[39;00m\n\u001b[38;5;246;03m// through `this`, even if it wasn't attached when it was defined.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyOtherFunc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyString\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mtoUpperCase\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyOtherFunc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyOtherFunc\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyOtherFunc\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"HELLO WORLD!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// We can also specify a context for a function to execute in when we invoke it\u001b[39;00m\n\u001b[38;5;246;03m// using `call` or `apply`.\u001b[39;00m\n\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252manotherFunc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252ms\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyString\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ms\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252manotherFunc\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcall\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\" And Hello Moon!\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello World! And Hello Moon!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// The `apply` function is nearly identical, but takes an array for an argument\u001b[39;00m\n\u001b[38;5;246;03m// list.\u001b[39;00m\n\n\u001b[38;5;252manotherFunc\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mapply\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;214m\" And Hello Sun!\"\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello World! And Hello Sun!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// This is useful when working with a function that accepts a sequence of\u001b[39;00m\n\u001b[38;5;246;03m// arguments and you want to pass an array.\u001b[39;00m\n\n\u001b[38;5;31mMath\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmin\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m42\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m27\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 6\u001b[39;00m\n\u001b[38;5;31mMath\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmin\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m42\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m27\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = NaN (uh-oh!)\u001b[39;00m\n\u001b[38;5;31mMath\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmin\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mapply\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mMath\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;67m42\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m27\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 6\u001b[39;00m\n\n\u001b[38;5;246;03m// But, `call` and `apply` are only temporary. When we want it to stick, we can\u001b[39;00m\n\u001b[38;5;246;03m// use `bind`.\u001b[39;00m\n\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mboundFunc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252manotherFunc\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mbind\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mboundFunc\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;214m\" And Hello Saturn!\"\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"Hello World! And Hello Saturn!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// `bind` can also be used to partially apply (curry) a function.\u001b[39;00m\n\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mproduct\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252ma\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252ma\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m*\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mb\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdoubler\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mproduct\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mbind\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mdoubler\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m8\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 16\u001b[39;00m\n\n\u001b[38;5;246;03m// When you call a function with the `new` keyword, a new object is created, and\u001b[39;00m\n\u001b[38;5;246;03m// made available to the function via the `this` keyword. Functions designed to be\u001b[39;00m\n\u001b[38;5;246;03m// called like that are called constructors.\u001b[39;00m\n\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyConstructor\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyNewObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mnew\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyConstructor\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = {myNumber: 5}\u001b[39;00m\n\u001b[38;5;252mmyNewObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 5\u001b[39;00m\n\n\u001b[38;5;246;03m// Unlike most other popular object-oriented languages, JavaScript has no\u001b[39;00m\n\u001b[38;5;246;03m// concept of 'instances' created from 'class' blueprints; instead, JavaScript\u001b[39;00m\n\u001b[38;5;246;03m// combines instantiation and inheritance into a single concept: a 'prototype'.\u001b[39;00m\n\n\u001b[38;5;246;03m// Every JavaScript object has a 'prototype'. When you go to access a property\u001b[39;00m\n\u001b[38;5;246;03m// on an object that doesn't exist on the actual object, the interpreter will\u001b[39;00m\n\u001b[38;5;246;03m// look at its prototype.\u001b[39;00m\n\n\u001b[38;5;246;03m// Some JS implementations let you access an object's prototype on the magic\u001b[39;00m\n\u001b[38;5;246;03m// property `__proto__`. While this is useful for explaining prototypes it's not\u001b[39;00m\n\u001b[38;5;246;03m// part of the standard; we'll get to standard ways of using prototypes later.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyString\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Hello world!\"\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyPrototype\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmeaningOfLife\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m42\u001b[39m\u001b[38;5;252m,\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyString\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mtoLowerCase\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252m__proto__\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyPrototype\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmeaningOfLife\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 42\u001b[39;00m\n\n\u001b[38;5;246;03m// This works for functions, too.\u001b[39;00m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyFunc\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"hello world!\"\u001b[39;00m\n\n\u001b[38;5;246;03m// Of course, if your property isn't on your prototype, the prototype's\u001b[39;00m\n\u001b[38;5;246;03m// prototype is searched, and so on.\u001b[39;00m\n\u001b[38;5;252mmyPrototype\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252m__proto__\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyBoolean\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mtrue\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyBoolean\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// There's no copying involved here; each object stores a reference to its\u001b[39;00m\n\u001b[38;5;246;03m// prototype. This means we can alter the prototype and our changes will be\u001b[39;00m\n\u001b[38;5;246;03m// reflected everywhere.\u001b[39;00m\n\u001b[38;5;252mmyPrototype\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmeaningOfLife\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m43\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmeaningOfLife\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 43\u001b[39;00m\n\n\u001b[38;5;246;03m// The for/in statement allows iteration over properties of an object,\u001b[39;00m\n\u001b[38;5;246;03m// walking up the prototype chain until it sees a null prototype.\u001b[39;00m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mconsole\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlog\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;246;03m///prints:\u001b[39;00m\n\u001b[38;5;246;03m// Hello world!\u001b[39;00m\n\u001b[38;5;246;03m// 43\u001b[39;00m\n\u001b[38;5;246;03m// [Function: myFunc]\u001b[39;00m\n\u001b[38;5;246;03m// true\u001b[39;00m\n\n\u001b[38;5;246;03m// To only consider properties attached to the object itself\u001b[39;00m\n\u001b[38;5;246;03m// and not its prototypes, use the `hasOwnProperty()` check.\u001b[39;00m\n\u001b[38;5;70;01mfor\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01min\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mhasOwnProperty\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;252mconsole\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mlog\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m[\u001b[39m\u001b[38;5;252mx\u001b[39m\u001b[38;5;252m]\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;246;03m///prints:\u001b[39;00m\n\u001b[38;5;246;03m// Hello world!\u001b[39;00m\n\n\u001b[38;5;246;03m// We mentioned that `__proto__` was non-standard, and there's no standard way to\u001b[39;00m\n\u001b[38;5;246;03m// change the prototype of an existing object. However, there are two ways to\u001b[39;00m\n\u001b[38;5;246;03m// create a new object with a given prototype.\u001b[39;00m\n\n\u001b[38;5;246;03m// The first is Object.create, which is a recent addition to JS, and therefore\u001b[39;00m\n\u001b[38;5;246;03m// not available in all implementations yet.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mObject\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mmyPrototype\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyObj\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmeaningOfLife\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 43\u001b[39;00m\n\n\u001b[38;5;246;03m// The second way, which works anywhere, has to do with constructors.\u001b[39;00m\n\u001b[38;5;246;03m// Constructors have a property called prototype. This is *not* the prototype of\u001b[39;00m\n\u001b[38;5;246;03m// the constructor function itself; instead, it's the prototype that new objects\u001b[39;00m\n\u001b[38;5;246;03m// are given when they're created with that constructor and the new keyword.\u001b[39;00m\n\u001b[38;5;252mMyConstructor\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mprototype\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m5\u001b[39m\u001b[38;5;252m,\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252mgetMyNumber\u001b[39m\u001b[38;5;252m:\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNewObj2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mnew\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mMyConstructor\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyNewObj2\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mgetMyNumber\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 5\u001b[39;00m\n\u001b[38;5;252mmyNewObj2\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m6\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyNewObj2\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mgetMyNumber\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 6\u001b[39;00m\n\n\u001b[38;5;246;03m// Built-in types like strings and numbers also have constructors that create\u001b[39;00m\n\u001b[38;5;246;03m// equivalent wrapper objects.\u001b[39;00m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m12\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNumberObj\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mnew\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mNumber\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m12\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m==\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNumberObj\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = true\u001b[39;00m\n\n\u001b[38;5;246;03m// Except, they aren't exactly equivalent.\u001b[39;00m\n\u001b[38;5;70;01mtypeof\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 'number'\u001b[39;00m\n\u001b[38;5;70;01mtypeof\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNumberObj\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = 'object'\u001b[39;00m\n\u001b[38;5;252mmyNumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmyNumberObj\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = false\u001b[39;00m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;246;03m// This code won't execute, because 0 is falsy.\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;70;01mnew\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;31mNumber\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m// This code will execute, because wrapped numbers are objects, and objects\u001b[39;00m\n\u001b[38;5;252m   \u001b[39m\u001b[38;5;246;03m// are always truthy.\u001b[39;00m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// However, the wrapper objects and the regular builtins share a prototype, so\u001b[39;00m\n\u001b[38;5;246;03m// you can actually add functionality to a string, for instance.\u001b[39;00m\n\u001b[38;5;31mString\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mprototype\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mfirstCharacter\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mthis\u001b[39;00m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcharAt\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;214m\"abc\"\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mfirstCharacter\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// = \"a\"\u001b[39;00m\n\n\u001b[38;5;246;03m// This fact is often used in \"polyfilling\", which is implementing newer\u001b[39;00m\n\u001b[38;5;246;03m// features of JavaScript in an older subset of JavaScript, so that they can be\u001b[39;00m\n\u001b[38;5;246;03m// used in older environments such as outdated browsers.\u001b[39;00m\n\n\u001b[38;5;246;03m// For instance, we mentioned that Object.create isn't yet available in all\u001b[39;00m\n\u001b[38;5;246;03m// implementations, but we can still use it with this polyfill:\u001b[39;00m\n\u001b[38;5;70;01mif\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;31mObject\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mundefined\u001b[39;00m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// don't overwrite it if it exists\u001b[39;00m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;31mObject\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mproto\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m// make a temporary constructor with the right prototype\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mvar\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mConstructor\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m{\u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;252mConstructor\u001b[39m\u001b[38;5;252m.\u001b[39m\u001b[38;5;252mprototype\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mproto\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;246;03m// then use it to create a new, appropriately-prototyped object\u001b[39;00m\n\u001b[38;5;252m        \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mnew\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mConstructor\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\n\n\u001b[38;5;246;03m// ES6 Additions\u001b[39;00m\n\n\u001b[38;5;246;03m// The \"let\" keyword allows you to define variables in a lexical scope, \u001b[39;00m\n\u001b[38;5;246;03m// as opposed to a block scope like the var keyword does.\u001b[39;00m\n\u001b[38;5;70;01mlet\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"Billy\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// Variables defined with let can be reassigned new values.\u001b[39;00m\n\u001b[38;5;252mname\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;214m\"William\"\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// The \"const\" keyword allows you to define a variable in a lexical scope\u001b[39;00m\n\u001b[38;5;246;03m// like with let, but you cannot reassign the value once one has been assigned.\u001b[39;00m\n\n\u001b[38;5;70;01mconst\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m3.14\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;252mpi\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m4.13\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// You cannot do this.\u001b[39;00m\n\n\u001b[38;5;246;03m// There is a new syntax for functions in ES6 known as \"lambda syntax\".\u001b[39;00m\n\u001b[38;5;246;03m// This allows functions to be defined in a lexical scope like with variables\u001b[39;00m\n\u001b[38;5;246;03m// defined by const and let. \u001b[39;00m\n\n\u001b[38;5;70;01mconst\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252misEven\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mnumber\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mnumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m%\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;252misEven\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m7\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;246;03m// false\u001b[39;00m\n\n\u001b[38;5;246;03m// The \"equivalent\" of this function in the traditional syntax would look like this:\u001b[39;00m\n\n\u001b[38;5;70;01mfunction\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252misEven\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mnumber\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mnumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m%\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m2\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m===\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m0\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;246;03m// I put the word \"equivalent\" in double quotes because a function defined\u001b[39;00m\n\u001b[38;5;246;03m// using the lambda syntax cannnot be called before the definition.\u001b[39;00m\n\u001b[38;5;246;03m// The following is an example of invalid usage:\u001b[39;00m\n\n\u001b[38;5;252madd\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;67m1\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;67m8\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m;\u001b[39m\n\n\u001b[38;5;70;01mconst\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252madd\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252mfirstNumber\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msecondNumber\u001b[39m\u001b[38;5;252m)\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m=>\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m{\u001b[39m\n\u001b[38;5;252m    \u001b[39m\u001b[38;5;70;01mreturn\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfirstNumber\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m+\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msecondNumber\u001b[39m\u001b[38;5;252m;\u001b[39m\n\u001b[38;5;252m}\u001b[39m\u001b[38;5;252m;\u001b[39m\n"
  },
  {
    "path": "tests/results/23",
    "content": ":learn\n:list\nArrays\nAxioms\nChannels\nDeclarations\nEmbedding\nErrors\nInterfaces\nMaps\nOperators\nPointers\nStructs\nfor\nfunc\ngo\nhello\nhttp\nif\npackages\nprint\nrange\nrosetta/\nslices\nswitch\ntypes\n"
  },
  {
    "path": "tests/results/24",
    "content": "Unknown topic.\nDo you mean one of these topics maybe?\n\n    * mkfs.fat 84\n    * mkfs.vfat 80\n    * mkfs.exfat 76\n    \n"
  },
  {
    "path": "tests/results/25",
    "content": "\u001b[38;5;242m# Latency numbers every programmer should know \u001b[m\n\n1ns                          Main memory reference:       Send 2,000 bytes             Read 1,000,000 bytes         \n\u001b[37m▗▖                           \u001b[m100ns                        over commodity network:      sequentially from SSD: 61us  \n                             \u001b[34m▗▖                           \u001b[m62ns                         \u001b[31m▗                            \u001b[m\nL1 cache reference: 1ns                                   \u001b[32m▗                            \u001b[m                             \n\u001b[37m▗▖                           \u001b[m1us                                                       Disk seek: 2ms               \n                             \u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[mSSD random read: 16us        \u001b[31m▗▖▗▖▗                        \u001b[m\nBranch mispredict: 3ns       \u001b[34m                             \u001b[m\u001b[32m▗▖                           \u001b[m                             \n\u001b[37m▗▖▗▖▗▖                       \u001b[m                                                          Read 1,000,000 bytes         \n                             Compress 1KB with Snappy:     Read 1,000,000 bytes         sequentially from disk:      \nL2 cache reference: 4ns      2us                          sequentially from memory:    947us                        \n\u001b[37m▗▖▗▖▗▖▗▖                     \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m3us                          \u001b[31m▗                            \u001b[m\n                             \u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗                            \u001b[m                             \nMutex lock/unlock: 16ns      \u001b[34m                             \u001b[m                             Packet roundtrip             \n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m                             Round trip                   CA to Netherlands: 150ms     \n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗                \u001b[m10us = \u001b[32m▗▖\u001b[m                    in same datacenter: 500us    \u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n                             \u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n100ns = \u001b[34m▗▖\u001b[m                   \u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m                             \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m                             \u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m1ms = \u001b[31m▗▖\u001b[m                     \u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[34m                             \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m                             \u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[37m                             \u001b[m                             \u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n                                                          \u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\n\u001b[38;5;242m# [github.com/chubin/late.nz] [MIT License]               \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m\u001b[31m                             \u001b[m\n\u001b[38;5;242m# Console port of \"Jeff Dean's latency numbers\"           \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m                             \n\u001b[38;5;242m# from [github.com/colin-scott/interactive_latencies]     \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m                             \n\u001b[38;5;242m                                                          \u001b[m\u001b[32m▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖▗▖         \u001b[m                             \n"
  },
  {
    "path": "tests/results/3",
    "content": "#[cheat:ls]\n# To display everything in <dir>, excluding hidden files:\nls <dir>\n\n# To display everything in <dir>, including hidden files:\nls -a <dir>\n\n# To display all files, along with the size (with unit suffixes) and timestamp\nls -lh <dir>\n\n# To display files, sorted by size:\nls -S <dir>\n\n# To display directories only:\nls -d */ <dir>\n\n# To display directories only, include hidden:\nls -d .*/ */ <dir>\n#[tldr:ls]\n# ls\n# List directory contents.\n# More information: <https://www.gnu.org/software/coreutils/ls>.\n\n# List files one per line:\nls -1\n\n# List all files, including hidden files:\nls -a\n\n# List all files, with trailing `/` added to directory names:\nls -F\n\n# Long format list (permissions, ownership, size, and modification date) of all files:\nls -la\n\n# Long format list with size displayed using human-readable units (KiB, MiB, GiB):\nls -lh\n\n# Long format list sorted by size (descending):\nls -lS\n\n# Long format list of all files, sorted by modification date (oldest first):\nls -ltr\n\n# Only list directories:\nls -d */\n"
  },
  {
    "path": "tests/results/4",
    "content": "\u001b[48;5;8m\u001b[24m cheat.sheets:btrfs \u001b[24m\u001b[0m\n\u001b[38;5;246;03m# Create a btrfs file system on /dev/sdb, /dev/sdc, and /dev/sdd\u001b[39;00m\n\u001b[38;5;252mmkfs.btrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdd\u001b[39m\n\n\u001b[38;5;246;03m# btrfs with just one hard drive, metadata not redundant\u001b[39;00m\n\u001b[38;5;246;03m# (this is dangerous: if your metadata is lost, your data is lost as well)\u001b[39;00m\n\u001b[38;5;252mmkfs.btrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-m\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msingle\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdb\u001b[39m\n\n\u001b[38;5;246;03m# data to be redundant and metadata to be non-redundant:\u001b[39;00m\n\u001b[38;5;252mmkfs.btrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-m\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mraid0\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-d\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mraid1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdd\u001b[39m\n\n\u001b[38;5;246;03m# both data and metadata to be redundant\u001b[39;00m\n\u001b[38;5;252mmkfs.btrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-d\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mraid1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdc\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdd\u001b[39m\n\n\u001b[38;5;246;03m# To get a list of all btrfs file systems\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfilesystem\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mshow\u001b[39m\n\n\u001b[38;5;246;03m# detailed df for a filesystem (mounted in /mnt)\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfilesystem\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdf\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt\u001b[39m\n\n\u001b[38;5;246;03m# resize btrfs online (-2g decreases, +2g increases)\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfilesystem\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mresize\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-2g\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt\u001b[39m\n\n\u001b[38;5;246;03m# use maximum space\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfilesystem\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mresize\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmax\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt\u001b[39m\n\n\u001b[38;5;246;03m# add new device to a filesystem\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdevice\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252madd\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdf\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt\u001b[39m\n\n\u001b[38;5;246;03m# remove devices from a filesystem\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdevice\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdelete\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mmissing\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt\u001b[39m\n\n\u001b[38;5;246;03m# create the subvolume /mnt/sv1 in the /mnt volume\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt/sv1\u001b[39m\n\n\u001b[38;5;246;03m# list subvolumes\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt\u001b[39m\n\n\u001b[38;5;246;03m# mount subvolume without mounting the main filesystem\u001b[39;00m\n\u001b[38;5;252mmount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-o\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;87msubvol\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252msv1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt\u001b[39m\n\n\u001b[38;5;246;03m# delete subvolume\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdelete\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt/sv1\u001b[39m\n\n\u001b[38;5;246;03m# taking snapshot of a subvolume\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msnapshot\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt/sv1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt/sv1_snapshot\u001b[39m\n\n\u001b[38;5;246;03m# taking snapshot of a file (copy file by reference)\u001b[39;00m\n\u001b[38;5;252mcp\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m--reflink\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt/sv1/test1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt/sv1/test3\u001b[39m\n\n\u001b[38;5;246;03m# convert ext3/ext4 to btrfs\u001b[39;00m\n\u001b[38;5;252mbtrfs-convert\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdb1\u001b[39m\n\n\u001b[38;5;246;03m# convert btrfs to ext3/ext4\u001b[39;00m\n\u001b[38;5;252mbtrfs-convert\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-r\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdb1\u001b[39m\n\n\u001b[48;5;8m\u001b[24m tldr:btrfs \u001b[24m\u001b[0m\n\u001b[38;5;246;03m# btrfs\u001b[39;00m\n\u001b[38;5;246;03m# A filesystem based on the copy-on-write (COW) principle for Linux.\u001b[39;00m\n\u001b[38;5;246;03m# Some subcommands such as `btrfs device` have their own usage documentation.\u001b[39;00m\n\u001b[38;5;246;03m# More information: <https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs>.\u001b[39;00m\n\n\u001b[38;5;246;03m# Create subvolume:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/subvolume\u001b[39m\n\n\u001b[38;5;246;03m# List subvolumes:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/mount_point\u001b[39m\n\n\u001b[38;5;246;03m# Show space usage information:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfilesystem\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdf\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/mount_point\u001b[39m\n\n\u001b[38;5;246;03m# Enable quota:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mquota\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;31menable\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/subvolume\u001b[39m\n\n\u001b[38;5;246;03m# Show quota:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mqgroup\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mshow\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/subvolume\u001b[39m\n"
  },
  {
    "path": "tests/results/5",
    "content": "\u001b[48;5;8m\u001b[24m cheat.sheets:btrfs \u001b[24m\u001b[0m\n\u001b[38;5;246;03m# create the subvolume /mnt/sv1 in the /mnt volume\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt/sv1\u001b[39m\n\n\u001b[38;5;246;03m# list subvolumes\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt\u001b[39m\n\n\u001b[38;5;246;03m# mount subvolume without mounting the main filesystem\u001b[39;00m\n\u001b[38;5;252mmount\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-o\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;87msubvol\u001b[39m\u001b[38;5;252m=\u001b[39m\u001b[38;5;252msv1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/dev/sdb\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt\u001b[39m\n\n\u001b[38;5;246;03m# delete subvolume\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdelete\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt/sv1\u001b[39m\n\n\u001b[38;5;246;03m# taking snapshot of a subvolume\u001b[39;00m\n\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msnapshot\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt/sv1\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m/mnt/sv1_snapshot\u001b[39m\n\n\u001b[48;5;8m\u001b[24m tldr:btrfs \u001b[24m\u001b[0m\n\u001b[38;5;246;03m# Create subvolume:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/subvolume\u001b[39m\n\n\u001b[38;5;246;03m# List subvolumes:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/mount_point\u001b[39m\n\n\u001b[38;5;246;03m# Enable quota:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mquota\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;31menable\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/subvolume\u001b[39m\n\n\u001b[38;5;246;03m# Show quota:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mqgroup\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mshow\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/subvolume\u001b[39m\n\n\u001b[48;5;8m\u001b[24m tldr:btrfs-filesystem \u001b[24m\u001b[0m\n\u001b[38;5;246;03m# Defragment a directory recursively (does not cross subvolume boundaries):\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mfilesystem\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdefragment\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-v\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-r\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/directory\u001b[39m\n\n\u001b[48;5;8m\u001b[24m tldr:btrfs-subvolume \u001b[24m\u001b[0m\n\u001b[38;5;246;03m# btrfs subvolume\u001b[39;00m\n\u001b[38;5;246;03m# Manage btrfs subvolumes and snapshots.\u001b[39;00m\n\u001b[38;5;246;03m# More information: <https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs-subvolume>.\u001b[39;00m\n\n\u001b[38;5;246;03m# Create a new empty subvolume:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcreate\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/new_subvolume\u001b[39m\n\n\u001b[38;5;246;03m# List all subvolumes and snapshots in the specified filesystem:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mlist\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/btrfs_filesystem\u001b[39m\n\n\u001b[38;5;246;03m# Delete a subvolume:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdelete\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/subvolume\u001b[39m\n\n\u001b[38;5;246;03m# Create a read-only snapshot of an existing subvolume:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msnapshot\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252m-r\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/source_subvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/target\u001b[39m\n\n\u001b[38;5;246;03m# Create a read-write snapshot of an existing subvolume:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msnapshot\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/source_subvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/target\u001b[39m\n\n\u001b[38;5;246;03m# Show detailed information about a subvolume:\u001b[39;00m\n\u001b[38;5;252msudo\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mbtrfs\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252msubvolume\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mshow\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mpath/to/subvolume\u001b[39m\n"
  },
  {
    "path": "tests/results/6",
    "content": "\u001b[38;5;172m## curl cht.sh\u001b[0m\n\nTo access a cheat sheet you can simply issue a plain HTTP or HTTPS request\nspecifying the topic name in the query URL:\n\n    \u001b[36mcurl cheat.sh\u001b[0m\u001b[32m/tar\u001b[0m\n    \u001b[36mcurl https://cheat.sh\u001b[0m\u001b[32m/tar\u001b[0m\n\nYou can use the full service name, \u001b[32mcheat.sh\u001b[0m, or the shorter variant, \u001b[32mcht.sh\u001b[0m.\nThey are equivalent:\n\n    \u001b[36mcurl https://\u001b[0m\u001b[32mcht.sh\u001b[0m\u001b[36m/tar\u001b[0m\n    \u001b[36mcurl https://\u001b[0m\u001b[32mcheat.sh\u001b[0m\u001b[36m/tar\u001b[0m\n\nThe preferred access protocol is HTTPS, and you should use it always when possible.\n\nCheat sheets in the root namespaces cover UNIX/Linux commands.\n\nCheat sheets covering programming languages are located in subsections:\n\n    \u001b[36mcurl cht.sh/\u001b[0m\u001b[32mgo/func\u001b[0m\n\nAll cheat sheets in a subsection can be listed using a special query \u001b[32m:list\u001b[0m :\n\n    \u001b[36mcurl cht.sh/go/\u001b[0m\u001b[32m:list\u001b[0m\n\nThere are several other special queries. All of them are starting with a \u001b[32mcolon\u001b[0m.\nSee \u001b[32m/:help\u001b[0m for the full list of the special queries.\n\n\n\u001b[38;5;172m## Search\u001b[0m\n\nIf a cheat sheet is too large, you can cut the needed part out using an\nadditional search parameter. In this case, only the paragraph that contains the\nsearch term will be displayed:\n\n    \u001b[36mcurl cht.sh/tar\u001b[0m\u001b[32m~extract\u001b[0m\n\nIf the name of the cheat sheet is omitted, and only the serch query is specified,\nall cheat sheets in the namespace are scanned, and the found occurrencies\nare displayed:\n\n    \u001b[36mcurl cht.sh/\u001b[0m\u001b[32m~extract\u001b[0m\n\n\n\u001b[38;5;172m## Options\u001b[0m\n\ncheat.sh queries as well as search queries have many options.\nThey can be specified as a part of the query string in the URL, after \u001b[32m?\u001b[0m.\nShort single letter options could be written all jointly together,\nand long options are separated with \u001b[32m&\u001b[0m. For example, to switch \nsyntax highlighting off the \u001b[32mT\u001b[0m switch is used:\n\n    \u001b[36mcurl cht.sh/tar\u001b[0m\u001b[32m?T\u001b[0m\n\nFull list of all available cheat.sh options as well as description of all modes\nof operation can be found in \u001b[32m/:help\u001b[0m,\n\n    \u001b[36mcurl cht.sh\u001b[0m\u001b[32m/:help\u001b[0m\n\n\n\u001b[38;5;172m## cht.sh client\u001b[0m\n\nThough it's perfectly possible to access cheat.sh using \u001b[36mcurl\u001b[0m (or any other\nHTTP client) alone, there is a special client, that has several advantages\ncomparing to plain curling: \u001b[32mcht.sh\u001b[0m.\n\nTo install the client in \u001b[32m~/bin\u001b[0m:\n\n    \u001b[36mcurl\u001b[0m \u001b[32mhttps://cht.sh/:cht.sh\u001b[0m \u001b[36m> ~/bin/cht.sh\u001b[0m\n    \u001b[36mchmod +x ~/bin/cht.sh\u001b[0m\n\nQueries look the same, but you can separate words in the query with \u001b[36mspaces\u001b[0m,\ninstead of \u001b[36m+\u001b[0m as when using curl, what looks more natural:\n\n    \u001b[36mcht.sh\u001b[0m \u001b[32mpython zip lists\u001b[0m\n\n\n\u001b[38;5;172m## cht.sh shell\u001b[0m\n\nIf you always issuing queries about the same programming language, it's can be\nmore convenient to run the client in the shell mode and specify the queries\ncontext:\n\n    \u001b[36m$\u001b[0m \u001b[32mcht.sh --shell python\u001b[0m\n    \u001b[36mcht.sh/python> zip lists\u001b[0m\n\nOf course, you can start the shell without the context too:\n\n    \u001b[36m$\u001b[0m \u001b[32mcht.sh --shell\u001b[0m\n    \u001b[36mcht.sh> python zip lists\u001b[0m\n    \u001b[36mcht.sh> go http query\u001b[0m\n    \u001b[36mcht.sh> js iterate list\u001b[0m\n\nIf you use predominantly one language but sometime issuing queries about other,\nyou may prepend the query with \u001b[32m/\u001b[0m:\n\n    \u001b[36mcht.sh/python>\u001b[0m \u001b[32mzip lists\u001b[0m\n    \u001b[36mcht.sh/python>\u001b[0m \u001b[32m/go http query\u001b[0m\n    \u001b[36mcht.sh/python>\u001b[0m \u001b[32m/js iterate list\u001b[0m\n\n\n\u001b[38;5;172m## :learn\u001b[0m\n\nIf you are just start learning a new programming language, and you have no\ndistinct queries for the moment, cheat.sh can be a good starting point too. As\nyou know, it exports cheat sheets from the best cheat sheet repositories, and\none of them is \u001b[36mLearn X in Y\u001b[0m, a repository of concise documentation devoted\nto learning programming languages from scratch (and not only them).\n\nIf you want start learning a new programming language, do (use less -R because\nthe output could be quite big): \n\n    \u001b[36mcurl cht.sh/elixir/\u001b[0m\u001b[32m:learn\u001b[0m \u001b[36m| less -R\u001b[0m\n\nOr simply \u001b[32m:learn\u001b[0m with cht.sh (you don't need \u001b[32mless -R\u001b[0m here, because\n\u001b[36mcht.sh\u001b[0m starts pager if needed automatically):\n\n    \u001b[2mcht.sh/elixir>\u001b[0m \u001b[32m:learn\u001b[0m\n\n\n\u001b[38;5;172m## Programming languages questions\u001b[0m\n\nOne of the most important features of cheat.sh is that you can ask it any\nquestions about programming languages and instantly get answers on them. You\ncan use both direct HTTP queries or the cht.sh client for that:\n\n    \u001b[36mcurl cht.sh/\u001b[0m\u001b[32mpython/reverse+list\u001b[0m\n    \n    \u001b[2mcht.sh/python>\u001b[0m \u001b[32mreverse list\u001b[0m\n\nIn the latter case you don't need + to separate the words in the query, you can\ndo it in a more natural way, with spaces.\n\nIf context in the cht.sh shell is not specified, you have to write the\nprogramming language name as the first word in the query:\n\n    \u001b[2mcht.sh>\u001b[0m \u001b[32mpython reverse list\u001b[0m\n\nBut if you are using only one programming language and all queries are about\nit, it's better to change the current context and \n\n\n\u001b[38;5;172m## Comments\u001b[0m\n\nText in the answers is syntactically formatted as comment in the correspondent\nprogramming language\n\nWhen using cht.sh, you can copy the result of the last query into the selection\nbuffer (you may also call it \"clibpoard\") using \u001b[32mC\u001b[0m (or \u001b[32mc\u001b[0m, with text):\n\n    \u001b[36mcht.sh/python> reverse list\u001b[0m\n    \u001b[2m...\u001b[0m\n    \u001b[36mcht.sh/python>\u001b[0m \u001b[32mC\u001b[0m\n    \u001b[2m1 lines copied\u001b[0m\n\n\n\u001b[38;5;172m## bash TAB-completion for cht.sh\u001b[0m\n\nOne of the advantages of the \u001b[36mcht.sh\u001b[0m client comparing to plain curl is that you\ncan use TAB completion when writing its queries in \u001b[36mbash\u001b[0m\n(other supported shells: \u001b[36mzsh\u001b[0m and \u001b[36mfish\u001b[0m).\n\nInstall the TAB completion script for that. Assuming you use bash, you have to do:\n\n    \u001b[36mmkdir -p ~/.bash.d/\u001b[0m\n    \u001b[36mcurl\u001b[0m \u001b[32mhttps://cht.sh/:bash_completion\u001b[0m \u001b[36m> ~/.bash.d/cht.sh\u001b[0m\n    \u001b[36mecho 'source ~/.bash.d/cht.sh' >> ~/.bashrc\u001b[0m\n    \u001b[36msource ~/.bash.d/cht.sh\u001b[0m\n\n\n\u001b[38;5;172m## Editor\u001b[0m\n\nYou can access cheat.sh directly from editors: \u001b[36mVim\u001b[0m and \u001b[36mEmacs\u001b[0m.\nIt's a very important feature! You should absolutely like it.\n\n\u001b[36mImagine:\u001b[0m\ninstead of switching to your browser, googling, browsing Stack Overflow\nand eventually copying the code snippets you need and later pasting them into\nthe editor, you can achieve the same instantly and without leaving\nthe editor at all!\n\nHere is how it looks like:\n\n1. In Vim, if you have a question while editing a program, you can just type\nyour question \u001b[36mdirectly in the buffer\u001b[0m and press \u001b[32m<leader>KK\u001b[0m. You will get\nthe answer to your question in \u001b[36mpager\u001b[0m. (with \u001b[32m<leader>KB\u001b[0m you'll get the answer\nin a separate \u001b[36mbuffer\u001b[0m).\n\n2. If you like the answer. You can manually paste it from the buffer or\nthe pager, or if you are lazy you can use \u001b[32m<leader>KP\u001b[0m to paste it under\nyour question (\u001b[32m<leader>KR\u001b[0m will replace your question). If you want the\nanswer without the comments, \u001b[32m<leader>KC\u001b[0m replays the last query\ntoggling them.\n\nYou have to install cheat.sh \u001b[36mVim/Emacs plugins\u001b[0m for the editor support.\nSee \u001b[32m/:vim\u001b[0m or \u001b[32m/:emacs\u001b[0m with the detailed installation instructions.\n\n\n\u001b[38;5;172m## Feature requests, feedback and contribution\u001b[0m\n\nIf you want to submit a new community driver repository for cheat.sh please\nopen a ticket on the project page on GitHub.\n\nIf you want to modify an existing cheat sheet, please check the source of the\ncheat sheet (it is always displayed in the cheat sheet bottom line).\n\nIf you want to add a new cheat sheet, add it here:\n\u001b[36mhttps://github.com/chubin/cheat.sheets\u001b[0m\n\nIf you want to suggest a new feature for cheat.sh, or if you've found a bug,\nplease open a new issue on github:\n\u001b[36mhttps://github.com/chubin/cheat.sh\u001b[0m\n\nIf you want to get the major project updates, follow @igor_chubin in Twitter\nor this RSS feed: \u001b[36mhttps://twitrss.me/twitter_user_to_rss/?user=igor_chubin\u001b[0m\n"
  },
  {
    "path": "tests/results/7",
    "content": "Usage:\n\n    $ curl cheat.sh/TOPIC       show cheat sheet on the TOPIC\n    $ curl cheat.sh/TOPIC/SUB   show cheat sheet on the SUB topic in TOPIC\n    $ curl cheat.sh/~KEYWORD    search cheat sheets for KEYWORD\n\nOptions:\n\n    ?OPTIONS\n\n    q                  quiet mode, don't show github/twitter buttons\n    T                  text only, no ANSI sequences\n    style=STYLE        color style\n\n    c                  do not comment text, do not shift code (QUERY+ only)\n    C                  do not comment text, shift code (QUERY+ only)\n    Q                  code only, don't show text (QUERY+ only)\n\nOptions can be combined together in this way:\n\n    curl 'cheat.sh/for?qT&style=bw'\n\n(when using & in shell, don't forget to specify the quotes or escape & with \\)\n\nSpecial pages:\n\n    :help               this page\n    :list               list all cheat sheets\n    :post               how to post new cheat sheet\n    :cht.sh             shell client (cht.sh)\n    :bash_completion    bash function for tab completion\n    :styles             list of color styles\n    :styles-demo        show color styles usage examples\n    :random             fetches a random cheat sheet\n\nShell client:\n\n    $ curl https://cht.sh/:cht.sh > ~/bin/cht.sh\n    $ chmod +x ~/bin/cht.sh\n    $ cht.sh python :learn\n    $ cht.sh --shell\n\nTab completion:\n\n    $ mkdir -p ~/.bash.d/\n    $ curl cheat.sh/:bash_completion > ~/.bash.d/cht.sh\n    $ . ~/.bash.d/cht.sh\n    $ echo '. ~/.bash.d/cht.sh' >> ~/.bashrc\n\nEditor integration:\n\n    :emacs              see the page for the Emacs configuration\n    :vim                see the page for the Vim configuration\n\nSearch:\n\n    /~snapshot          look for \"snapshot\" in the first level cheat sheets\n    /~ssh~passphrase    several keywords can be combined together using ~\n    /scala/~closure     look for \"closure\" in scala cheat sheets\n    /~snapshot/r        look for \"snapshot\" in all cheat sheets recursively\n\nYou can use special search options after the closing slash:\n\n    /~shot/bi           case insensitive (i), word boundaries (b)\n\nList of search options:\n\n    b   word boundaries\n    i   case insensitive search\n    r   recursive\n\nProgramming languages topics:\n\nEach programming language topic has the following subtopics:\n\n    hello               hello world + how to start the program\n    :learn              big cheat sheet for learning language from scratch\n    :list               list of topics\n    :random             fetches a random cheat sheet belonging to the topic\n"
  },
  {
    "path": "tests/results/8",
    "content": "#!/bin/bash\n# shellcheck disable=SC1117,SC2001\n#\n# [X] open section\n# [X] one shot mode\n# [X] usage info\n# [X] dependencies check\n# [X] help\n# [X] yank/y/copy/c\n# [X] Y/C\n# [X] eof problem\n# [X] more\n# [X] stealth mode\n#\n# here are several examples for the stealth mode:\n#\n# zip lists\n# list permutation\n# random list element\n# reverse a list\n# read json from file\n# append string to a file\n# run process in background\n# count words in text counter\n# group elements list\n\n__CHTSH_VERSION=0.0.4\n__CHTSH_DATETIME=\"2021-04-25 12:30:30 +0200\"\n\n# cht.sh configuration loading\n#\n# configuration is stored in ~/.cht.sh/ (can be overridden with CHTSH env var.)\n#\nCHTSH_HOME=${CHTSH:-\"$HOME\"/.cht.sh}\n[ -z \"$CHTSH_CONF\" ] && CHTSH_CONF=$CHTSH_HOME/cht.sh.conf\n# shellcheck disable=SC1090,SC2002\n[ -e \"$CHTSH_CONF\" ] && source \"$CHTSH_CONF\"\n[ -z \"$CHTSH_URL\" ] && CHTSH_URL=https://cht.sh\n\n# currently we support only two modes:\n# * lite = access the server using curl\n# * auto = try standalone usage first\nCHTSH_MODE=\"$(cat \"$CHTSH_HOME\"/mode 2> /dev/null)\"\n[ \"$CHTSH_MODE\" != lite ] && CHTSH_MODE=auto\nCHEATSH_INSTALLATION=\"$(cat \"$CHTSH_HOME/standalone\" 2> /dev/null)\"\n\n\nexport LESSSECURE=1\nSTEALTH_MAX_SELECTION_LENGTH=5\n\ncase \"$(uname -s)\" in\n  Darwin) is_macos=yes ;;\n  *) is_macos=no ;;\nesac\n\n# for KSH93\n# shellcheck disable=SC2034,SC2039,SC2168\nif echo \"$KSH_VERSION\" | grep -q ' 93' && ! local foo 2>/dev/null; then\n  alias local=typeset\nfi\n\nfatal()\n{\n  echo \"ERROR: $*\" >&2\n  exit 1\n}\n\n_say_what_i_do()\n{\n  [ -n \"$LOG\" ] && echo \"$(date '+[%Y-%m-%d %H:%M%S]') $*\" >> \"$LOG\"\n\n  local this_prompt=\"\\033[0;1;4;32m>>\\033[0m\"\n  printf \"\\n${this_prompt}%s\\033[0m\\n\" \" $* \"\n}\n\ncheatsh_standalone_install()\n{\n  # the function installs cheat.sh with the upstream repositories\n  # in the standalone mode\n  local installdir; installdir=\"$1\"\n  local default_installdir=\"$HOME/.cheat.sh\"\n\n  [ -z \"$installdir\" ] && installdir=${default_installdir}\n\n  if [ \"$installdir\" = help ]; then\n    cat <<EOF\nInstall cheat.sh in the standalone mode.\n\nAfter the installation, cheat.sh can be used locally, without accessing\nthe public cheat.sh service, or it can be used in the server mode,\nwhere the newly installed server could be accessed by external clients\nin the same fashion as the public cheat.sh server.\n\nDuring the installation, cheat.sh code as well as the cheat.sh upstream\ncheat sheets repositories will be fetched.\n\nIt takes approximately 1G of the disk space.\n\nDefault installation location:  ~/.cheat.sh/\nIt can be overridden by a command line parameter to this script:\n\n    ${0##*/} --standalone-install DIR\n\nSee cheat.sh/:standalone or https://github.com/chubin/cheat.sh/README.md\nfor more information:\n\n    cht.sh :standalone\n    curl cheat.sh/:standalone\n\nAfter the installation is finished, the cht.sh shell client is switched\nto the auto mode, where it uses the local cheat.sh installation if possible.\nYou can switch the mode with the --mode switch:\n\n    cht.sh --mode lite      # use https://cheat.sh/ only\n    cht.sh --mode auto      # use local installation\n\nFor intallation and standalone usage, you need \\`git\\`, \\`python\\`,\nand \\`virtualenv\\` to be installed locally.\nEOF\n    return\n  fi\n\n  local _exit_code=0\n\n  local dependencies=(python git virtualenv)\n  for dep in \"${dependencies[@]}\"; do\n    command -v \"$dep\" >/dev/null || \\\n    { echo \"DEPENDENCY: \\\"$dep\\\" is needed to install cheat.sh in the standalone mode\" >&2; _exit_code=1; }\n  done\n  [ \"$_exit_code\" -ne 0 ] && return \"$_exit_code\"\n\n  while true; do\n    local _installdir\n    echo -n \"Where should cheat.sh be installed [$installdir]? \"; read -r _installdir\n    [ -n \"$_installdir\" ] && installdir=$_installdir\n\n    if [ \"$installdir\" = y ] \\\n        || [ \"$installdir\" = Y ] \\\n        || [ \"$(echo \"$installdir\" | tr \"[:upper:]\" \"[:lower:]\")\" = yes ]\n    then\n      echo Please enter the directory name\n      echo If it was the directory name already, please prepend it with \\\"./\\\": \"./$installdir\"\n    else\n      break\n    fi\n  done\n\n  if [ -e \"$installdir\" ]; then\n    echo \"ERROR: Installation directory [$installdir] exists already\"\n    echo \"Please remove it first before continuing\"\n    return 1\n  fi\n\n  if ! mkdir -p \"$installdir\"; then\n    echo \"ERROR: Could not create the installation directory \\\"$installdir\\\"\"\n    echo \"ERROR: Please check the permissions and start the script again\"\n    return 1\n  fi\n\n  local space_needed=700\n  local space_available; space_available=$(($(df -k \"$installdir\" | awk '{print $4}' | tail -1)/1024))\n\n  if [ \"$space_available\" -lt \"$space_needed\" ]; then\n    echo \"ERROR: Installation directory has no enough space (needed: ${space_needed}M, available: ${space_available}M\"\n    echo \"ERROR: Please clean up and start the script again\"\n    rmdir \"$installdir\"\n    return 1\n  fi\n\n  _say_what_i_do Cloning cheat.sh locally\n  local url=https://github.com/chubin/cheat.sh\n  rmdir \"$installdir\"\n  git clone \"$url\" \"$installdir\" || fatal Could not clone \"$url\" with git into \"$installdir\"\n  cd \"$installdir\" || fatal \"Cannot cd into $installdir\"\n\n  # after the repository cloned, we may have the log directory\n  # and we can write our installation log into it\n  mkdir -p \"log/\"\n  LOG=\"$PWD/log/install.log\"\n\n  # we use tee everywhere so we should set -o pipefail\n  set -o pipefail\n\n  # currently the script uses python 2,\n  # but cheat.sh supports python 3 too\n  # if you want to switch it to python 3\n  # set PYTHON2 to NO:\n  # PYTHON2=NO\n  #\n  PYTHON2=NO\n  if [[ $PYTHON2 = YES ]]; then\n    python=\"python2\"\n    pip=\"pip\"\n    virtualenv_python3_option=()\n  else\n    python=\"python3\"\n    pip=\"pip3\"\n    virtualenv_python3_option=(-p python3)\n  fi\n\n  _say_what_i_do Creating virtual environment\n  virtualenv \"${virtualenv_python3_option[@]}\" ve \\\n      || fatal \"Could not create virtual environment with 'virtualenv ve'\"\n\n  export CHEATSH_PATH_WORKDIR=$PWD\n\n  # rapidfuzz does not support Python 2,\n  # so if we are using Python 2, install fuzzywuzzy instead\n  if [[ $PYTHON2 = YES ]]; then\n    sed -i s/rapidfuzz/fuzzywuzzy/ requirements.txt\n    echo \"python-Levenshtein\" >> requirements.txt\n  fi\n\n  _say_what_i_do Installing python requirements into the virtual environment\n  ve/bin/\"$pip\" install -r requirements.txt > \"$LOG\" \\\n      || {\n\n    echo \"ERROR:\"\n    echo \"---\"\n    tail -n 10 \"$LOG\"\n    echo \"---\"\n    echo \"See $LOG for more\"\n    fatal Could not install python dependencies into the virtual environment\n  }\n  echo \"$(ve/bin/\"$pip\" freeze | wc -l) dependencies were successfully installed\"\n\n  _say_what_i_do Fetching the upstream cheat sheets repositories\n  ve/bin/python lib/fetch.py fetch-all | tee -a \"$LOG\"\n\n  _say_what_i_do Running self-tests\n  (\n    cd tests || exit\n\n    if CHEATSH_TEST_STANDALONE=YES \\\n       CHEATSH_TEST_SKIP_ONLINE=NO \\\n       CHEATSH_TEST_SHOW_DETAILS=NO \\\n       PYTHON=../ve/bin/python bash run-tests.sh | tee -a \"$LOG\"\n    then\n      printf \"\\033[0;32m%s\\033[0m\\n\" \"SUCCESS\"\n    else\n      printf \"\\033[0;31m%s\\033[0m\\n\" \"FAILED\"\n      echo \"Some tests were failed. Run the tests manually for further investigation:\"\n      echo \"  cd $PWD; bash run-tests.sh)\"\n    fi\n  )\n\n  mkdir -p \"$CHTSH_HOME\"\n  echo \"$installdir\" > \"$CHTSH_HOME/standalone\"\n  echo auto > \"$CHTSH_HOME/mode\"\n\n  _say_what_i_do Done\n\n  local v1; v1=$(printf \"\\033[0;1;32m\")\n  local v2; v2=$(printf \"\\033[0m\")\n\n  cat <<EOF | sed \"s/{/$v1/; s/}/$v2/\"\n\n{      _      }\n{     \\\\ \\\\   }     The installation is successfully finished.\n{      \\\\ \\\\  }\n{      / /    }   Now you can use cheat.sh in the standalone mode,\n{     /_/     }   or you can start your own cheat.sh server.\n\n\nNow the cht.sh shell client is switched to the auto mode, where it uses\nthe local cheat.sh installation if possible.\nYou can switch the mode with the --mode switch:\n\n    cht.sh --mode lite      # use https://cheat.sh/ only\n    cht.sh --mode auto      # use local installation\n\nYou can add your own cheat sheets repository (config is in \\`etc/config.yaml\\`),\nor create new cheat sheets adapters (in \\`lib/adapters\\`).\n\nTo update local copies of cheat sheets repositores on a regular basis,\nadd the following line to your user crontab (crontab -e):\n\n    10 * * * * $installdir/ve/bin/python $installdir/lib/fetch.py update-all\n\nAll cheat sheets will be automatically actualized each hour.\n\nIf you are running a server reachable from the Internet, it can be instantly\nnotified via a HTTP request about any cheat sheets changes. For that, please\nopen an issue on the cheat.sh project repository [github.com/chubin/cheat.sh]\nwith the ENTRY-POINT from the URL https://ENTRY-POINT/:actualize specified\nEOF\n}\n\nchtsh_mode()\n{\n  local mode=\"$1\"\n\n  local text; text=$(\n    echo \"  auto    use the standalone installation first\"\n    echo \"  lite    use the cheat sheets server directly\"\n  )\n\n  if [ -z \"$mode\" ]; then\n    echo \"current mode: $CHTSH_MODE ($(printf \"%s\" \"$text\" | grep \"$CHTSH_MODE\" | sed \"s/$CHTSH_MODE//; s/^ *//; s/ \\+/ /\"))\"\n    if [ -d \"$CHEATSH_INSTALLATION\" ]; then\n      echo \"cheat.sh standalone installation: $CHEATSH_INSTALLATION\"\n    else\n      echo 'cheat.sh standalone installation not found; falling back to the \"lite\" mode'\n    fi\n  elif [ \"$mode\" = auto ] || [ \"$mode\" = lite ]; then\n    if [ \"$mode\" = \"$CHTSH_MODE\" ]; then\n      echo \"The configured mode was \\\"$CHTSH_MODE\\\"; nothing changed\"\n    else\n      mkdir -p \"$CHTSH_HOME\"\n      echo \"$mode\" > \"$CHTSH_HOME/mode\"\n      echo \"Configured mode: $mode\"\n    fi\n  else\n    echo \"Unknown mode: $mode\"\n    echo Supported modes:\n    echo \"  auto    use the standalone installation first\"\n    echo \"  lite    use the cheat sheets server directly\"\n  fi\n}\n\nget_query_options()\n{\n  local query=\"$*\"\n  if [ -n \"$CHTSH_QUERY_OPTIONS\" ]; then\n    case $query in\n      *\\?*)   query=\"$query&${CHTSH_QUERY_OPTIONS}\";;\n      *)      query=\"$query?${CHTSH_QUERY_OPTIONS}\";;\n    esac\n  fi\n  printf \"%s\" \"$query\"\n}\n\ndo_query()\n{\n  local query=\"$*\"\n  local b_opts=\n  local uri=\"${CHTSH_URL}/\\\"\\$(get_query_options $query)\\\"\"\n\n  if [ -e \"$CHTSH_HOME/id\" ]; then\n    b_opts=\"-b \\\"\\$CHTSH_HOME/id\\\"\"\n  fi\n\n  eval curl \"$b_opts\" -s \"$uri\" > \"$TMP1\"\n\n  if [ -z \"$lines\" ] || [ \"$(wc -l \"$TMP1\" | awk '{print $1}')\" -lt \"$lines\" ]; then\n    cat \"$TMP1\"\n  else\n    ${PAGER:-$defpager} \"$TMP1\"\n  fi\n}\n\nprepare_query()\n{\n  local section=\"$1\"; shift\n  local input=\"$1\"; shift\n  local arguments=\"$1\"\n\n  local query\n  if [ -z \"$section\" ] || [ x\"${input}\" != x\"${input#/}\" ]; then\n    query=$(printf %s \"$input\" | sed 's@ @/@; s@ @+@g')\n  else\n    query=$(printf %s \"$section/$input\" | sed 's@ @+@g')\n  fi\n\n  [ -n \"$arguments\" ] && arguments=\"?$arguments\"\n  printf %s \"$query$arguments\"\n}\n\nget_list_of_sections()\n{\n  curl -s \"${CHTSH_URL}\"/:list | grep -v '/.*/' | grep '/$' | xargs\n}\n\ngen_random_str()\n(\n  len=$1\n  if command -v openssl >/dev/null; then\n    openssl rand -base64 $((len*3/4)) | awk -v ORS='' //\n  else\n    rdev=/dev/urandom\n    for d in /dev/{srandom,random,arandom}; do\n      test -r \"$d\" && rdev=$d\n    done\n    if command -v hexdump >/dev/null; then\n      hexdump -vn $((len/2)) -e '1/1 \"%02X\" 1 \"\"' \"$rdev\"\n    elif command -v xxd >/dev/null; then\n      xxd -l $((len/2)) -ps \"$rdev\" | awk -v ORS='' //\n    else\n      cd /tmp || { echo Cannot cd into /tmp >&2; exit 1; }\n      s=\n      # shellcheck disable=SC2000\n      while [ \"$(echo \"$s\" | wc -c)\" -lt \"$len\" ]; do\n        s=\"$s$(mktemp -u XXXXXXXXXX)\"\n      done\n      printf \"%.${len}s\" \"$s\"\n    fi\n  fi\n)\n\nif [ \"$CHTSH_MODE\" = auto ] && [ -d \"$CHEATSH_INSTALLATION\" ]; then\n  curl() {\n    # ignoring all options\n    # currently the standalone.py does not support them anyway\n    local opt\n    while getopts \"b:s\" opt; do\n      :\n    done\n    shift $((OPTIND - 1))\n\n    local url; url=\"$1\"; shift\n    PYTHONIOENCODING=UTF-8 \"$CHEATSH_INSTALLATION/ve/bin/python\" \"$CHEATSH_INSTALLATION/lib/standalone.py\" \"${url#\"$CHTSH_URL\"}\" \"$@\"\n  }\nelif [ \"$(uname -s)\" = OpenBSD ] && [ -x /usr/bin/ftp ]; then\n  # any better test not involving either OS matching or actual query?\n  curl() {\n    local opt args=\"-o -\"\n    while getopts \"b:s\" opt; do\n      case $opt in\n        b) args=\"$args -c $OPTARG\";;\n        s) args=\"$args -M -V\";;\n        *) echo \"internal error: unsupported cURL option '$opt'\" >&2; exit 1;;\n      esac\n    done\n    shift $((OPTIND - 1))\n    /usr/bin/ftp \"$args\" \"$@\"\n  }\nelse\n  command -v curl   >/dev/null || { echo 'DEPENDENCY: install \"curl\" to use cht.sh' >&2; exit 1; }\n  _CURL=$(command -v curl)\n  if [ x\"$CHTSH_CURL_OPTIONS\" != x ]; then\n    curl() {\n      $_CURL \"${CHTSH_CURL_OPTIONS}\" \"$@\"\n    }\n  fi\nfi\n\nif [ \"$1\" = --read ]; then\n  read -r a || a=\"exit\"\n  printf \"%s\\n\" \"$a\"\n  exit 0\nelif [ x\"$1\" = x--help ] || [ -z \"$1\" ]; then\n\n  n=${0##*/}\n  s=$(echo \"$n\" | sed \"s/./ /\"g)\n\n  cat <<EOF\nUsage:\n\n    $n [OPTIONS|QUERY]\n\nOptions:\n\n    QUERY                   process QUERY and exit\n\n    --help                  show this help\n    --shell [LANG]          shell mode (open LANG if specified)\n\n    --standalone-install [DIR|help]\n                            install cheat.sh in the standalone mode\n                            (by default, into ~/.cheat.sh/)\n\n    --mode [auto|lite]      set (or display) mode of operation\n                            * auto - prefer the local installation\n                            * lite - use the cheat sheet server\n\nEOF\n  exit 0\nelif [ x\"$1\" = x--shell ]; then\n  shell_mode=yes\n  shift\nelif [ x\"$1\" = x--standalone-install ]; then\n  shift\n  cheatsh_standalone_install \"$@\"\n  exit \"$?\"\nelif [ x\"$1\" = x--mode ]; then\n  shift\n  chtsh_mode \"$@\"\n  exit \"$?\"\nfi\n\nprompt=\"cht.sh\"\nopts=\"\"\ninput=\"\"\nfor o; do\n  if [ x\"$o\" != x\"${o#-}\" ]; then\n    opts=\"${opts}${o#-}\"\n  else\n    input=\"$input $o\"\n  fi\ndone\nquery=$(echo \"$input\" | sed 's@ *$@@; s@^ *@@; s@ @/@; s@ @+@g')\n\nif [ \"$shell_mode\" != yes ]; then\n  curl -s \"${CHTSH_URL}\"/\"$(get_query_options \"$query\")\"\n  exit 0\nelse\n  new_section=\"$1\"\n  valid_sections=$(get_list_of_sections)\n  valid=no; for q in $valid_sections; do [ \"$q\" = \"$new_section/\" ] && { valid=yes; break; }; done\n\n  if [ \"$valid\" = yes ]; then\n    section=\"$new_section\"\n    # shellcheck disable=SC2001\n    this_query=\"$(echo \"$input\" | sed 's@ *[^ ]* *@@')\"\n    this_prompt=\"\\033[0;32mcht.sh/$section>\\033[0m \"\n  else\n    this_query=\"$input\"\n    this_prompt=\"\\033[0;32mcht.sh>\\033[0m \"\n  fi\n  if [ -n \"$this_query\" ] && [ -z \"$CHEATSH_RESTART\" ]; then\n    printf \"$this_prompt$this_query\\n\"\n    curl -s \"${CHTSH_URL}\"/\"$(get_query_options \"$query\")\"\n  fi\nfi\n\nif [ \"$is_macos\" != yes ]; then\n  if [ \"$XDG_SESSION_TYPE\" = wayland ]; then\n    command -v wl-copy >/dev/null || echo 'DEPENDENCY: please install \"wl-copy\" for \"copy\"' >&2\n  else\n    command -v xsel >/dev/null ||   echo 'DEPENDENCY: please install \"xsel\" for \"copy\"' >&2\n  fi\nfi\ncommand -v rlwrap >/dev/null || { echo 'DEPENDENCY: install \"rlwrap\" to use cht.sh in the shell mode' >&2; exit 1; }\n\nmkdir -p \"$CHTSH_HOME/\"\nlines=$(tput lines)\n\nif command -v less >/dev/null; then\n  defpager=\"less -R\"\nelif command -v more >/dev/null; then\n  defpager=\"more\"\nelse\n  defpager=\"cat\"\nfi\n\ncmd_cd() {\n  if [ $# -eq 0 ]; then\n    section=\"\"\n  else\n    new_section=$(echo \"$input\" | sed 's/cd  *//; s@/*$@@; s@^/*@@')\n    if [ -z \"$new_section\" ] || [ \"..\" = \"$new_section\" ]; then\n      section=\"\"\n    else\n      valid_sections=$(get_list_of_sections)\n      valid=no; for q in $valid_sections; do [ \"$q\" = \"$new_section/\" ] && { valid=yes; break; }; done\n      if [ \"$valid\" = no ]; then\n        echo \"Invalid section: $new_section\"\n        echo \"Valid sections:\"\n        echo \"$valid_sections\" \\\n            | xargs printf \"%-10s\\n\" \\\n            | tr ' ' .  \\\n            | xargs -n 10 \\\n            | sed 's/\\./ /g; s/^/  /'\n      else\n        section=\"$new_section\"\n      fi\n    fi\n  fi\n}\n\ncmd_copy() {\n  if [ -z \"$DISPLAY\" ]; then\n    echo copy: supported only in the Desktop version\n  elif [ -z \"$input\" ]; then\n    echo copy: Make at least one query first.\n  else\n    curl -s \"${CHTSH_URL}\"/\"$(get_query_options \"$query\"?T)\" > \"$TMP1\"\n    if [ \"$is_macos\" != yes ]; then\n      if [ \"$XDG_SESSION_TYPE\" = wayland ]; then\n        wl-copy < \"$TMP1\"\n      else\n        xsel -bi < \"$TMP1\"\n      fi\n    else\n      pbcopy < \"$TMP1\"\n    fi\n    echo \"copy: $(wc -l \"$TMP1\" | awk '{print $1}') lines copied to the selection\"\n  fi\n}\n\ncmd_ccopy() {\n  if [ -z \"$DISPLAY\" ]; then\n    echo copy: supported only in the Desktop version\n  elif [ -z \"$input\" ]; then\n    echo copy: Make at least one query first.\n  else\n    curl -s \"${CHTSH_URL}\"/\"$(get_query_options \"$query\"?TQ)\" > \"$TMP1\"\n    if [ \"$is_macos\" != yes ]; then\n      if [ \"$XDG_SESSION_TYPE\" = wayland ]; then\n        wl-copy < \"$TMP1\"\n      else\n        xsel -bi < \"$TMP1\"\n      fi\n    else\n      pbcopy < \"$TMP1\"\n    fi\n    echo \"copy: $(wc -l \"$TMP1\" | awk '{print $1}') lines copied to the selection\"\n  fi\n}\n\ncmd_exit() {\n  exit 0\n}\n\ncmd_help() {\n  cat <<EOF\nhelp    - show this help\nhush    - do not show the 'help' string at start anymore\ncd LANG - change the language context\ncopy    - copy the last answer in the clipboard (aliases: yank, y, c)\nccopy   - copy the last answer w/o comments (cut comments; aliases: cc, Y, C)\nexit    - exit the cheat shell (aliases: quit, ^D)\nid [ID] - set/show an unique session id (\"reset\" to reset, \"remove\" to remove)\nstealth - stealth mode (automatic queries for selected text)\nupdate  - self update (only if the scriptfile is writeable)\nversion - show current cht.sh version\n/:help  - service help\nQUERY   - space separated query staring (examples are below)\n              cht.sh> python zip list\n              cht.sh/python> zip list\n              cht.sh/go> /python zip list\nEOF\n}\n\ncmd_hush() {\n  mkdir -p \"$CHTSH_HOME/\" && touch \"$CHTSH_HOME/.hushlogin\" && echo \"Initial 'use help' message was disabled\"\n}\n\ncmd_id() {\n  id_file=\"$CHTSH_HOME/id\"\n\n  if [ id = \"$input\" ]; then\n    new_id=\"\"\n  else\n    new_id=$(echo \"$input\" | sed 's/id  *//; s/ *$//; s/ /+/g')\n  fi\n  if [ \"$new_id\" = remove ]; then\n    if [ -e \"$id_file\" ]; then\n      rm -f -- \"$id_file\" && echo \"id is removed\"\n    else\n      echo \"id was not set, so you can't remove it\"\n    fi\n    return\n  fi\n  if [ -n \"$new_id\" ] && [ reset != \"$new_id\" ] && [ \"$(/bin/echo -n \"$new_id\" | wc -c)\" -lt 16 ]; then\n    echo \"ERROR: $new_id: Too short id. Minimal id length is 16. Use 'id reset' for a random id\"\n    return\n  fi\n  if [ -z \"$new_id\" ]; then\n    # if new_id is not specified check if we have some id already\n    # if yes, just show it\n    # if not, generate a new id\n    if [ -e \"$id_file\" ]; then\n      awk '$6 == \"id\" {print $NF}' <\"$id_file\" | tail -n 1\n      return\n    else\n      new_id=reset\n    fi\n  fi\n  if [ \"$new_id\" = reset ]; then\n    new_id=$(gen_random_str 12)\n  else\n    echo WARNING: if someone gueses your id, he can read your cht.sh search history\n  fi\n  if [ -e \"$id_file\" ] && grep -q '\\tid\\t[^\\t][^\\t]*$' \"$id_file\" 2> /dev/null; then\n    sed -i 's/\\tid\\t[^\\t][^\\t]*$/ id '\"$new_id\"'/' \"$id_file\"\n  else\n    if ! [ -e \"$id_file\" ]; then\n      printf '#\\n\\n' > \"$id_file\"\n    fi\n    printf \".cht.sh\\tTRUE\\t/\\tTRUE\\t0\\tid\\t$new_id\\n\" >> \"$id_file\"\n  fi\n  echo \"$new_id\"\n}\n\ncmd_query() {\n  query=$(prepare_query \"$section\" \"$input\")\n  do_query \"$query\"\n}\n\ncmd_stealth() {\n  if [ \"$input\" != stealth ]; then\n    arguments=$(echo \"$input\" | sed 's/stealth //; s/ /\\&/')\n  fi\n  trap break INT\n  if [ \"$is_macos\" = yes ]; then\n    past=$(pbpaste)\n  else\n    if [ \"$XDG_SESSION_TYPE\" = wayland ]; then\n      past=$(wl-paste -p)\n    else\n      past=$(xsel -o)\n    fi\n  fi\n  printf \"\\033[0;31mstealth:\\033[0m you are in the stealth mode; select any text in any window for a query\\n\"\n  printf \"\\033[0;31mstealth:\\033[0m selections longer than $STEALTH_MAX_SELECTION_LENGTH words are ignored\\n\"\n  if [ -n \"$arguments\" ]; then\n    printf \"\\033[0;31mstealth:\\033[0m query arguments: ?$arguments\\n\"\n  fi\n  printf \"\\033[0;31mstealth:\\033[0m use ^C to leave this mode\\n\"\n  while true; do\n    if [ \"$is_macos\" = yes ]; then\n      current=$(pbpaste)\n    else\n      if [ \"$XDG_SESSION_TYPE\" = wayland ]; then\n        current=$(wl-paste -p)\n      else\n        current=$(xsel -o)\n      fi\n    fi\n    if [ \"$past\" != \"$current\" ]; then\n      past=$current\n      current_text=\"$(echo $current | tr -c '[a-zA-Z0-9]' ' ')\"\n      if [ \"$(echo \"$current_text\" | wc -w)\" -gt \"$STEALTH_MAX_SELECTION_LENGTH\" ]; then\n        printf \"\\033[0;31mstealth:\\033[0m selection length is longer than $STEALTH_MAX_SELECTION_LENGTH words; ignoring\\n\"\n        continue\n      else\n        printf \"\\n\\033[0;31mstealth: \\033[7m $current_text\\033[0m\\n\"\n        query=$(prepare_query \"$section\" \"$current_text\" \"$arguments\")\n        do_query \"$query\"\n      fi\n    fi\n    sleep 1;\n  done\n  trap - INT\n}\n\ncmd_update() {\n  [ -w \"$0\" ] || { echo \"The script is readonly; please update manually: curl -s ${CHTSH_URL}/:cht.sh | sudo tee $0\"; return; }\n  TMP2=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX)\n  curl -s \"${CHTSH_URL}\"/:cht.sh > \"$TMP2\"\n  if ! cmp \"$0\" \"$TMP2\" > /dev/null 2>&1; then\n    if grep -q ^__CHTSH_VERSION= \"$TMP2\"; then\n      # section was vaildated by us already\n      args=(--shell \"$section\")\n      cp \"$TMP2\" \"$0\" && echo \"Updated. Restarting...\" && rm \"$TMP2\" && CHEATSH_RESTART=1 exec \"$0\" \"${args[@]}\"\n    else\n      echo \"Something went wrong. Please update manually\"\n    fi\n  else\n    echo \"cht.sh is up to date. No update needed\"\n  fi\n  rm -f \"$TMP2\" > /dev/null 2>&1\n}\n\ncmd_version() {\n  insttime=$(ls -l -- \"$0\" | sed 's/  */ /g' | cut -d ' ' -f 6-8)\n  echo \"cht.sh version $__CHTSH_VERSION of $__CHTSH_DATETIME; installed at: $insttime\"\n  TMP2=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX)\n  if curl -s \"${CHTSH_URL}\"/:cht.sh > \"$TMP2\"; then\n    if ! cmp \"$0\" \"$TMP2\" > /dev/null 2>&1; then\n      echo \"Update needed (type 'update' for that)\".\n    else\n      echo \"Up to date. No update needed\"\n    fi\n  fi\n  rm -f \"$TMP2\" > /dev/null 2>&1\n}\n\nTMP1=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX)\ntrap 'rm -f $TMP1 $TMP2' EXIT\ntrap 'true' INT\n\nif ! [ -e \"$CHTSH_HOME/.hushlogin\" ] && [ -z \"$this_query\" ]; then\n  echo \"type 'help' for the cht.sh shell help\"\nfi\n\nwhile true; do\n  if [ \"$section\" != \"\" ]; then\n    full_prompt=\"$prompt/$section> \"\n  else\n    full_prompt=\"$prompt> \"\n  fi\n\n  input=$(\n    rlwrap -H \"$CHTSH_HOME/history\" -pgreen -C cht.sh -S \"$full_prompt\" bash \"$0\" --read | sed 's/ *#.*//'\n  )\n\n  cmd_name=${input%% *}\n  cmd_args=${input#* }\n  case $cmd_name in\n    \"\")             continue;;   # skip empty input lines\n    '?'|h|help)     cmd_name=help;;\n    hush)           cmd_name=hush;;\n    cd)             cmd_name=\"cd\";;\n    exit|quit)      cmd_name=\"exit\";;\n    copy|yank|c|y)  cmd_name=copy;;\n    ccopy|cc|C|Y)   cmd_name=ccopy;;\n    id)             cmd_name=id;;\n    stealth)        cmd_name=stealth;;\n    update)         cmd_name=update;;\n    version)        cmd_name=version;;\n    *)              cmd_name=\"query\"; cmd_args=\"$input\";;\n  esac\n  \"cmd_$cmd_name\" $cmd_args\ndone\n"
  },
  {
    "path": "tests/results/9",
    "content": "\u001b[38;5;246;03m#  How do I copy a file in Python?\u001b[39;00m\n\u001b[38;5;246;03m#  \u001b[39;00m\n\u001b[38;5;246;03m#  shutil (http://docs.python.org/3/library/shutil.html) has many methods\u001b[39;00m\n\u001b[38;5;246;03m#  you can use. One of which is:\u001b[39;00m\n\n\u001b[38;5;70;01mfrom\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;68;04mshutil\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;70;01mimport\u001b[39;00m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mcopyfile\u001b[39m\n\n\u001b[38;5;252mcopyfile\u001b[39m\u001b[38;5;252m(\u001b[39m\u001b[38;5;252msrc\u001b[39m\u001b[38;5;252m,\u001b[39m\u001b[38;5;252m \u001b[39m\u001b[38;5;252mdst\u001b[39m\u001b[38;5;252m)\u001b[39m\n\n\u001b[38;5;246;03m#  Copy the contents of the file named src to a file named dst. The\u001b[39;00m\n\u001b[38;5;246;03m#  destination location must be writable; otherwise, an IOError exception\u001b[39;00m\n\u001b[38;5;246;03m#  will be raised. If dst already exists, it will be replaced. Special\u001b[39;00m\n\u001b[38;5;246;03m#  files such as character or block devices and pipes cannot be copied\u001b[39;00m\n\u001b[38;5;246;03m#  with this function. src and dst are path names given as strings.\u001b[39;00m\n\u001b[38;5;246;03m#  \u001b[39;00m\n\u001b[38;5;246;03m#  [Swati] [so/q/123198] [cc by-sa 3.0]\u001b[39;00m\n"
  },
  {
    "path": "tests/run-tests.sh",
    "content": "#!/bin/bash\n\n# 1) start server:\n#   without caching:\n#       CHEATSH_CACHE_TYPE=none CHEATSH_PORT=50000 python bin/srv.py\n#       (recommended)\n#   with caching:\n#       CHEATSH_REDIS_PREFIX=TEST1 CHEATSH_PORT=50000 python bin/srv.py\n#       (for complex search queries + to test caching)\n# 2) configure CHTSH_URL\n# 3) run the script\n\nCHTSH_SCRIPT=$(dirname \"$(dirname \"$(realpath \"$(readlink -f \"$0\")\")\")\")/share/cht.sh.txt\n\n# work from script's dir\ncd \"$(dirname \"$0\")\" || exit\n\n# detect Python - if not set in env, try default virtualenv\nPYTHON=\"${PYTHON:-../ve/bin/python}\"\n# if no virtalenv, try current python3 binary\nif ! command -v \"$PYTHON\" &> /dev/null; then\n  PYTHON=$(command -v python3)\nfi\npython_version=\"$($PYTHON -c 'import sys; print(sys.version_info[0])')\"\necho \"Using PYTHON $python_version: $PYTHON\"\n\nskip_online=\"${CHEATSH_TEST_SKIP_ONLINE:-NO}\"\ntest_standalone=\"${CHEATSH_TEST_STANDALONE:-YES}\"\nshow_details=\"${CHEATSH_TEST_SHOW_DETAILS:-YES}\"\nupdate_tests_results=\"${CHEATSH_UPDATE_TESTS_RESULTS:-NO}\"\nCHTSH_URL=\"${CHTSH_URL:-http://localhost:8002}\"\n\nTMP=$(mktemp /tmp/cht.sh.tests-XXXXXXXXXXXXXX)\nTMP2=$(mktemp /tmp/cht.sh.tests-XXXXXXXXXXXXXX)\nTMP3=$(mktemp /tmp/cht.sh.tests-XXXXXXXXXXXXXX)\ntrap 'rm -rf $TMP $TMP2 $TMP3' EXIT\n\necho \"Using cht.sh client at $CHTSH_SCRIPT\"\n\nexport PYTHONIOENCODING=UTF-8\n\ni=0\nfailed=0\n{\n  if [ -z \"$1\" ]; then\n    cat -n tests.txt\n  else\n    cat -n tests.txt | sed -n \"$(echo \"$*\" | sed 's/ /p; /g;s/$/p/')\"\n  fi\n} > \"$TMP3\"\n\n\nwhile read -r number test_line; do\n  echo -e \"\\e[34mRunning $number: \\e[36m$test_line\\e[0m\"\n  if [ \"$skip_online\" = YES ]; then\n    if [[ $test_line = *\\[online\\]* ]]; then\n      echo \"$number is [online]; skipping\"\n      continue\n    fi\n  fi\n\n  if [[ \"$python_version\" = 2 ]] && [[ $test_line = *\\[python3\\]* ]]; then\n    echo \"$number is for Python 3; skipping\"\n    continue\n  fi\n\n  if [[ \"$python_version\" = 3 ]] && [[ $test_line = *\\[python2\\]* ]]; then\n    echo \"$number is for Python 2; skipping\"\n    continue\n  fi\n\n  #shellcheck disable=SC2001\n  test_line=$(echo \"$test_line\" | sed 's@ *#.*@@')\n\n  if [ \"$test_standalone\" = YES ]; then\n    test_line=\"${test_line//cht.sh /}\"\n    [[ $show_details == YES ]] && echo \"${PYTHON} ../lib/standalone.py $test_line\"\n    \"${PYTHON}\" ../lib/standalone.py \"$test_line\" > \"$TMP\"\n  elif [[ $test_line = \"cht.sh \"* ]]; then\n    test_line=\"${test_line//cht.sh /}\"\n    [[ $show_details == YES ]] && echo \"bash $CHTSH_SCRIPT $test_line\"\n    eval \"bash $CHTSH_SCRIPT $test_line\" > \"$TMP\"\n  else\n    [[ $show_details == YES ]] && echo \"curl -s $CHTSH_URL/$test_line\"\n    eval \"curl -s $CHTSH_URL/$test_line\" > \"$TMP\"\n  fi\n\n  if ! diff -u3 results/\"$number\" \"$TMP\" > \"$TMP2\"; then\n    if [[ $update_tests_results = NO ]]; then\n      if [ \"$show_details\" = YES ]; then\n        cat -t \"$TMP2\"\n      fi\n      echo \"FAILED: [$number] $test_line\"\n    else\n      cat \"$TMP\" > results/\"$number\"\n      echo \"UPDATED: [$number] $test_line\"\n    fi\n    ((failed++))\n  fi\n  ((i++))\ndone < \"$TMP3\"\n\nif [[ $update_tests_results = NO ]]; then\n  echo TESTS/OK/FAILED \"$i/$((i-failed))/$failed\"\nelse\n  echo TESTS/OK/UPDATED \"$i/$((i-failed))/$failed\"\nfi\n\ntest $failed -eq 0\n"
  },
  {
    "path": "tests/tests.txt",
    "content": "python/:list\nls\nls?T\nbtrfs\nbtrfs~volume                # search on page\n:intro\n:help\n:cht.sh\ncht.sh python copy file     # [online]\npython/copy+file            # [online]\npython/copy+file?Q          # [online]\npython/copy+file?QT         # [online]\n/\n//\npython/:learn\nlatencies                   # [python3]\naz                          # chubin/cheat.sheets\npython/rosetta/Substring    # rosetta\npython/rosetta/Substring?T  # rosetta\npython/rosetta/:list        # rosetta\njs/:learn                   # short names check\njavascript/:learn           # short names check\nemacs:go-mode/:list         # special editor names\nmkffs.ffatt                 # unknown\nlatencies                   # [python2]\n"
  }
]