Compare commits

...
133 Commits
Author SHA1 Message Date
José Valim 524528b973 Add branch docs publishing 2023-05-30 11:23:49 +02:00
jendis a64d42f5d3 Fix elixir test assertion for erlang >=OTP-24.1 (#11309) 2021-10-13 23:48:14 +02:00
Tobias Pfeiffer 7636046bd9 Add missing --warnings-as-errors on mix test to Changelog (#11303)
Sources:
* https://dashbit.co/blog/tests-with-warnings-as-errors
* https://hexdocs.pm/mix/master/Mix.Tasks.Test.html
2021-10-08 13:30:42 +02:00
Justin Morrow 552b5abed8 docs(code.ex): fix ensure_loaded typos in Code docs (#11253)
Fixes two documentation typos in the code.ex `@moduledoc`
`ensure_lodead!` => `ensure_loaded!`
`ensure_lodead?` => `ensure_loaded?`
2021-09-17 08:50:38 +02:00
José Valim 74bfab8ee2 Release v1.12.3 2021-09-05 10:02:59 +02:00
José Valim e00cbe16cd Revert content tracking instead of mtime. 2021-08-24 08:31:52 +02:00
Marc-André Lafortune 9df7a548ed Make sure .beam files still exist for restored files (#11187) 2021-08-18 07:51:50 +02:00
José Valim 9137fd1cb2 Do not return context tuples on optimized eval 2021-07-22 08:10:38 +02:00
José Valim 5189b292ac Purge v8 manifests properly 2021-07-16 21:37:57 +02:00
Marc-André Lafortune 74f9a299ea Rely on modification time and hash to determine modified sources (#11080) 2021-07-16 21:37:57 +02:00
José Valim 2ce9d25552 Do not error autocompletion with module attribute, closes #11120 2021-07-16 19:21:36 +02:00
José Valim b558142819 Rename exit_code to exit_status for consistency 2021-07-15 20:52:20 +02:00
Łukasz Samson d7f96d8332 Keep backwards compatibility on Range and Date.Range (#11117) 2021-07-14 13:32:03 +02:00
José Valim 010efd8ec6 Fix regex 2021-07-13 11:29:26 +02:00
José Valim c0174044bc Fix regex 2021-07-13 11:12:08 +02:00
José Valim 616e0d8ccc Do not crash when handling ambiguity errors, closes #11111 2021-07-13 10:36:14 +02:00
José Valim 13ba96be3c Keep backwards compatibility on range usage, closes #11110 2021-07-12 12:32:22 +02:00
José Valim edb5e7e052 Document backwards incompatible change, closes #11105 2021-07-06 15:01:41 +02:00
José Valim 58ca6524f8 Release v1.12.2 2021-07-01 18:15:34 +02:00
José Valim afcefb3e21 Run formatter 2021-06-26 09:33:24 +02:00
José Valim fb5aabf05a Remove warning and improve coverage on Enum.into/2 tests 2021-06-26 09:31:02 +02:00
José Valim d9a81101dd Optimize Enum.into and Map.new 2021-06-26 09:26:45 +02:00
José Valim 8fca53ad31 Ensure deprecated macros emit warnings 2021-06-23 22:15:43 +02:00
José Valim 76dfedb2e3 Compile most recently changed files first 2021-06-22 20:07:38 +02:00
Christopher Keele 8bec593f5d Ensure unconstrained rebar deps generate valid mix specifications (#11063) 2021-06-15 10:25:33 +02:00
TORIFUKUKaiou 03859fb92e Add @doc since: "1.12.0" and comments (#11046) 2021-06-08 09:07:35 +02:00
José Valim 53e49f33f1 Update CHANGELOG 2021-06-08 09:03:06 +02:00
Marc Riera c0bdd6101f Improve docs for sigil_r (#11051) 2021-06-08 08:59:24 +02:00
José Valim e7cb210712 Do not add compile time deps on args to Application.compile_env/2, closes #11052 2021-06-08 08:59:21 +02:00
TORIFUKUKaiou 4a4657e413 Add @doc since: "1.12.0" (#11039) 2021-06-05 22:21:21 +02:00
José Valim fcada17819 Align profiling times for better readability
Before we would write:

    lib/foo.ex compiled in 10ms (plus 100ms waiting)

However, because the file name is variable, it was
hard to see which file took the longest. Now we will
write:

        10ms compiling +    100ms waiting for lib/foo.ex

By right aligning all times, we can easily look in
the first row and see which file took the longest.
We can also provide a summary option in the future,
if necessary.
2021-06-05 22:21:15 +02:00
José Valim 6be8bddc02 Also annotate temp var for remote call in map.foo as generated
Closes #11030.
2021-06-01 15:04:23 +02:00
José Valim 9feda914dc Simplify reading of apps from deps 2021-06-01 11:53:12 +02:00
José Valim 62e1d71377 Avoid central bottleneck when loading apps if we know their source 2021-06-01 10:24:18 +02:00
José Valim d6ed6d18ef Remove duplication across branches 2021-06-01 09:37:47 +02:00
José Valim e024a12c50 Load apps concurrently 2021-06-01 09:36:25 +02:00
José Valim 42807d288e Release v1.12.1 2021-05-28 17:34:14 +02:00
José Valim 3b8d7fa15d Update CHANGELOG 2021-05-28 11:41:32 +02:00
José Valim d1d5e04319 Revert "Run all available tests if there are no pending --failed tests"
This reverts commit ae48325991.
2021-05-27 15:53:28 +02:00
José Valim ba1fd1abb8 Improve error message on invalid config 2021-05-26 19:14:28 +02:00
Wojtek Mach 8fd6c8f845 Ensure Mix.install/2 can be called after errors with deps (#11011) 2021-05-26 19:14:04 +02:00
Wojtek Mach 95dcbe9fe0 Mix.install/2: Expand paths for path deps (#11012) 2021-05-26 19:14:04 +02:00
José Valim 98a79dc839 Fix spec for which_children, closes #11005 2021-05-25 09:46:59 +02:00
José Valim 29444793b7 Fix formatter integration test 2021-05-22 21:24:58 +02:00
José Valim ff3674ddef Format multiline inside interpolation on first run, closes #10996 2021-05-22 20:46:05 +02:00
José Valim 0460017c5c Revert keeping of underscores between digits in camelize, closes #10995 2021-05-21 14:11:13 +02:00
José Valim f3b870857a Split on \r\n and \n accordingly during unicode compilation, closes #10991 2021-05-20 12:12:55 +02:00
José Valim faa2f35d8e Fix bootstrapping issue 2021-05-19 23:23:55 +02:00
José Valim 3339168330 Silence httpc warnings 2021-05-19 23:13:56 +02:00
José Valim 1c3ee4ed72 Remove unecessary copying of priv/include for Rebar 3 deps 2021-05-19 19:30:40 +02:00
José Valim 926455ca24 Add date to CHANGELOG 2021-05-19 14:36:49 +02:00
José Valim f73e318bce Release v1.12.0 2021-05-19 12:10:36 +02:00
Jason Axelson 1f3b022340 Improve ExUnit seed docs (#10962)
Make it more obvious what a seed of 0 does.
2021-05-19 12:08:12 +02:00
Preston Guillory f82f2c7b3e Optimize Enum.unzip/1 for lists (#10963)
The existing unzip implementation is generic for all enumerable types.
However, large optimizations are available if the input is a list.

First, instead of doing two reverse operations at the end, we can do
one at the beginning. This optimization is unavailable in the existing
generic implementation in order to avoid materializing an enumerable
that might be generated lazily.

Second, we can accumulate the two output lists in two separate parameters,
rather than in the reduce function's accumulator. This avoids generating a
tuple per input element that would just be matched away and discarded
by Enum.reduce/3.

Testing with Benchfella shows a roughly 2x to 3x performance improvement
depending on the size of the list.
2021-05-19 12:08:09 +02:00
José Valim 63e6f24457 Add IO.stream/0 and IO.binstream/0 as convenience functions 2021-05-19 12:07:51 +02:00
José Valim aa25920f75 Improve error message for expression after keyword
For maps and lists:

    $ elixir -e "%{foo: :bar, :baz => :bat}"
    ** (SyntaxError) nofile:1: unexpected expression after keyword list. Keyword lists must always come last in lists and maps. Therefore, this is not allowed:

        [some: :value, :another]
        %{some: :value, another => value}

    Instead, reorder it to be the last entry:

        [:another, some: :value]
        %{another => value, some: :value}

    Syntax error after: ','
        (elixir 1.13.0-dev) lib/code.ex:655: Code.eval_string_with_error_handling/3

For calls:

    $ elixir -e "call foo: :bar, :baz"
    ** (SyntaxError) nofile:1: unexpected expression after keyword list. Keyword lists must always come as the last argument. Therefore, this is not allowed:

        function_call(1, some: :option, 2)

    Instead, wrap the keyword in brackets:

        function_call(1, [some: :option], 2)

    Syntax error after: ','
        (elixir 1.13.0-dev) lib/code.ex:655: Code.eval_string_with_error_handling/3

Closes #10973.
2021-05-19 12:07:36 +02:00
José Valim 64dcd3f937 Improve unused type variable message, closes #10985 2021-05-19 12:07:33 +02:00
José Valim 4c6f393bd0 Update CHANGELOG.md 2021-05-16 20:17:40 +02:00
José Valim d11396204b Update CHANGELOG 2021-05-16 13:52:45 +02:00
José Valim 05ab231bc6 Remove REBAR_BARE_COMPILER_OUTPUT_DIR to fix issues with build_embedded
See #10978.
2021-05-16 13:51:19 +02:00
Eksperimental 9fcdf234dd Add OTP 24.0 to Linux CI (#10980) 2021-05-14 07:38:51 +02:00
Eksperimental 14afabb7c8 Fix typo (#10979) 2021-05-14 07:38:51 +02:00
José Valim 2d5141d69d Specify how we track OTP versions 2021-05-13 09:17:10 +02:00
José Valim 480c19cb5b Respect keywords in access in code formatter 2021-05-11 12:37:58 +02:00
felipe stival 1c9d7365db Fix signature expansion when no docs (#10971)
We were returning an error whenever there wasn't a list of docs. This
changes it so it returns an empty list and the expansion can proceed.
2021-05-11 08:47:55 +02:00
José Valim a5caf4bf56 Require Erlang/OTP 22+ 2021-05-06 19:20:14 +02:00
José Valim 767e3479df Require Erlang/OTP 22+ 2021-05-06 19:14:44 +02:00
Eksperimental 863c49899c Update Enum.{random, shuffle}/1 docs to OTP 22 (#10848) 2021-05-06 19:14:30 +02:00
José Valim 5467b4e335 Remove TODOs related to Erlang/OTP 22+ 2021-05-06 19:14:26 +02:00
Łukasz Samson 7aec544b22 Use :erlang.system_info(:ets_count) introduced in OTP 22 (#10841) 2021-05-06 19:14:22 +02:00
Eksperimental f71f37e43d Remove Integer.to_string/1 and Integer.to_charlist/1 (#8777)
They are not needed, since they are covered by their /2 version.
2021-05-06 19:14:18 +02:00
Wojtek Mach ff96fa2834 Add @doc since to System.shell/2 (#10967) 2021-05-06 09:08:07 +02:00
José Valim 49bc4fc0ea Add System.shell/2 (#10965) 2021-05-05 21:05:05 +02:00
Adam Rutkowski fe3c393c3f Disallow streaming with max_concurrency=0 (#10966) 2021-05-05 21:05:05 +02:00
Wojtek Mach d9d70158a6 Mix.install/2: Recover from deps.get failures (#10958) 2021-04-27 23:13:43 +02:00
José Valim a582bd931f Fix CI on Windows 2021-04-25 19:55:38 +02:00
Joe f358cd4977 Update CHANGELOG.md (#10953) 2021-04-25 19:45:18 +02:00
José Valim 47b4952d73 Merge CHANGELOG 2021-04-24 18:32:54 +02:00
José Valim ce321f8cf4 Release v1.12.0-rc.1 2021-04-24 16:49:35 +02:00
José Valim 77fa0c4f46 Handle new significant key in sasl reports 2021-04-23 17:16:10 +02:00
José Valim 3842dcce87 Update CHANGELOG 2021-04-23 11:55:16 +02:00
Eksperimental 22f2fa9ddc Add missing backtick in Code.cursor_context/2 (#10943) 2021-04-22 15:32:56 +02:00
Wojtek Mach 148cdcec14 Update Code.cursor_context/2 docs (#10931) 2021-04-20 12:37:46 +02:00
Wojtek Mach c13335ffd4 Add Module.reserved_attributes/0 (#10926) 2021-04-20 12:37:46 +02:00
José Valim d85d13fb28 Code.cursor_context/2 (#10915) 2021-04-20 12:37:46 +02:00
Eksperimental 0b4eb72609 Fix table in Operators page (#10930)
It was broken due to the changes in d9a23d0d38
2021-04-20 09:09:07 +02:00
José Valim a83fddb3c8 Do not crash on Path.absname(c:) (#10919) 2021-04-17 22:05:58 +02:00
José Valim 81d04d80fa Make sure we traverse all files when looking for definitions 2021-04-12 13:15:12 +02:00
José Valim ccb554614d Always pop the project stack 2021-04-12 12:36:11 +02:00
sabiwara 02d0567f05 Fix regression in Enum.dedup/1 (#10886) 2021-04-09 13:18:14 +02:00
José Valim 4582f87faf Update CHANGELOG 2021-04-09 13:13:16 +02:00
José Valim 274557b131 Fix bootstrap warning 2021-04-09 00:30:15 +02:00
José Valim d7946202bf Fix Mix suite with async_run and await_run 2021-04-09 00:11:45 +02:00
José Valim 9cfa855237 Support explicit ExUnit.run 2021-04-08 23:01:10 +02:00
José Valim 381991149c Explicitly mention relative and absolute URIs, closes #10884 2021-04-08 08:17:28 +02:00
Michał Łępicki bd38b6ed4c Fix grammar in Logger backends docs (#10883) 2021-04-08 08:17:28 +02:00
José Valim b571ddb3e0 Update Logger backend recommendations 2021-04-07 19:36:09 +02:00
José Valim 877b3d929b Only try to inspect git! failures if response is a binary 2021-04-07 19:15:25 +02:00
José Valim 7e2b22402c Do not ignore unimplemented function headers from used modules 2021-04-07 18:52:47 +02:00
José Valim 3df04b23f9 Temporarily defdelegate and defexception inside protocols 2021-04-05 10:17:16 +02:00
Wojtek Mach 33feac639a Mix.install/2: Allow calling with the same dependencies and don't generate .app file (#10875) 2021-04-04 20:19:09 +02:00
Wojtek Mach 8c4bed23e6 Use docs canonical version in all built-in apps (#10872)
Before:

https://hexdocs.pm/elixir/1.12.0-rc.0/changelog.html contains links like:

  - [`Mix.install/2`](https://hexdocs.pm/mix/Mix.html#install/2)

which currently 404.

After:

https://hexdocs.pm/elixir/1.12.0-rc.0/changelog.html would contain:

  - [`Mix.install/2`](https://hexdocs.pm/mix/1.12/Mix.html#install/2)

See demo: http://wojtekmach.pl/docs/elixir/1.12/elixir/changelog.html
2021-04-04 09:56:18 +02:00
Wojtek Mach b9c374e9bb Change docs canonical version (#10871)
We unfortunately had a discrepancy between what the docs said was the
canonical version and what was the actual URL:

    % curl --silent https://hexdocs.pm/elixir/1.12/Kernel.html | grep 'rel="canonical"'
          <link rel="canonical" href="https://hexdocs.pm/elixir/v1.12/Kernel.html" />
    % curl --silent https://hexdocs.pm/elixir/1.11/Kernel.html | grep 'rel="canonical"'
          <link rel="canonical" href="https://hexdocs.pm/elixir/v1.11/Kernel.html" />
    % curl --silent https://hexdocs.pm/elixir/1.10/Kernel.html | grep 'rel="canonical"'
          <link rel="canonical" href="https://hexdocs.pm/elixir/v1.10/Kernel.html" />

Notice `elixir/1.12` vs `elixir/v1.12`. The latter 404s!

This seems the easiest way to fix it.

Alternatively, we can handle it on hexdocs/bob side, move the docs to
the correct URL and add redirects. That would probably be more effort
but then again we wouldn't have to re-apply this same patch on all the
`v1.*` branches.
2021-04-04 08:34:06 +02:00
Eksperimental c045969850 Use first..start notation for ranges in CHANGELOG (#10870) 2021-04-03 23:28:20 +02:00
Enrico Rivarola 56e01f151b Sync unicode data to Unicode 13.0.0 (#10866) 2021-04-03 17:49:48 +02:00
Eksperimental 171caface8 Update Unicode upgrade instructions (#10862) 2021-04-03 17:49:48 +02:00
Eksperimental b2a04575c3 Update Unicode to version 13.0.0 (#10861) 2021-04-03 17:48:38 +02:00
José Valim 5ce4ede684 Add note about OTP 21 2021-04-03 16:39:45 +02:00
José Valim 31d2b99879 Release v1.12.0-rc.0 2021-04-03 15:32:28 +02:00
Michał Szajbe b49bac34d4 Pass xref's compile args to compile task (#10852) 2021-04-03 15:30:11 +02:00
José Valim 5b3ef7705e Update CHANGELOG 2021-04-03 15:27:09 +02:00
José Valim 64fca3cdb1 Clarifications to Calendar.ISO 2021-04-03 15:02:42 +02:00
José Valim 415d4647c4 Remove invalid escaping of sigils, closes #10864 2021-04-02 23:14:38 +02:00
Eksperimental 91344a24a8 Format source code with new rules 2021-04-01 09:48:05 +02:00
Eksperimental 5fbdee2714 Quote range operator atom
This commit has only the actual changes
Add tests for quoted range operator
2021-04-01 09:48:05 +02:00
Eksperimental 832fbce136 Fix grammar in Range docs (#10851)
- Use "with a step of X"
- Replace usage of "start" and "stop" with "first" and "last"
2021-03-30 18:51:06 +02:00
José Valim c45d9ab13d Do not discard blamed stacktrace from exception in exit in ExUnit formatter 2021-03-30 16:16:31 +02:00
Wojtek Mach 94096055ad Update compatibility-and-deprecations.md (#10846) 2021-03-30 15:02:27 +02:00
José Valim 02e9b898c4 More range copyedit 2021-03-30 14:44:50 +02:00
Eksperimental 1c01996c29 Copyedit Range specs and docs (#10845) 2021-03-30 14:44:50 +02:00
Eksperimental 103db3a2ef Simplify specs in Range by introducing t:limit/0 (#10844) 2021-03-30 14:26:40 +02:00
José Valim 6f95bf274f Use types were appropriate in Range 2021-03-30 14:14:10 +02:00
Kelvin Stinghen 7210ab2fbd Keeping underscore between digits on Macro.camelize/1 (#10843)
Closes #10839
2021-03-30 13:42:45 +02:00
Eksperimental 174b77150e Use one-based var names in Types (#10824)
In the same fashion as generated arguments 30373382ec
2021-03-30 13:42:41 +02:00
José Valim 1dd09cb0bc Document ranges structs are read-only 2021-03-30 12:02:32 +02:00
José Valim 203cb4bb6f Add Registry.values/3 2021-03-30 11:43:50 +02:00
Łukasz Jan Niemier 8ff5c76b9c Set correct value returned by get_fun/2 callback (#10842)
By looking at source of `Access.all/0` it seems that returned value by
this function is `container()` instead of tuple `{val, container()}`.
2021-03-30 11:08:44 +02:00
José Valim 51de0e09a7 Add line numbers of first expression to lists 2021-03-30 11:08:44 +02:00
José Valim 9b38e4ed07 Remove Range.empty?/1 2021-03-30 09:22:33 +02:00
Eksperimental 2d40ad09d1 Simplify Range's step error message (#10835) 2021-03-29 23:34:55 +02:00
Eksperimental 00d1bc6765 Update range definition (#10834)
Ranges are no longer exclusively a consecutive sequence of integers.
2021-03-29 23:34:51 +02:00
Eksperimental 544466a4d1 Fix t:Range.t/2 (#10833)
We need to be explicit and define the step field, otherwise IEx and ExDoc will spec it as "term()"

    (1)> t Range.t/2
    @type t(first, last) :: %Range{first: first, last: last, step: term()
2021-03-29 22:35:48 +02:00
José Valim 385d2cd54a Prepare v1.12 for release 2021-03-29 17:44:50 +02:00
129 changed files with 5979 additions and 2105 deletions
+4 -3
View File
@@ -12,20 +12,21 @@ test_template: &DEFAULT_TEST_SETTINGS
test_freebsd_task:
<<: *DEFAULT_TEST_SETTINGS
name: FreeBSD 12.2
name: FreeBSD 13.0
alias: FreeBSD Stable
freebsd_instance:
image_family: freebsd-12-2
image_family: freebsd-13-0
cpu: 8
memory: 7424Mi
env:
CHECK_REPRODUCIBLE: true
LC_ALL: en_US.UTF-8
PATH: $PATH:/usr/local/lib/erlang22/bin
install_script:
- pkg install -y erlang git gmake
- pkg install -y erlang-runtime22 git gmake
- rm -rf .git
- gmake compile
+87
View File
@@ -0,0 +1,87 @@
name: builds.hex.pm
on:
push:
branches:
- main
- v*.*
tags:
- v*
env:
ELIXIR_OPTS: "--warnings-as-errors"
ERLC_OPTS: "warnings_as_errors"
LANG: C.UTF-8
concurrency: builds_txt
jobs:
release_pre_built:
strategy:
fail-fast: true
max-parallel: 1
matrix:
include:
- otp: 23
otp_version: '23.3'
build_docs: build_docs
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 50
- name: Get tags
run: git fetch --tags origin
- uses: ./.github/workflows/release_pre_built
with:
otp_version: ${{ matrix.otp_version }}
otp: ${{ matrix.otp }}
build_docs: ${{ matrix.build_docs }}
- name: Utils.sh
run: |
cat << 'EOF' > utils.sh
function purge_key() {
curl \
-X POST \
-H "Fastly-Key: ${FASTLY_KEY}" \
-H "Accept: application/json" \
-H "Content-Length: 0" \
"https://api.fastly.com/service/$1/purge/$2"
}
function purge() {
purge_key ${FASTLY_REPO_SERVICE_ID} $1
purge_key ${FASTLY_BUILDS_SERVICE_ID} $1
sleep 2
purge_key ${FASTLY_REPO_SERVICE_ID} $1
purge_key ${FASTLY_BUILDS_SERVICE_ID} $1
sleep 2
purge_key ${FASTLY_REPO_SERVICE_ID} $1
purge_key ${FASTLY_BUILDS_SERVICE_ID} $1
}
EOF
chmod +x utils.sh
- name: Upload Docs to S3
if: ${{ matrix.build_docs }}
env:
AWS_ACCESS_KEY_ID: ${{ secrets.HEX_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.HEX_AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.HEX_AWS_REGION }}
AWS_S3_BUCKET: ${{ secrets.HEX_AWS_S3_BUCKET }}
FASTLY_REPO_SERVICE_ID: ${{ secrets.HEX_FASTLY_REPO_SERVICE_ID }}
FASTLY_BUILDS_SERVICE_ID: ${{ secrets.HEX_FASTLY_BUILDS_SERVICE_ID }}
FASTLY_KEY: ${{ secrets.HEX_FASTLY_KEY }}
run: |
source utils.sh
version=$(echo ${{ github.ref_name }} | sed -e 's/^v//g')
for f in doc/*; do
if [ -d "$f" ]; then
app=`echo $f | sed s/"doc\/"//`
tarball="${app}-${version}.tar.gz"
surrogate_key="docs/${app}-${version}"
tar -czf "${tarball}" -C "doc/${app}" .
aws s3 cp "${tarball}" "s3://${{ env.AWS_S3_BUCKET }}/docs/${tarball}" \
--cache-control "public,max-age=3600" \
--metadata "{\"surrogate-key\":\"${surrogate_key}\",\"surrogate-control\":\"public,max-age=604800\"}"
purge "${surrogate_key}"
fi
done
+5 -3
View File
@@ -15,7 +15,7 @@ jobs:
strategy:
fail-fast: false
matrix:
otp_release: ['OTP-23.0', 'OTP-22.3', 'OTP-22.0', 'OTP-21.3.8', 'OTP-21.0']
otp_release: ['OTP-24.0', 'OTP-23.3', 'OTP-23.0', 'OTP-22.3', 'OTP-22.0']
development: [false]
include:
- otp_release: master
@@ -51,7 +51,7 @@ jobs:
run: make test_elixir
- name: Check reproducible builds
run: taskset 1 make check_reproducible
if: matrix.otp_release == 'OTP-23.0'
if: matrix.otp_release == 'OTP-24.0'
test_windows:
name: Windows, OTP-${{ matrix.otp_release }}, Windows Server 2019
@@ -83,7 +83,9 @@ jobs:
- name: Erlang test suite
run: make --keep-going test_erlang
- name: Elixir test suite
run: make --keep-going test_elixir
run: |
del c:/Windows/System32/drivers/etc/hosts
make --keep-going test_elixir
check_posix_compliant:
name: Check POSIX-compliant
@@ -0,0 +1,51 @@
name: "Release pre built"
description: "Builds elixir release, ExDoc and generates docs"
inputs:
otp:
description: "The major OTP version"
otp_version:
description: "The exact OTP version (major.minor[.patch])"
build_docs:
description: "If docs have to be built or not"
runs:
using: "composite"
steps:
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ inputs.otp_version }}
version-type: strict
- name: Build Elixir Release
shell: bash
run: |
make Precompiled.zip
mv Precompiled.zip elixir-otp-${{ inputs.otp }}.zip
shasum -a 1 elixir-otp-${{ inputs.otp }}.zip > elixir-otp-${{ inputs.otp }}.zip.sha1sum
shasum -a 256 elixir-otp-${{ inputs.otp }}.zip > elixir-otp-${{ inputs.otp }}.zip.sha256sum
echo "$PWD/bin" >> $GITHUB_PATH
- name: Get latest stable ExDoc version
if: ${{ inputs.build_docs }}
shell: bash
run: |
EX_DOC_LATEST_STABLE_VERSION=$(curl -s https://hex.pm/api/packages/ex_doc | jq --raw-output '.latest_stable_version')
echo "EX_DOC_LATEST_STABLE_VERSION=${EX_DOC_LATEST_STABLE_VERSION}" >> $GITHUB_ENV
- uses: actions/checkout@v3
if: ${{ inputs.build_docs }}
with:
repository: elixir-lang/ex_doc
ref: v${{ env.EX_DOC_LATEST_STABLE_VERSION }}
path: ex_doc
- name: Build ex_doc
if: ${{ inputs.build_docs }}
shell: bash
run: |
mv ex_doc ../ex_doc
cd ../ex_doc
../elixir/bin/mix do local.rebar --force, local.hex --force, deps.get, compile
cd ../elixir
- name: Build Docs
if: ${{ inputs.build_docs }}
shell: bash
run: |
make Docs.zip
shasum -a 1 Docs.zip > Docs.zip.sha1sum
shasum -a 256 Docs.zip > Docs.zip.sha256sum
+97 -11
View File
@@ -1,6 +1,8 @@
# Changelog for Elixir v1.12
Elixir v1.12 is out with improvements to scripting, tighter Erlang/OTP 24 integration, stepped ranges, and dozen of new functions across the standard library. Overall this is a small release, which continues our tradition of bringing Elixir developers quality of live improvements every 6 months.
Elixir v1.12 is out with improvements to scripting, tighter Erlang/OTP 24 integration, stepped ranges, and dozen of new functions across the standard library. Overall this is a small release, which continues our tradition of bringing Elixir developers quality of life improvements every 6 months.
Elixir v1.12 requires Erlang/OTP 22+. We also recommend running `mix local.rebar` after installation to upgrade to the latest Rebar versions, which includes support for Erlang OTP/24+.
## Scripting improvements: `Mix.install/2` and `System.trap_signal/3`
@@ -72,21 +74,81 @@ iex(3)> :ets.insert(ets, :should_be_a_tuple)
(stdlib 3.15) :ets.insert(#Reference<0.105641012.1058144260.76455>, :should_be_a_tuple)
```
Finally, note Rebar v2 no longer works on Erlang/OTP 24+. Mix defaults to Rebar v3 since v1.4, so no changes should be necessary by the huge majority of developers. However, if you are explicitly setting `manager: :rebar` in your dependency, you want to move to Rebar v3 by removing the `:manager` option. Support for unsupported Rebar versions will be removed from Mix in the future.
## Stepped ranges
Elixir has support for ranges from before its v1.0 release. Ranges support only integers and are inclusive, using the mathematic notation `a..b`. Ranges in Elixir are either increasing `1..10` or decreasing `10..1` and the direction of the range was always inferred from the starting and stop positions. Ranges are always lazy as its values are emitted as they are enumerated rather than being computed upfront.
Elixir has support for ranges from before its v1.0 release. Ranges support only integers and are inclusive, using the mathematic notation `a..b`. Ranges in Elixir are either increasing `1..10` or decreasing `10..1` and the direction of the range was always inferred from the first and last positions. Ranges are always lazy as its values are emitted as they are enumerated rather than being computed upfront.
Unfortunately, due to this inference, it is not possible to have empty ranges. For example, if you want to create a list of `n` elements, you can express it with a range from `1..n`, as `1..0` is a decreasing range with two elements.
Unfortunately, due to this inference, it is not possible to have empty ranges. For example, if you want to create a list of `n` elements, you cannot express it with a range from `1..n`, as `1..0` (for `n=0`) is a decreasing range with two elements.
Elixir v1.12 supports stepped ranges via the `first..last//step` notation. For example: `1..10//2` will emit the numbers `1`, `3`, `5`, `7`, and `9`. You can consider the `//` operator to perform "range division", as it effectively divides and rounds up the number of elements in the range by `step`. Steps can be either positive (increasing ranges) or negative (decreasing ranges). Stepped ranges bring more expressive power to Elixir ranges and they elegantly solve the empty range problem, as they allow the direction of the steps to be explicitly declared instead of inferred.
Elixir v1.12 supports stepped ranges via the `first..last//step` notation. For example: `1..10//2` will emit the numbers `1`, `3`, `5`, `7`, and `9`. You can consider the `//` operator as an equivalent to "range division", as it effectively divides the number of elements in the range by `step`, rounding up on inexact scenarios. Steps can be either positive (increasing ranges) or negative (decreasing ranges). Stepped ranges bring more expressive power to Elixir ranges and they elegantly solve the empty range problem, as they allow the direction of the steps to be explicitly declared instead of inferred.
As of Elixir v1.12, implicitly decreasing ranges are soft-deprecated and warnings will be emitted in future Elixir versions based on our [deprecation policy](https://hexdocs.pm/elixir/compatibility-and-deprecations.html#deprecations).
## Additional functions
Elixir v1.12 has the additional of many functions across the standard library. The `Enum` module received additions such as `Enum.count_until/2`, `Enum.product/1`, `Enum.zip_with/2`, and more. The `Integer` module now includes `Integer.pow/2` and `Integer.extended_gcd/2`. The `Range` module now deals with stepped ranges and includes new convenience functions such as `Range.empty?/1` and `Range.size/1`. Finally, the `Kernel` module got two new functions, `Kernel.then/2` and `Kernel.tap/2`, which are specially useful in `|>` pipelines.
Elixir v1.12 has the additional of many functions across the standard library. The `Enum` module received additions such as `Enum.count_until/2`, `Enum.product/1`, `Enum.zip_with/2`, and more. The `Integer` module now includes `Integer.pow/2` and `Integer.extended_gcd/2`. Finally, the `Kernel` module got two new functions, `Kernel.then/2` and `Kernel.tap/2`, which are specially useful in `|>` pipelines.
## v1.12.0-dev
## v1.12.3 (2021-09-05)
### 1. Bug fixes
#### Elixir
* [Code] Make sure that bindings in the default context returned by `Code.eval_*` functions are not returned as tagged tuples
* [Kernel] Do not crash when handling ambiguity errors
* [Range] Still match on old range patterns throughout the stdlib
#### IEx
* [IEx.Autocomplete] Do not error autocompletion with module attribute
#### Mix
* [Mix] Rename inconsistent `:exit_code` option to `:exit_status` on `Mix.raise/2`
## v1.12.2 (2021-07-01)
### 1. Bug fixes
#### Elixir
* [Kernel] Ensure deprecated macros emit warnings
#### Mix
* [mix deps] Ensure unconstrained rebar deps generate valid mix specifications
### 2. Enhancements
#### Elixir
* [elixirc] Change the output of `--profile time` to make it easier to detect outliers
* [Application] Do not add compile time deps on args to `Application.compile_env/2` and `Application.compile_env!/2`
* [Enum] Optimize `Enum.into/3` and `Map.new/2`
#### Mix
* [mix compile] Compile most recently changed files first
* [mix compile, mix run, mix test] Speed up the time taken to load dependencies. This should make the usage of Mix inside projects quite more responsive
## v1.12.1 (2021-05-28)
### 1. Bug fixes
#### Elixir
* [Code] Make sure `Code.format_string!/2` formats multiline expression inside interpolation on the first run
* [Macro] Revert keeping of underscores between digits in camelize
#### Mix
* [Mix] Make sure `Mix.install/2` expand paths for deps
* [mix deps.get] Silence false positives on `httpc` warnings
* [mix test] Do not run the whole suite when there are no --failed tests as it won't behave as expected inside umbrellas
## v1.12.0 (2021-05-19)
### 1. Enhancements
@@ -97,7 +159,9 @@ Elixir v1.12 has the additional of many functions across the standard library. T
#### Elixir
* [Code] Add `Code.cursor_context/2` to return the context of a code snippet
* [Code] Do not add newlines around interpolation on code formatting. Note this means formatted code that has interpolation after the line length on Elixir v1.12 won't be considered as formatted on earlier Elixir versions
* [Code] Do not add brackets when keywords is used in the access syntax
* [Calendar] Support basic datetime format in `Calendar.ISO` parsing functions
* [Code] Improve evaluation performance on systems running on Erlang/OTP 24+
* [Date] Support steps via `Date.range/3`
@@ -109,8 +173,9 @@ Elixir v1.12 has the additional of many functions across the standard library. T
* [Exception] Show `error_info` data for exceptions coming from Erlang
* [Float] Add `Float.pow/2`
* [Integer] Add `Integer.pow/2` and `Integer.extended_gcd/2`
* [IO] Add `IO.stream/0` and `IO.binstream/0` which default to STDIO with line orientation
* [List] Add default value for `List.first/1` and `List.last/1`
* [Kernel] Add `start..stop//step` as support for stepped ranges
* [Kernel] Add `first..last//step` as support for stepped ranges
* [Kernel] Also warn for literal structs on `min/2` and `max/2`
* [Kernel] Add `Kernel.tap/2` and `Kernel.then/2`
* [Kernel] Do not add runtime dependencies to remotes in typespecs
@@ -123,12 +188,16 @@ Elixir v1.12 has the additional of many functions across the standard library. T
* [Module] Add `Module.get_definition/2` and `Module.delete_definition/2`
* [Module] Allow `@on_load` to be a private function
* [Module] Validate `@dialyzer` related module attributes
* [Range] Add `Range.new/3`, `Range.empty?/1`, and `Range.size/1`
* [Module] Add `Module.reserved_attributes/0` to list all reserved attributes by the language
* [Range] Add `Range.new/3` and `Range.size/1`
* [Regex] Add offset option to `Regex.scan/3` and `Regex.run/3`
* [Registry] Support `:compression` on `Registry` tables
* [Registry] Support `Registry.values/3` for reading values under a given key-pid pair
* [Stream] Add `Stream.zip_with/2` and `Stream.zip_with/3`
* [String] Add `:turkic` mode option to String case functions
* [String] Update to Unicode 13.0
* [System] Add `System.trap_signal/3` and `System.untrap_signal/2`
* [System] Add `System.shell/2` to invoke a command that is interpreted by the shell
* [Tuple] Add `Tuple.sum/1` and `Tuple.product/1`
* [URI] Support RFC3986 compliant encoding and decoding of queries via the `:rfc3986` option
@@ -139,6 +208,7 @@ Elixir v1.12 has the additional of many functions across the standard library. T
* [ExUnit] Print how much time is spent on `async` vs `sync` tests
* [ExUnit] Improve error messages for doctests
* [ExUnit] Compile doctests faster (often by two times)
* [ExUnit] Add `ExUnit.async_run/0` and `ExUnit.await_run/1`
#### IEx
@@ -157,6 +227,7 @@ Elixir v1.12 has the additional of many functions across the standard library. T
* [mix release] Add `RELEASE_PROG` to releases with the name of the executable starting the release
* [mix release] Support `remote.vm.args` to customize how the connecting VM boots
* [mix test] Run all available tests if there are no pending `--failed` tests. This provides a better workflow as you no longer need to toggle the `--failed` flag between runs
* [mix test] Support `mix test --warnings-as-errors`, treating warnings as errors and returning a non-zero exit status (only applies to test files, not compilation)
### 2. Bug fixes
@@ -169,11 +240,17 @@ Elixir v1.12 has the additional of many functions across the standard library. T
* [Kernel] Public functions without documentation now appear as an empty map on `Code.fetch_docs/1`, unless they start with underscore, where they remain as `:none`. This aligns Elixir's implementation with EEP48
* [Kernel] Do not crash when complex literals (binaries and maps) are used in guards
* [Kernel] Properly parse keywords (such as `end`) followed by the `::` operator
* [Kernel] Do not ignore unimplemented signatures from generated functions
* [Kernel] Improve error message when an expression follows a keyword list without brackets
* [Macro] `Macro.decompose_call/1` now also consider tuples with more than 2 elements to not be valid calls
* [Macro] Fix `Macro.underscore/1` for digit preceded by capitals: "FOO10" now becomes "foo10" instead of "fo_o10"
* [Macro] Fix `Macro.to_string/1` double-escaping of escape characters in sigils
* [Macro] Fix `Macro.underscore/1` on digits preceded by capitals: "FOO10" now becomes "foo10" instead of "fo_o10"
* [Macro] Preserve underscores between digits on `Macro.underscore/1`
* [OptionParser] Properly parse when numbers follow-up aliases, for example, `-ab3` is now parsed as `-a -b 3`
* [Path] Fix `Path.relative_to/2` when referencing self
* [Path] Do not crash when a volume is given to `Path.absname/1`, such as "c:"
* [Task] Ensure `Task.async_stream/2` with `ordered: false` discard results as they are emitted, instead of needlessly accumulating inside the stream manager
* [Task] Raise if `:max_concurrency` is set to 0 on streaming operations
* [URI] Do not discard empty paths on `URI.merge/2`
#### ExUnit
@@ -194,13 +271,14 @@ Elixir v1.12 has the additional of many functions across the standard library. T
* [mix test] Ensure protocols within the current project are consolidated when `--cover` is given
* [mix release] Improve compliance of release scripts with stripped down Linux installations
* [mix release] Preserve file mode when copying non-beam ebin files
* [mix xref] Ensure args are passed to the underlying `mix compile` call
### 3. Soft-deprecations (no warnings emitted)
#### Elixir
* [Kernel] Using `start..stop` to match on ranges is soft-deprecated and will warn on future Elixir versions. Use `start..stop//step` instead
* [Kernel] Using `start..stop` to create decreasing ranges is soft-deprecated and will warn on future versions. Use `start..stop//-1` instead
* [Kernel] Using `first..last` to match on ranges is soft-deprecated and will warn on future Elixir versions. Use `first..last//step` instead
* [Kernel] Using `first..last` to create decreasing ranges is soft-deprecated and will warn on future versions. Use `first..last//-1` instead
### 4. Hard-deprecations
@@ -218,6 +296,14 @@ Elixir v1.12 has the additional of many functions across the standard library. T
* [mix compile] The `:xref` compiler is deprecated and it has no effect. Please remove it from your mix.exs file.
### 5. Backwards incompatible changes
A backward incompatible change was found on Elixir v1.12.0 after the release. This was not planned and it is documented below:
#### ExUnit
* [ExUnit.Formatter] `{:suite_finished, load_time, run_time}` message has been updated to `{:suite_finished, %{load: load_time, run: run_time, async: async_time}}`
## v1.11
The CHANGELOG for v1.11 releases can be found [in the v1.11 branch](https://github.com/elixir-lang/elixir/blob/v1.11/CHANGELOG.md).
+28 -20
View File
@@ -2,7 +2,7 @@ PREFIX ?= /usr/local
TEST_FILES ?= "*_test.exs"
SHARE_PREFIX ?= $(PREFIX)/share
MAN_PREFIX ?= $(SHARE_PREFIX)/man
#CANONICAL := vMAJOR.MINOR/
CANONICAL := 1.12/
CANONICAL ?= master/
ELIXIRC := bin/elixirc --ignore-module-conflict $(ELIXIRC_OPTS)
ERLC := erlc -I lib/elixir/include
@@ -28,9 +28,9 @@ SOURCE_DATE_EPOCH_FILE = $(SOURCE_DATE_EPOCH_PATH)/SOURCE_DATE_EPOCH
#==> Functions
define CHECK_ERLANG_RELEASE
erl -noshell -eval '{V,_} = string:to_integer(erlang:system_info(otp_release)), io:fwrite("~s", [is_integer(V) and (V >= 21)])' -s erlang halt | grep -q '^true'; \
erl -noshell -eval '{V,_} = string:to_integer(erlang:system_info(otp_release)), io:fwrite("~s", [is_integer(V) and (V >= 22)])' -s erlang halt | grep -q '^true'; \
if [ $$? != 0 ]; then \
echo "At least Erlang/OTP 21.0 is required to build Elixir"; \
echo "At least Erlang/OTP 22.0 is required to build Elixir"; \
exit 1; \
fi
endef
@@ -179,40 +179,48 @@ clean_residual_files:
LOGO_PATH = $(shell test -f ../docs/logo.png && echo "--logo ../docs/logo.png")
SOURCE_REF = $(shell tag="$(call GIT_TAG)" revision="$(call GIT_REVISION)"; echo "$${tag:-$$revision}")
DOCS_FORMAT = html
COMPILE_DOCS = bin/elixir ../ex_doc/bin/ex_doc "$(1)" "$(VERSION)" "lib/$(2)/ebin" --main "$(3)" --source-url "https://github.com/elixir-lang/elixir" --source-ref "$(call SOURCE_REF)" $(call LOGO_PATH) --output doc/$(2) --canonical "https://hexdocs.pm/$(2)/$(CANONICAL)" --homepage-url "https://elixir-lang.org/docs.html" --formatter "$(DOCS_FORMAT)" $(4)
DOCS_COMPILE = CANONICAL=$(CANONICAL) bin/elixir ../ex_doc/bin/ex_doc "$(1)" "$(VERSION)" "lib/$(2)/ebin" --main "$(3)" --source-url "https://github.com/elixir-lang/elixir" --source-ref "$(call SOURCE_REF)" $(call LOGO_PATH) --output doc/$(2) --canonical "https://hexdocs.pm/$(2)/$(CANONICAL)" --homepage-url "https://elixir-lang.org/docs.html" --formatter "$(DOCS_FORMAT)" $(4)
DOCS_CONFIG = bin/elixir lib/elixir/scripts/docs_config.exs "$(1)"
docs: compile ../ex_doc/bin/ex_doc docs_elixir docs_eex docs_mix docs_iex docs_ex_unit docs_logger
docs_elixir: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (elixir)"
$(Q) rm -rf doc/elixir
$(call COMPILE_DOCS,Elixir,elixir,Kernel,--config "lib/elixir/docs.exs")
$(call DOCS_COMPILE,Elixir,elixir,Kernel,--config "lib/elixir/scripts/elixir_docs.exs")
$(call DOCS_CONFIG,elixir)
docs_eex: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (eex)"
$(Q) rm -rf doc/eex
$(call COMPILE_DOCS,EEx,eex,EEx)
$(call DOCS_COMPILE,EEx,eex,EEx,--config "lib/elixir/scripts/mix_docs.exs")
$(call DOCS_CONFIG,eex)
docs_mix: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (mix)"
$(Q) rm -rf doc/mix
$(call COMPILE_DOCS,Mix,mix,Mix)
$(call DOCS_COMPILE,Mix,mix,Mix,--config "lib/elixir/scripts/mix_docs.exs")
$(call DOCS_CONFIG,mix)
docs_iex: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (iex)"
$(Q) rm -rf doc/iex
$(call COMPILE_DOCS,IEx,iex,IEx)
$(call DOCS_COMPILE,IEx,iex,IEx,--config "lib/elixir/scripts/mix_docs.exs")
$(call DOCS_CONFIG,iex)
docs_ex_unit: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (ex_unit)"
$(Q) rm -rf doc/ex_unit
$(call COMPILE_DOCS,ExUnit,ex_unit,ExUnit)
$(call DOCS_COMPILE,ExUnit,ex_unit,ExUnit,--config "lib/elixir/scripts/mix_docs.exs")
$(call DOCS_CONFIG,ex_unit)
docs_logger: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (logger)"
$(Q) rm -rf doc/logger
$(call COMPILE_DOCS,Logger,logger,Logger)
$(call DOCS_COMPILE,Logger,logger,Logger,--config "lib/elixir/scripts/mix_docs.exs")
$(call DOCS_CONFIG,logger)
../ex_doc/bin/ex_doc:
@ echo "ex_doc is not found in ../ex_doc as expected. See README for more information."
@@ -221,23 +229,23 @@ docs_logger: compile ../ex_doc/bin/ex_doc
#==> Zip tasks
Docs.zip: docs
rm -f Docs-v$(VERSION).zip
zip -9 -r Docs-v$(VERSION).zip CHANGELOG.md doc NOTICE LICENSE README.md
@ echo "Docs file created $(CURDIR)/Docs-v$(VERSION).zip"
rm -f Docs.zip
zip -9 -r Docs.zip CHANGELOG.md doc NOTICE LICENSE README.md
@ echo "Docs file created $(CURDIR)/Docs.zip"
Precompiled.zip: build_man compile
rm -f Precompiled-v$(VERSION).zip
zip -9 -r Precompiled-v$(VERSION).zip bin CHANGELOG.md lib/*/ebin lib/*/lib LICENSE man NOTICE README.md VERSION
@ echo "Precompiled file created $(CURDIR)/Precompiled-v$(VERSION).zip"
rm -f Precompiled.zip
zip -9 -r Precompiled.zip bin CHANGELOG.md lib/*/ebin lib/*/lib LICENSE man NOTICE README.md VERSION
@ echo "Precompiled file created $(CURDIR)/Precompiled.zip"
zips: Precompiled.zip Docs.zip
@ echo ""
@ echo "### Checksums"
@ echo ""
@ shasum -a 1 < Precompiled-v$(VERSION).zip | sed -e "s/-//" | xargs echo " * Precompiled.zip SHA1:"
@ shasum -a 512 < Precompiled-v$(VERSION).zip | sed -e "s/-//" | xargs echo " * Precompiled.zip SHA512:"
@ shasum -a 1 < Docs-v$(VERSION).zip | sed -e "s/-//" | xargs echo " * Docs.zip SHA1:"
@ shasum -a 512 < Docs-v$(VERSION).zip | sed -e "s/-//" | xargs echo " * Docs.zip SHA512:"
@ shasum -a 1 < Precompiled.zip | sed -e "s/-//" | xargs echo " * Precompiled.zip SHA1:"
@ shasum -a 512 < Precompiled.zip | sed -e "s/-//" | xargs echo " * Precompiled.zip SHA512:"
@ shasum -a 1 < Docs.zip | sed -e "s/-//" | xargs echo " * Docs.zip SHA1:"
@ shasum -a 512 < Docs.zip | sed -e "s/-//" | xargs echo " * Docs.zip SHA512:"
@ echo ""
#==> Test tasks
+2 -2
View File
@@ -48,10 +48,10 @@ If Elixir fails to build (specifically when pulling in a new version via
If tests pass, you can use Interactive Elixir by running `bin/iex` in your terminal.
However, if tests fail, it is likely that you have an outdated Erlang/OTP version
(Elixir requires Erlang/OTP 21.0 or later). You can check your Erlang/OTP version
(Elixir requires Erlang/OTP 22.0 or later). You can check your Erlang/OTP version
by calling `erl` in the command line. You will see some information similar to:
Erlang/OTP 21 [erts-9.0] [smp:2:2] [async-threads:10] [kernel-poll:false]
Erlang/OTP 22 [erts-9.0] [smp:2:2] [async-threads:10] [kernel-poll:false]
If you have properly set up your dependencies and tests still fail,
you may want to open up a bug report, as explained next.
+2 -2
View File
@@ -6,8 +6,8 @@ Elixir applies bug fixes only to the latest minor branch. Security patches are a
| Elixir version | Support
| -------------- | ------------------------------
| 1.12 | Development
| 1.11 | Bug fixes and security patches
| 1.12 | Bug fixes and security patches
| 1.11 | Security patches only
| 1.10 | Security patches only
| 1.9 | Security patches only
| 1.8 | Security patches only
+1 -1
View File
@@ -1 +1 @@
1.12.0-dev
1.12.3
+1 -1
View File
@@ -14,7 +14,7 @@ Usage: $(basename "$0") [elixir switches] [compiler switches] [.ex files]
--no-docs Does not attach documentation to compiled modules
--profile time Profile the time to compile modules
--verbose Prints compilation status
--warnings-as-errors Treats warnings as errors and return non-zero exit code
--warnings-as-errors Treats warnings as errors and return non-zero exit status
Options given after -- are passed down to the executed code.
Options can be passed to the Erlang runtime using \$ELIXIR_ERL_OPTIONS.
+1 -1
View File
@@ -23,7 +23,7 @@ echo --no-debug-info Does not attach debug info to compiled modules
echo --no-docs Does not attach documentation to compiled modules
echo --profile time Profile the time to compile modules
echo --verbose Prints compilation status
echo --warnings-as-errors Treats warnings as errors and returns non-zero exit code
echo --warnings-as-errors Treats warnings as errors and returns non-zero exit status
echo.
echo ** Options given after -- are passed down to the executed code
echo ** Options can be passed to the Erlang runtime using ELIXIR_ERL_OPTIONS
+3 -4
View File
@@ -99,16 +99,15 @@ defmodule Access do
@type key :: any
@type value :: any
@type get_fun(data, current_value) ::
(:get, data, (term -> term) ->
{current_value, new_data :: container})
@type get_fun(data) ::
(:get, data, (term -> term) -> new_data :: container)
@type get_and_update_fun(data, current_value) ::
(:get_and_update, data, (term -> term) ->
{current_value, new_data :: container} | :pop)
@type access_fun(data, current_value) ::
get_fun(data, current_value) | get_and_update_fun(data, current_value)
get_fun(data) | get_and_update_fun(data, current_value)
@doc """
Invoked in order to access the value stored under `key` in the given term `term`.
+15 -19
View File
@@ -507,11 +507,22 @@ defmodule Application do
raise "Application.compile_env/3 cannot be called inside functions, only in the module body"
end
key_or_path = expand_key_or_path(key_or_path, __CALLER__)
quote do
Application.__compile_env__(unquote(app), unquote(key_or_path), unquote(default), __ENV__)
end
end
defp expand_key_or_path({:__aliases__, _, _} = alias, env),
do: Macro.expand(alias, %{env | function: {:__info__, 1}})
defp expand_key_or_path(list, env) when is_list(list),
do: Enum.map(list, &expand_key_or_path(&1, env))
defp expand_key_or_path(other, _env),
do: other
@doc false
def __compile_env__(app, key_or_path, default, env) do
case fetch_compile_env(app, key_or_path, env) do
@@ -533,6 +544,8 @@ defmodule Application do
raise "Application.compile_env!/2 cannot be called inside functions, only in the module body"
end
key_or_path = expand_key_or_path(key_or_path, __CALLER__)
quote do
Application.__compile_env__!(unquote(app), unquote(key_or_path), __ENV__)
end
@@ -694,9 +707,6 @@ defmodule Application do
:application.set_env(app, key, value, opts)
end
# TODO: Remove this once we support Erlang/OTP 22+ exclusively.
@compile {:no_warn_undefined, {:application, :set_env, 2}}
@doc """
Puts the environment for multiple apps at the same time.
@@ -705,28 +715,14 @@ defmodule Application do
* have the same application listed more than once
* have the same key inside the same application listed more than once
If those conditions are not met, the behaviour is undefined
(on Erlang/OTP 21 and earlier) or will raise (on Erlang/OTP 22
and later).
If those conditions are not met, it will raise.
It receives the same options as `put_env/4`. Returns `:ok`.
"""
@doc since: "1.9.0"
@spec put_all_env([{app, [{key, value}]}], timeout: timeout, persistent: boolean) :: :ok
def put_all_env(config, opts \\ []) when is_list(config) and is_list(opts) do
# TODO: Remove function exported? check when we require Erlang/OTP 22+
if function_exported?(:application, :set_env, 2) do
:application.set_env(config, opts)
else
for app_keyword <- config,
{app, keyword} = app_keyword,
key_value <- keyword,
{key, value} = key_value do
:application.set_env(app, key, value, opts)
end
:ok
end
:application.set_env(config, opts)
end
@doc """
+4 -4
View File
@@ -92,7 +92,7 @@ defmodule Date do
def range(%{calendar: calendar} = first, %{calendar: calendar} = last) do
{first_days, _} = to_iso_days(first)
{last_days, _} = to_iso_days(last)
# TODO: Deprecate inferring a range with step of -1 on Elixir v1.16
# TODO: Deprecate inferring a range with a step of -1 on Elixir v1.16
step = if first_days <= last_days, do: 1, else: -1
range(first, first_days, last, last_days, calendar, step)
end
@@ -102,7 +102,7 @@ defmodule Date do
end
@doc """
Returns a range of dates with step.
Returns a range of dates with a step.
## Examples
@@ -133,8 +133,8 @@ defmodule Date do
step
) do
raise ArgumentError,
"both dates must have matching calendar and the step must be an integer " <>
"different than zero, got: #{inspect(first)}, #{inspect(last)}, #{step}"
"both dates must have matching calendar and the step must be a " <>
"non-zero integer, got: #{inspect(first)}, #{inspect(last)}, #{step}"
end
defp range(first, first_days, last, last_days, calendar, step) do
+84 -24
View File
@@ -26,13 +26,15 @@ defmodule Date.Range do
defstruct [:first, :last, :first_in_iso_days, :last_in_iso_days, :step]
defimpl Enumerable do
def member?(%{first: %{calendar: calendar}} = range, %Date{calendar: calendar} = date) do
%{
first_in_iso_days: first_days,
last_in_iso_days: last_days,
step: step
} = range
def member?(
%Date.Range{
first: %{calendar: calendar},
first_in_iso_days: first_days,
last_in_iso_days: last_days,
step: step
} = range,
%Date{calendar: calendar} = date
) do
{days, _} = Date.to_iso_days(date)
cond do
@@ -47,24 +49,43 @@ defmodule Date.Range do
end
end
def member?(_, _) do
def member?(%Date.Range{step: _}, _) do
{:ok, false}
end
# TODO: Remove me on v2.0
def member?(
%{__struct__: Date.Range, first_in_iso_days: first_days, last_in_iso_days: last_days} =
date_range,
date
) do
step = if first_days <= last_days, do: 1, else: -1
member?(Map.put(date_range, :step, step), date)
end
def count(range) do
{:ok, size(range)}
end
def slice(range) do
%{
first_in_iso_days: first,
first: %{calendar: calendar},
step: step
} = range
def slice(
%Date.Range{
first_in_iso_days: first,
first: %{calendar: calendar},
step: step
} = range
) do
{:ok, size(range), &slice(first + &1 * step, step, &2, calendar)}
end
# TODO: Remove me on v2.0
def slice(
%{__struct__: Date.Range, first_in_iso_days: first_days, last_in_iso_days: last_days} =
date_range
) do
step = if first_days <= last_days, do: 1, else: -1
slice(Map.put(date_range, :step, step))
end
defp slice(current, _step, 1, calendar) do
[date_from_iso_days(current, calendar)]
end
@@ -76,17 +97,30 @@ defmodule Date.Range do
]
end
def reduce(range, acc, fun) do
%{
first_in_iso_days: first_days,
last_in_iso_days: last_days,
first: %{calendar: calendar},
step: step
} = range
def reduce(
%Date.Range{
first_in_iso_days: first_days,
last_in_iso_days: last_days,
first: %{calendar: calendar},
step: step
},
acc,
fun
) do
reduce(first_days, last_days, acc, fun, step, calendar)
end
# TODO: Remove me on v2.0
def reduce(
%{__struct__: Date.Range, first_in_iso_days: first_days, last_in_iso_days: last_days} =
date_range,
acc,
fun
) do
step = if first_days <= last_days, do: 1, else: -1
reduce(Map.put(date_range, :step, step), acc, fun)
end
defp reduce(_first_days, _last_days, {:halt, acc}, _fun, _step, _calendar) do
{:halted, acc}
end
@@ -135,6 +169,15 @@ defmodule Date.Range do
defp size(%Date.Range{first_in_iso_days: first_days, last_in_iso_days: last_days, step: step}),
do: abs(div(last_days - first_days, step)) + 1
# TODO: Remove me on v2.0
defp size(
%{__struct__: Date.Range, first_in_iso_days: first_days, last_in_iso_days: last_days} =
date_range
) do
step = if first_days <= last_days, do: 1, else: -1
size(Map.put(date_range, :step, step))
end
defp empty?(%Date.Range{
first_in_iso_days: first_days,
last_in_iso_days: last_days,
@@ -151,10 +194,21 @@ defmodule Date.Range do
when step < 0 and first_days < last_days,
do: true
defp empty?(%Date.Range{}), do: false
defp empty?(%Date.Range{step: _}), do: false
# TODO: Remove me on v2.0
defp empty?(
%{__struct__: Date.Range, first_in_iso_days: first_days, last_in_iso_days: last_days} =
date_range
) do
step = if first_days <= last_days, do: 1, else: -1
empty?(Map.put(date_range, :step, step))
end
end
defimpl Inspect do
import Kernel, except: [inspect: 2]
def inspect(%Date.Range{first: first, last: last, step: 1}, _) do
"#DateRange<" <> inspect(first) <> ", " <> inspect(last) <> ">"
end
@@ -162,5 +216,11 @@ defmodule Date.Range do
def inspect(%Date.Range{first: first, last: last, step: step}, _) do
"#DateRange<" <> inspect(first) <> ", " <> inspect(last) <> ", #{step}>"
end
# TODO: Remove me on v2.0
def inspect(%{__struct__: Date.Range, first: first, last: last} = date_range, opts) do
step = if first <= last, do: 1, else: -1
inspect(Map.put(date_range, :step, step), opts)
end
end
end
+38 -40
View File
@@ -11,60 +11,40 @@ defmodule Calendar.ISO do
## ISO 8601 compliance
The ISO 8601 specification is feature-rich, but allows applications
to selectively implement most parts of it. The choices Elixir makes here
to selectively implement most parts of it. The choices Elixir makes
are catalogued below.
### Additions
ISO 8601 does not allow a whitespace instead of `T` as a separator
between date and times, both when parsing and formatting.
This is a common enough representation, Elixir allows it during parsing.
The formatting of dates in `NaiveDateTime.to_iso8601/1` and `DateTime.to_iso8601/1`
do produce specification-compliant string representations using the `T` separator.
#### Examples
iex> Calendar.ISO.parse_naive_datetime("2015-01-23 23:50:07.0123456")
{:ok, {2015, 1, 23, 23, 50, 7, {12345, 6}}}
iex> Calendar.ISO.parse_naive_datetime("2015-01-23T23:50:07.0123456")
{:ok, {2015, 1, 23, 23, 50, 7, {12345, 6}}}
iex> Calendar.ISO.parse_utc_datetime("2015-01-23 23:50:07.0123456Z")
{:ok, {2015, 1, 23, 23, 50, 7, {12345, 6}}, 0}
iex> Calendar.ISO.parse_utc_datetime("2015-01-23T23:50:07.0123456Z")
{:ok, {2015, 1, 23, 23, 50, 7, {12345, 6}}, 0}
### Features
The standard library supports a minimal set of possible ISO 8601 features.
Specifically, the parser only supports calendar dates, and defaults to
only parsing extended-formatted date/times.
Specifically, the parser only supports calendar dates and does not support
ordinal and week formats.
By default Elixir only parses extended-formatted date/times. You can opt-in
to parse basic-formatted date/times.
You can ask to parse only basic-formatted date/times instead, or both.
`NaiveDateTime.to_iso8601/2` and `DateTime.to_iso8601/2` allow you to produce
either basic or extended formatted strings, and `Calendar.strftime/2` allows
you to format datetimes however else you desire.
Other optional ISO 8601 features; such as ordinal dates, week dates, and reduced
precision (except for milliseconds); are not supported by the parser or formatters.
No functions exist to parse ISO 8601 durations or time intervals.
Elixir does not support reduced accuracy formats (for example, a date without
the day component) nor decimal precisions in the lowest component (such as
`10:01:25,5`). No functions exist to parse ISO 8601 durations or time intervals.
#### Examples
Only the extended format is supported in parsing; the basic format is not.
Elixir expects the extended format by default when parsing:
iex> Calendar.ISO.parse_naive_datetime("2015-01-23 23:50:07")
iex> Calendar.ISO.parse_naive_datetime("2015-01-23T23:50:07")
{:ok, {2015, 1, 23, 23, 50, 7, {0, 0}}}
iex> Calendar.ISO.parse_naive_datetime("20150123 235007")
iex> Calendar.ISO.parse_naive_datetime("20150123T235007")
{:error, :invalid_format}
Parsing can be restricted to basic or extend formats.
Parsing can be restricted to basic if desired:
iex> Calendar.ISO.parse_naive_datetime("20150123 235007Z", :basic)
iex> Calendar.ISO.parse_naive_datetime("20150123T235007Z", :basic)
{:ok, {2015, 1, 23, 23, 50, 7, {0, 0}}}
iex> Calendar.ISO.parse_naive_datetime("20150123 235007Z", :extended)
iex> Calendar.ISO.parse_naive_datetime("20150123T235007Z", :extended)
{:error, :invalid_format}
Only calendar dates are supported in parsing; ordinal and week dates are not.
@@ -78,8 +58,7 @@ defmodule Calendar.ISO do
iex> Calendar.ISO.parse_date("2015-W016-3")
{:error, :invalid_format}
Reduced precision is supported for only milliseconds;
years, months, days, hours, minutes, and seconds must be fully specified.
Years, months, days, hours, minutes, and seconds must be fully specified:
iex> Calendar.ISO.parse_date("2015-04-15")
{:ok, {2015, 4, 15}}
@@ -122,6 +101,27 @@ defmodule Calendar.ISO do
iex> Calendar.ISO.parse_utc_datetime("+2015-01-23 23:50:07Z")
{:ok, {2015, 1, 23, 23, 50, 7, {0, 0}}, 0}
### Additions
ISO 8601 does not allow a whitespace instead of `T` as a separator
between date and times, both when parsing and formatting.
This is a common enough representation, Elixir allows it during parsing.
The formatting of dates in `NaiveDateTime.to_iso8601/1` and `DateTime.to_iso8601/1`
do produce specification-compliant string representations using the `T` separator.
#### Examples
iex> Calendar.ISO.parse_naive_datetime("2015-01-23 23:50:07.0123456")
{:ok, {2015, 1, 23, 23, 50, 7, {12345, 6}}}
iex> Calendar.ISO.parse_naive_datetime("2015-01-23T23:50:07.0123456")
{:ok, {2015, 1, 23, 23, 50, 7, {12345, 6}}}
iex> Calendar.ISO.parse_utc_datetime("2015-01-23 23:50:07.0123456Z")
{:ok, {2015, 1, 23, 23, 50, 7, {12345, 6}}, 0}
iex> Calendar.ISO.parse_utc_datetime("2015-01-23T23:50:07.0123456Z")
{:ok, {2015, 1, 23, 23, 50, 7, {12345, 6}}, 0}
"""
@behaviour Calendar
@@ -1288,9 +1288,7 @@ defmodule Calendar.ISO do
@doc """
Determines if the date given is valid according to the proleptic Gregorian calendar.
Note that while ISO 8601 allows times to specify 24:00:00 as the
zero hour of the next day, this notation is not supported by Elixir.
Leap seconds are not supported as well by the built-in Calendar.ISO.
Leap seconds are not supported by the built-in Calendar.ISO.
## Examples
+256 -2
View File
@@ -38,8 +38,8 @@ defmodule Code do
are loaded as needed. In embedded mode the opposite happens, as all
modules need to be loaded upfront or explicitly.
You can use `ensure_loaded/1` (as well as `ensure_lodead?/1` and
`ensure_lodead!/1`) to check if a module is loaded before using it and
You can use `ensure_loaded/1` (as well as `ensure_loaded?/1` and
`ensure_loaded!/1`) to check if a module is loaded before using it and
act.
## `ensure_compiled/1` and `ensure_compiled!/1`
@@ -206,6 +206,259 @@ defmodule Code do
required_files()
end
@doc """
Receives a string and returns the cursor context.
This function receives a string with incomplete Elixir code,
representing a cursor position, and based on the string, it
provides contextual information about said position. The
return of this function can then be used to provide tips,
suggestions, and autocompletion functionality.
This function provides a best-effort detection and may not be
accurate under certain circumstances. See the "Limitations"
section below.
Consider adding a catch-all clause when handling the return
type of this function as new cursor information may be added
in future releases.
## Examples
iex> Code.cursor_context("")
:expr
iex> Code.cursor_context("hello_wor")
{:local_or_var, 'hello_wor'}
## Return values
* `{:alias, charlist}` - the context is an alias, potentially
a nested one, such as `Hello.Wor` or `HelloWor`
* `{:dot, inside_dot, charlist}` - the context is a dot
where `inside_dot` is either a `{:var, charlist}`, `{:alias, charlist}`,
`{:module_attribute, charlist}`, `{:unquoted_atom, charlist}` or a `dot`
itself. If a var is given, this may either be a remote call or a map
field access. Examples are `Hello.wor`, `:hello.wor`, `hello.wor`,
`Hello.nested.wor`, `hello.nested.wor`, and `@hello.world`
* `{:dot_arity, inside_dot, charlist}` - the context is a dot arity
where `inside_dot` is either a `{:var, charlist}`, `{:alias, charlist}`,
`{:module_attribute, charlist}`, `{:unquoted_atom, charlist}` or a `dot`
itself. If a var is given, it must be a remote arity. Examples are
`Hello.world/`, `:hello.world/`, `hello.world/2`, and `@hello.world/2`
* `{:dot_call, inside_dot, charlist}` - the context is a dot
call. This means parentheses or space have been added after the expression.
where `inside_dot` is either a `{:var, charlist}`, `{:alias, charlist}`,
`{:module_attribute, charlist}`, `{:unquoted_atom, charlist}` or a `dot`
itself. If a var is given, it must be a remote call. Examples are
`Hello.world(`, `:hello.world(`, `Hello.world `, `hello.world(`, `hello.world `,
and `@hello.world(`
* `:expr` - may be any expression. Autocompletion may suggest an alias,
local or var
* `{:local_or_var, charlist}` - the context is a variable or a local
(import or local) call, such as `hello_wor`
* `{:local_arity, charlist}` - the context is a local (import or local)
call, such as `hello_world/`
* `{:local_call, charlist}` - the context is a local (import or local)
call, such as `hello_world(` and `hello_world `
* `{:module_attribute, charlist}` - the context is a module attribute, such
as `@hello_wor`
* `:none` - no context possible
* `:unquoted_atom` - the context is an unquoted atom. This can be either
previous atoms or all available `:erlang` modules
## Limitations
* There is no context for operators
* The current algorithm only considers the last line of the input
* Context does not yet track strings, sigils, etc.
* Arguments of functions calls are not currently recognized
"""
@doc since: "1.12.0"
@spec cursor_context(List.Chars.t(), keyword()) ::
{:alias, charlist}
| {:dot, inside_dot, charlist}
| {:dot_arity, inside_dot, charlist}
| {:dot_call, inside_dot, charlist}
| :expr
| {:local_or_var, charlist}
| {:local_arity, charlist}
| {:local_call, charlist}
| {:module_attribute, charlist}
| :none
| {:unquoted_atom, charlist}
when inside_dot:
{:alias, charlist}
| {:dot, inside_dot, charlist}
| {:module_attribute, charlist}
| {:unquoted_atom, charlist}
| {:var, charlist}
def cursor_context(string, opts \\ [])
def cursor_context(binary, opts) when is_binary(binary) and is_list(opts) do
binary =
case :binary.matches(binary, "\n") do
[] ->
binary
matches ->
{position, _} = List.last(matches)
binary_part(binary, position + 1, byte_size(binary) - position - 1)
end
do_cursor_context(String.to_charlist(binary), opts)
end
def cursor_context(charlist, opts) when is_list(charlist) and is_list(opts) do
chunked = Enum.chunk_by(charlist, &(&1 == ?\n))
case List.last(chunked, []) do
[?\n | _] -> do_cursor_context([], opts)
rest -> do_cursor_context(rest, opts)
end
end
def cursor_context(other, opts) do
cursor_context(to_charlist(other), opts)
end
@operators '\\<>+-*/:=|&~^@%'
@non_closing_punctuation '.,([{;'
@closing_punctuation ')]}'
@space '\t\s'
@closing_identifier '?!'
@operators_and_non_closing_puctuation @operators ++ @non_closing_punctuation
@non_identifier @closing_identifier ++
@operators ++ @non_closing_punctuation ++ @closing_punctuation ++ @space
defp do_cursor_context(list, _opts) do
reverse = Enum.reverse(list)
case strip_spaces(reverse, 0) do
# It is empty
{[], _} ->
:expr
{[?: | _], 0} ->
{:unquoted_atom, ''}
{[?@ | _], 0} ->
{:module_attribute, ''}
{[?. | rest], _} ->
dot(rest, '')
# It is a local or remote call with parens
{[?( | rest], _} ->
call_to_cursor_context(rest)
# A local arity definition
{[?/ | rest], _} ->
case identifier_to_cursor_context(rest) do
{:local_or_var, acc} -> {:local_arity, acc}
{:dot, base, acc} -> {:dot_arity, base, acc}
_ -> :none
end
# Starting a new expression
{[h | _], _} when h in @operators_and_non_closing_puctuation ->
:expr
# It is a local or remote call without parens
{rest, spaces} when spaces > 0 ->
call_to_cursor_context(rest)
# It is an identifier
_ ->
identifier_to_cursor_context(reverse)
end
end
defp strip_spaces([h | rest], count) when h in @space, do: strip_spaces(rest, count + 1)
defp strip_spaces(rest, count), do: {rest, count}
defp call_to_cursor_context(reverse) do
case identifier_to_cursor_context(reverse) do
{:local_or_var, acc} -> {:local_call, acc}
{:dot, base, acc} -> {:dot_call, base, acc}
_ -> :none
end
end
defp identifier_to_cursor_context(reverse) do
case identifier(reverse) do
# Parse :: first to avoid ambiguity with atoms
{:alias, false, '::' ++ _, _} -> :none
{kind, _, '::' ++ _, acc} -> alias_or_local_or_var(kind, acc)
# Now handle atoms, any other atom is unexpected
{_kind, _, ':' ++ _, acc} -> {:unquoted_atom, acc}
{:atom, _, _, _} -> :none
# Parse .. first to avoid ambiguity with dots
{:alias, false, _, _} -> :none
{kind, _, '..' ++ _, acc} -> alias_or_local_or_var(kind, acc)
# Module attributes
{:alias, _, '@' ++ _, _} -> :none
{:identifier, _, '@' ++ _, acc} -> {:module_attribute, acc}
# Everything else
{:alias, _, '.' ++ rest, acc} -> nested_alias(rest, acc)
{:identifier, _, '.' ++ rest, acc} -> dot(rest, acc)
{kind, _, _, acc} -> alias_or_local_or_var(kind, acc)
:none -> :none
end
end
defp nested_alias(rest, acc) do
case identifier_to_cursor_context(rest) do
{:alias, prev} -> {:alias, prev ++ '.' ++ acc}
_ -> :none
end
end
defp dot(rest, acc) do
case identifier_to_cursor_context(rest) do
{:local_or_var, prev} -> {:dot, {:var, prev}, acc}
{:unquoted_atom, _} = prev -> {:dot, prev, acc}
{:alias, _} = prev -> {:dot, prev, acc}
{:dot, _, _} = prev -> {:dot, prev, acc}
{:module_attribute, _} = prev -> {:dot, prev, acc}
_ -> :none
end
end
defp alias_or_local_or_var(:alias, acc), do: {:alias, acc}
defp alias_or_local_or_var(:identifier, acc), do: {:local_or_var, acc}
defp alias_or_local_or_var(_, _), do: :none
defp identifier([?? | rest]), do: check_identifier(rest, [??])
defp identifier([?! | rest]), do: check_identifier(rest, [?!])
defp identifier(rest), do: check_identifier(rest, [])
defp check_identifier([h | _], _acc) when h in @non_identifier, do: :none
defp check_identifier(rest, acc), do: rest_identifier(rest, acc)
defp rest_identifier([h | rest], acc) when h not in @non_identifier do
rest_identifier(rest, [h | acc])
end
defp rest_identifier(rest, acc) do
case String.Tokenizer.tokenize(acc) do
{kind, _, [], _, ascii_only?, _} -> {kind, ascii_only?, rest, acc}
_ -> :none
end
end
@doc """
Removes files from the required files list.
@@ -1297,6 +1550,7 @@ defmodule Code do
@doc """
Same as `ensure_loaded/1` but raises if the module cannot be loaded.
"""
@doc since: "1.12.0"
@spec ensure_loaded!(module) :: module
def ensure_loaded!(module) do
case ensure_loaded(module) do
+50 -30
View File
@@ -13,7 +13,7 @@ defmodule Code.Formatter do
@ampersand_prec Code.Identifier.unary_op(:&) |> elem(1)
# Operators that are composed of multiple binary operators
@multi_binary_operators [:..//]
@multi_binary_operators [:"..//"]
# Operators that do not have space between operands
@no_space_binary_operators [:.., :"//"]
@@ -257,6 +257,7 @@ defmodule Code.Formatter do
force_do_end_blocks: force_do_end_blocks,
locals_without_parens: locals_without_parens,
operand_nesting: 2,
skip_eol: false,
comments: comments
}
end
@@ -393,10 +394,17 @@ defmodule Code.Formatter do
end
# foo[bar]
defp quoted_to_algebra({{:., _, [Access, :get]}, meta, [target | args]}, _context, state) do
defp quoted_to_algebra({{:., _, [Access, :get]}, meta, [target, arg]}, _context, state) do
{target_doc, state} = remote_target_to_algebra(target, state)
{call_doc, state} = list_to_algebra(meta, args, state)
{concat(target_doc, call_doc), state}
{access_doc, state} =
if keyword?(arg) do
list_to_algebra(meta, arg, state)
else
list_to_algebra(meta, [arg], state)
end
{concat(target_doc, access_doc), state}
end
# %Foo{}
@@ -516,12 +524,12 @@ defmodule Code.Formatter do
end
# 1..2//3
defp quoted_to_algebra({:..//, meta, [left, middle, right]}, context, state) do
defp quoted_to_algebra({:"..//", meta, [left, middle, right]}, context, state) do
quoted_to_algebra({:"//", meta, [{:.., meta, [left, middle]}, right]}, context, state)
end
defp quoted_to_algebra({:fn, meta, [_ | _] = clauses}, _context, state) do
anon_fun_to_algebra(clauses, line(meta), closing_line(meta), state, eol?(meta))
anon_fun_to_algebra(clauses, line(meta), closing_line(meta), state, eol?(meta, state))
end
defp quoted_to_algebra({fun, meta, args}, context, state) when is_atom(fun) and is_list(args) do
@@ -553,6 +561,10 @@ defmodule Code.Formatter do
if keyword_key?(left_arg) do
{left, state} =
case left_arg do
# TODO: Remove this clause in v1.16 when we no longer quote operator :..//
{:__block__, _, [:"..//"]} ->
{string(~S{"..//":}), state}
{:__block__, _, [atom]} when is_atom(atom) ->
key =
case Code.Identifier.classify(atom) do
@@ -766,7 +778,7 @@ defmodule Code.Formatter do
concat(concat(group(left), op_string), group(right))
true ->
eol? = eol?(meta)
eol? = eol?(meta, state)
next_break_fits? =
op in @next_break_fits_operators and next_break_fits?(right_arg, state) and not eol?
@@ -908,7 +920,7 @@ defmodule Code.Formatter do
{docs, comments?, state} =
quoted_to_algebra_with_comments(operands, acc, min_line, max_line, state, fun)
if comments? or eol?(meta) do
if comments? or eol?(meta, state) do
{docs |> Enum.reduce(&line(&2, &1)) |> force_unfit(), state}
else
{docs |> Enum.reduce(&glue(&2, &1)), state}
@@ -1144,7 +1156,7 @@ defmodule Code.Formatter do
end
args = if keyword?, do: left ++ right, else: left ++ [right]
many_eol? = match?([_, _ | _], args) and eol?(meta)
many_eol? = match?([_, _ | _], args) and eol?(meta, state)
no_generators? = no_generators?(args)
to_algebra_fun = &quoted_to_algebra(&1, context, &2)
@@ -1335,8 +1347,7 @@ defmodule Code.Formatter do
defp list_interpolation_to_algebra([entry | entries], escape, state, acc, last) do
{{:., _, [Kernel, :to_string]}, _meta, [quoted]} = entry
{doc, state} = block_to_algebra(quoted, @max_line, @min_line, state)
doc = surround("\#{", doc, "}") |> interpolation_to_string()
{doc, state} = interpolation_to_string(quoted, state)
list_interpolation_to_algebra(entries, escape, state, concat(acc, doc), last)
end
@@ -1352,8 +1363,7 @@ defmodule Code.Formatter do
defp interpolation_to_algebra([entry | entries], escape, state, acc, last) do
{:"::", _, [{{:., _, [Kernel, :to_string]}, _meta, [quoted]}, {:binary, _, _}]} = entry
{doc, state} = block_to_algebra(quoted, @max_line, @min_line, state)
doc = surround("\#{", doc, "}") |> interpolation_to_string()
{doc, state} = interpolation_to_string(quoted, state)
interpolation_to_algebra(entries, escape, state, concat(acc, doc), last)
end
@@ -1361,6 +1371,12 @@ defmodule Code.Formatter do
{concat(acc, last), state}
end
defp interpolation_to_string(quoted, %{skip_eol: skip_eol} = state) do
{doc, state} = block_to_algebra(quoted, @max_line, @min_line, %{state | skip_eol: true})
doc = interpolation_to_string(surround("\#{", doc, "}"))
{doc, %{state | skip_eol: skip_eol}}
end
defp interpolation_to_string(doc) do
[head | tail] =
doc
@@ -1410,7 +1426,7 @@ defmodule Code.Formatter do
defp bitstring_to_algebra(meta, args, state) do
last = length(args) - 1
join = if eol?(meta), do: :line, else: :flex_break
join = if eol?(meta, state), do: :line, else: :flex_break
to_algebra_fun = &bitstring_segment_to_algebra(&1, &2, last)
{args_doc, join, state} =
@@ -1478,7 +1494,7 @@ defmodule Code.Formatter do
## Literals
defp list_to_algebra(meta, args, state) do
join = if eol?(meta), do: :line, else: :break
join = if eol?(meta, state), do: :line, else: :break
fun = &quoted_to_algebra(&1, :parens_arg, &2)
{args_doc, _join, state} =
@@ -1488,7 +1504,7 @@ defmodule Code.Formatter do
end
defp map_to_algebra(meta, name_doc, [{:|, _, [left, right]}], state) do
join = if eol?(meta), do: :line, else: :break
join = if eol?(meta, state), do: :line, else: :break
fun = &quoted_to_algebra(&1, :parens_arg, &2)
{left_doc, state} = fun.(left, state)
@@ -1505,7 +1521,7 @@ defmodule Code.Formatter do
end
defp map_to_algebra(meta, name_doc, args, state) do
join = if eol?(meta), do: :line, else: :break
join = if eol?(meta, state), do: :line, else: :break
fun = &quoted_to_algebra(&1, :parens_arg, &2)
{args_doc, _join, state} =
@@ -1516,7 +1532,7 @@ defmodule Code.Formatter do
end
defp tuple_to_algebra(meta, args, join, state) do
join = if eol?(meta), do: :line, else: join
join = if eol?(meta, state), do: :line, else: join
fun = &quoted_to_algebra(&1, :parens_arg, &2)
{args_doc, join, state} =
@@ -1533,6 +1549,11 @@ defmodule Code.Formatter do
Atom.to_string(atom)
end
# TODO: Remove this clause in v1.16 when we no longer quote operator :..//
defp atom_to_algebra(:"..//") do
string(":\"..//\"")
end
defp atom_to_algebra(atom) do
string = Atom.to_string(atom)
@@ -1693,7 +1714,7 @@ defmodule Code.Formatter do
|> glue(body_doc)
|> nest(2)
|> glue("end")
|> maybe_force_clauses(clauses)
|> maybe_force_clauses(clauses, state)
|> group()
{doc, state}
@@ -1727,7 +1748,7 @@ defmodule Code.Formatter do
|> glue(body_doc)
|> nest(2)
|> glue("end")
|> maybe_force_clauses(clauses)
|> maybe_force_clauses(clauses, state)
|> group()
{doc, state}
@@ -1755,7 +1776,7 @@ defmodule Code.Formatter do
"(() -> "
|> concat(nest(body_doc, :cursor))
|> concat(")")
|> maybe_force_clauses(clauses)
|> maybe_force_clauses(clauses, state)
|> group()
{doc, state}
@@ -1776,7 +1797,7 @@ defmodule Code.Formatter do
|> group()
|> concat(break() |> concat(body_doc) |> nest(2))
|> wrap_in_parens()
|> maybe_force_clauses(clauses)
|> maybe_force_clauses(clauses, state)
|> group()
{doc, state}
@@ -1795,8 +1816,8 @@ defmodule Code.Formatter do
## Clauses
defp maybe_force_clauses(doc, clauses) do
if Enum.any?(clauses, fn {:->, meta, _} -> eol?(meta) end) do
defp maybe_force_clauses(doc, clauses, state) do
if Enum.any?(clauses, fn {:->, meta, _} -> eol?(meta, state) end) do
force_unfit(doc)
else
doc
@@ -1819,7 +1840,7 @@ defmodule Code.Formatter do
{doc_acc, state_acc}
end)
{clauses_doc |> maybe_force_clauses([clause | clauses]) |> group(), state}
{clauses_doc |> maybe_force_clauses([clause | clauses], state) |> group(), state}
end
defp clauses_to_algebra(other, min_line, max_line, state) do
@@ -2160,8 +2181,8 @@ defmodule Code.Formatter do
false
end
defp eol_or_comments?(meta, %{comments: comments}) do
eol?(meta) or
defp eol_or_comments?(meta, %{comments: comments} = state) do
eol?(meta, state) or
(
min_line = line(meta)
max_line = closing_line(meta)
@@ -2248,9 +2269,8 @@ defmodule Code.Formatter do
defp keyword_key?(_),
do: false
defp eol?(meta) do
Keyword.get(meta, :newlines, 0) > 0
end
defp eol?(_meta, %{skip_eol: true}), do: false
defp eol?(meta, _state), do: Keyword.get(meta, :newlines, 0) > 0
defp meta?(meta, key) do
is_list(meta[key])
+1 -1
View File
@@ -83,7 +83,7 @@ defmodule Code.Identifier do
charlist = Atom.to_charlist(atom)
cond do
atom in [:%, :%{}, :{}, :<<>>, :..., :.., :., :..//, :->] ->
atom in [:%, :%{}, :{}, :<<>>, :..., :.., :., :"..//", :->] ->
:not_callable
atom in [:"::", :"//"] ->
+1 -1
View File
@@ -419,7 +419,7 @@ defmodule DynamicSupervisor do
@doc since: "1.6.0"
@spec which_children(Supervisor.supervisor()) :: [
# module() | :dynamic here because :supervisor.modules() is not exported
{:undefined, pid | :restarting, :worker | :supervisor, module() | :dynamic}
{:undefined, pid | :restarting, :worker | :supervisor, [module()] | :dynamic}
]
def which_children(supervisor) do
call(supervisor, :which_children)
+99 -47
View File
@@ -786,7 +786,7 @@ defmodule Enum do
def dedup(enumerable) do
Enum.reduce(enumerable, [], fn x, acc ->
case acc do
[^x, _] -> acc
[^x | _] -> acc
_ -> [x | acc]
end
end)
@@ -1421,28 +1421,35 @@ defmodule Enum do
into_protocol(enumerable, collectable)
end
def into(%{} = enumerable, %{} = collectable) do
Map.merge(collectable, enumerable)
end
def into(enumerable, %{} = collectable) when is_list(enumerable) do
Map.merge(collectable, :maps.from_list(enumerable))
end
def into(enumerable, %{} = collectable) do
reduce(enumerable, collectable, fn {key, val}, acc ->
Map.put(acc, key, val)
end)
if map_size(collectable) == 0 do
into_map(enumerable)
else
into_map(enumerable, collectable)
end
end
def into(enumerable, collectable) do
into_protocol(enumerable, collectable)
end
defp into_map(%{} = enumerable), do: enumerable
defp into_map(enumerable) when is_list(enumerable), do: :maps.from_list(enumerable)
defp into_map(enumerable), do: enumerable |> Enum.to_list() |> :maps.from_list()
defp into_map(%{} = enumerable, collectable),
do: Map.merge(collectable, enumerable)
defp into_map(enumerable, collectable) when is_list(enumerable),
do: Map.merge(collectable, :maps.from_list(enumerable))
defp into_map(enumerable, collectable),
do: Enum.reduce(enumerable, collectable, fn {key, val}, acc -> Map.put(acc, key, val) end)
defp into_protocol(enumerable, collectable) do
{initial, fun} = Collectable.into(collectable)
into(enumerable, initial, fun, fn entry, acc ->
into_protocol(enumerable, initial, fun, fn entry, acc ->
fun.(acc, {:cont, entry})
end)
end
@@ -1461,20 +1468,42 @@ defmodule Enum do
"""
@spec into(Enumerable.t(), Collectable.t(), (term -> term)) :: Collectable.t()
def into(enumerable, collectable, transform) when is_list(collectable) do
collectable ++ map(enumerable, transform)
end
def into(%_{} = enumerable, collectable, transform) do
into_protocol(enumerable, collectable, transform)
end
def into(enumerable, %_{} = collectable, transform) do
into_protocol(enumerable, collectable, transform)
end
def into(enumerable, %{} = collectable, transform) do
if map_size(collectable) == 0 do
enumerable |> Enum.map(transform) |> :maps.from_list()
else
Enum.reduce(enumerable, collectable, fn entry, acc ->
{key, val} = transform.(entry)
Map.put(acc, key, val)
end)
end
end
def into(enumerable, collectable, transform) do
into_protocol(enumerable, collectable, transform)
end
defp into_protocol(enumerable, collectable, transform) do
{initial, fun} = Collectable.into(collectable)
into(enumerable, initial, fun, fn entry, acc ->
into_protocol(enumerable, initial, fun, fn entry, acc ->
fun.(acc, {:cont, transform.(entry)})
end)
end
defp into(enumerable, initial, fun, callback) do
defp into_protocol(enumerable, initial, fun, callback) do
try do
reduce(enumerable, initial, callback)
catch
@@ -2026,11 +2055,13 @@ defmodule Enum do
def min_max(enumerable, empty_fallback \\ fn -> raise Enum.EmptyError end)
def min_max(first..last//step = range, empty_fallback) when is_function(empty_fallback, 0) do
if Range.empty?(range) do
empty_fallback.()
else
last = last - rem(last - first, step)
{Kernel.min(first, last), Kernel.max(first, last)}
case Range.size(range) do
0 ->
empty_fallback.()
_ ->
last = last - rem(last - first, step)
{Kernel.min(first, last), Kernel.max(first, last)}
end
end
@@ -2221,19 +2252,17 @@ defmodule Enum do
## Examples
The examples below use the `:exrop` pseudorandom algorithm since it's
the default from Erlang/OTP 20, however if you are using Erlang/OTP 22
or above then `:exsss` is the default algorithm. If you are using `:exsplus`,
then please update, as this algorithm is deprecated since Erlang/OTP 20.
The examples below use the `:exsss` pseudorandom algorithm since it's
the default from Erlang/OTP 22:
# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exrop, {101, 102, 103})
iex> Enum.random([1, 2, 3])
3
iex> :rand.seed(:exsss, {100, 101, 102})
iex> Enum.random([1, 2, 3])
2
iex> Enum.random([1, 2, 3])
1
iex> Enum.random(1..1_000)
846
309
"""
@spec random(t) :: element
@@ -2549,17 +2578,15 @@ defmodule Enum do
## Examples
The examples below use the `:exrop` pseudorandom algorithm since it's
the default from Erlang/OTP 20, however if you are using Erlang/OTP 22
or above then `:exsss` is the default algorithm. If you are using `:exsplus`,
then please update, as this algorithm is deprecated since Erlang/OTP 20.
The examples below use the `:exsss` pseudorandom algorithm since it's
the default from Erlang/OTP 22:
# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exrop, {1, 2, 3})
iex> :rand.seed(:exsss, {1, 2, 3})
iex> Enum.shuffle([1, 2, 3])
[3, 1, 2]
[3, 2, 1]
iex> Enum.shuffle([1, 2, 3])
[1, 3, 2]
[2, 1, 3]
"""
@spec shuffle(t) :: list
@@ -2634,6 +2661,12 @@ defmodule Enum do
end
end
# TODO: Remove me on v2.0
def slice(enumerable, %{__struct__: Range, first: first, last: last} = index_range) do
step = if first <= last, do: 1, else: -1
slice(enumerable, Map.put(index_range, :step, step))
end
defp slice_range(enumerable, first, last) when last >= first and last >= 0 and first >= 0 do
slice_any(enumerable, first, last - first + 1)
end
@@ -3146,11 +3179,11 @@ defmodule Enum do
## Examples
# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exrop, {1, 2, 3})
iex> :rand.seed(:exsss, {1, 2, 3})
iex> Enum.take_random(1..10, 2)
[7, 2]
[3, 1]
iex> Enum.take_random(?a..?z, 5)
'hypnt'
'mikel'
"""
@spec take_random(t, non_neg_integer) :: list
@@ -3354,6 +3387,15 @@ defmodule Enum do
"""
@spec unzip(t) :: {[element], [element]}
def unzip([_ | _] = list) do
:lists.reverse(list) |> unzip([], [])
end
def unzip([]) do
{[], []}
end
def unzip(enumerable) do
{list1, list2} =
reduce(enumerable, {[], []}, fn {el1, el2}, {list1, list2} ->
@@ -3363,6 +3405,14 @@ defmodule Enum do
{:lists.reverse(list1), :lists.reverse(list2)}
end
defp unzip([{el1, el2} | reversed_list], list1, list2) do
unzip(reversed_list, [el1 | list1], [el2 | list2])
end
defp unzip([], list1, list2) do
{list1, list2}
end
@doc """
Returns the `enumerable` with each element wrapped in a tuple
alongside its index.
@@ -3611,15 +3661,17 @@ defmodule Enum do
end
defp aggregate(first..last//step = range, fun, empty) do
if Range.empty?(range) do
empty.()
else
last = last - rem(last - first, step)
case Range.size(range) do
0 ->
empty.()
case fun.(first, last) do
true -> first
false -> last
end
_ ->
last = last - rem(last - first, step)
case fun.(first, last) do
true -> first
false -> last
end
end
end
+1 -1
View File
@@ -253,7 +253,7 @@ defmodule Exception do
defp rewrite_arg(arg) do
Macro.prewalk(arg, fn
{:%{}, meta, [__struct__: Range, first: first, last: last, step: step]} ->
{:..//, meta, [first, last, step]}
{:"..//", meta, [first, last, step]}
other ->
other
-12
View File
@@ -585,8 +585,6 @@ defmodule GenServer do
This callback is optional. If one is not implemented, the server will fail
if a continue instruction is used.
This callback is only supported on Erlang/OTP 21+.
"""
@callback handle_continue(continue :: term, state :: term) ::
{:noreply, new_state}
@@ -1038,18 +1036,8 @@ defmodule GenServer do
is unknown whether the destination `server` successfully
handled the message.
`c:handle_cast/2` will be called on the server to handle
the request. In case the `server` is on a node which is
not yet connected to the caller one, the semantics differ
depending on the used Erlang/OTP version.
`server` can be any of the values described in the "Name registration"
section of the documentation for this module.
Before Erlang/OTP 21, the call is going to block until a
connection happens. This was done to guarantee ordering.
Starting with Erlang/OTP 21, both Erlang and Elixir do
not block the call.
"""
@spec cast(server, term) :: :ok
def cast(server, request)
+11 -41
View File
@@ -318,12 +318,12 @@ defmodule Integer do
defp count_digits_nosign(<<_::bits>>, _, count), do: count
# TODO: Remove Integer.to_string/1 once the minimum supported version is
# Erlang/OTP 22, since it is covered by the now BIF Integer.to_string/2.
# Please reapply commit 2622fd6b0aa419a983a899a1fbdb5deefba3d85d.
@doc """
Returns a binary which corresponds to the text representation
of `integer`.
of `integer` in the given `base`.
`base` can be an integer between 2 and 36. If no `base` is given,
it defaults to `10`.
Inlined by the compiler.
@@ -341,22 +341,6 @@ defmodule Integer do
iex> Integer.to_string(0123)
"123"
"""
@spec to_string(integer) :: String.t()
def to_string(integer) do
:erlang.integer_to_binary(integer)
end
@doc """
Returns a binary which corresponds to the text representation
of `integer` in the given `base`.
`base` can be an integer between 2 and 36.
Inlined by the compiler.
## Examples
iex> Integer.to_string(100, 16)
"64"
@@ -368,15 +352,16 @@ defmodule Integer do
"""
@spec to_string(integer, 2..36) :: String.t()
def to_string(integer, base) do
def to_string(integer, base \\ 10) do
:erlang.integer_to_binary(integer, base)
end
# TODO: Remove Integer.to_charlist/1 once the minimum supported version is
# Erlang/OTP 22, since it is covered by the now BIF Integer.to_charlist/2.
# Please reapply commit 2622fd6b0aa419a983a899a1fbdb5deefba3d85d.
@doc """
Returns a charlist which corresponds to the text representation of the given `integer`.
Returns a charlist which corresponds to the text representation
of `integer` in the given `base`.
`base` can be an integer between 2 and 36. If no `base` is given,
it defaults to `10`.
Inlined by the compiler.
@@ -394,21 +379,6 @@ defmodule Integer do
iex> Integer.to_charlist(0123)
'123'
"""
@spec to_charlist(integer) :: charlist
def to_charlist(integer) do
:erlang.integer_to_list(integer)
end
@doc """
Returns a charlist which corresponds to the text representation of `integer` in the given `base`.
`base` can be an integer between 2 and 36.
Inlined by the compiler.
## Examples
iex> Integer.to_charlist(100, 16)
'64'
@@ -420,7 +390,7 @@ defmodule Integer do
"""
@spec to_charlist(integer, 2..36) :: charlist
def to_charlist(integer, base) do
def to_charlist(integer, base \\ 10) do
:erlang.integer_to_list(integer, base)
end
+30 -4
View File
@@ -508,6 +508,17 @@ defmodule IO do
:io.get_line(map_dev(device), to_chardata(prompt))
end
@doc """
Returns a line-based `IO.Stream` on `:stdio`.
This is equivalent to:
IO.stream(:stdio, :line)
"""
@doc since: "1.12.0"
def stream, do: stream(:stdio, :line)
@doc """
Converts the IO `device` into an `IO.Stream`.
@@ -524,6 +535,9 @@ defmodule IO do
Note that an IO stream has side effects and every time
you go over the stream you may get different results.
`stream/1` has been introduced in Elixir v1.12.0,
while `stream/2` has been available since v1.0.0.
## Examples
Here is an example on how we mimic an echo server
@@ -533,12 +547,23 @@ defmodule IO do
"""
@spec stream(device, :line | pos_integer) :: Enumerable.t()
def stream(device, line_or_codepoints)
def stream(device \\ :stdio, line_or_codepoints)
when line_or_codepoints == :line
when is_integer(line_or_codepoints) and line_or_codepoints > 0 do
IO.Stream.__build__(map_dev(device), false, line_or_codepoints)
end
@doc """
Returns a raw, line-based `IO.Stream` on `:stdio`. The operation is Unicode unsafe.
This is equivalent to:
IO.binstream(:stdio, :line)
"""
@doc since: "1.12.0"
def binstream, do: binstream(:stdio, :line)
@doc """
Converts the IO `device` into an `IO.Stream`. The operation is Unicode unsafe.
@@ -547,8 +572,7 @@ defmodule IO do
and write.
The `device` is iterated by the given number of bytes or line by line if
`:line` is given.
This reads from the IO device as a raw binary.
`:line` is given. This reads from the IO device as a raw binary.
Note that an IO stream has side effects and every time
you go over the stream you may get different results.
@@ -556,9 +580,11 @@ defmodule IO do
Finally, do not use this function on IO devices in Unicode
mode as it will return the wrong result.
`binstream/1` has been introduced in Elixir v1.12.0,
while `binstream/2` has been available since v1.0.0.
"""
@spec binstream(device, :line | pos_integer) :: Enumerable.t()
def binstream(device, line_or_bytes)
def binstream(device \\ :stdio, line_or_bytes)
when line_or_bytes == :line
when is_integer(line_or_bytes) and line_or_bytes > 0 do
IO.Stream.__build__(map_dev(device), true, line_or_bytes)
+7 -4
View File
@@ -3673,7 +3673,7 @@ defmodule Kernel do
end
defp range(_context, first, last) when is_integer(first) and is_integer(last) do
# TODO: Deprecate inferring a range with step of -1 on Elixir v1.17
# TODO: Deprecate inferring a range with a step of -1 on Elixir v1.17
step = if first <= last, do: 1, else: -1
{:%{}, [], [__struct__: Elixir.Range, first: first, last: last, step: step]}
end
@@ -3755,7 +3755,7 @@ defmodule Kernel do
defp validate_step!(step)
when is_float(step) or is_atom(step) or is_binary(step) or is_list(step) or step == 0 do
raise ArgumentError,
"ranges (first..last//step) expect the step to be an integer different than zero, " <>
"ranges (first..last//step) expect the step to be a non-zero integer, " <>
"got: #{Macro.to_string(step)}"
end
@@ -5554,7 +5554,7 @@ defmodule Kernel do
quote(do: List.to_charlist(unquote(unescape_list_tokens(pieces))))
end
@doc """
@doc ~S"""
Handles the sigil `~r` for regular expressions.
It returns a regular expression pattern, unescaping characters and replacing
@@ -5564,12 +5564,15 @@ defmodule Kernel do
## Examples
iex> Regex.match?(~r(foo), "foo")
iex> Regex.match?(~r/foo/, "foo")
true
iex> Regex.match?(~r/a#{:b}c/, "abc")
true
While the `~r` sigil allows parens and brackets to be used as delimiters,
it is preferred to use `"` or `/` to avoid escaping conflicts with reserved
regex characters.
"""
defmacro sigil_r(term, modifiers)
+18 -7
View File
@@ -398,7 +398,7 @@ defmodule Kernel.ParallelCompiler do
deadlocked =
deadlocked(waiting, :soft, false) ||
deadlocked(waiting, :soft, true) || deadlocked(waiting, :hard, false) ||
without_definition(waiting)
without_definition(waiting, files)
if deadlocked do
spawn_workers(deadlocked, spawned, waiting, files, result, warnings, state)
@@ -457,9 +457,13 @@ defmodule Kernel.ParallelCompiler do
defp each_cycle_return({kind, modules}), do: {kind, modules, []}
defp each_cycle_return(modules) when is_list(modules), do: {:compile, modules, []}
defp without_definition(waiting) do
# The goal of this function is to find leaves in the dependency graph,
# i.e. to find code that depends on code that we know is not being defined.
# Note that not all files have been compile yet, so they may not be in waiting.
defp without_definition(waiting, files) do
nillify_empty(
for {_, _, ref, on, _, _} <- waiting,
for %{pid: pid} <- files,
{_, ^pid, ref, on, _, _} <- List.wrap(List.keyfind(waiting, pid, 1)),
not defining?(on, waiting),
do: {ref, :not_found}
)
@@ -619,13 +623,13 @@ defmodule Kernel.ParallelCompiler do
data = maybe_warn_long_compilation(data, state)
if state.profile != :none do
compiling = System.convert_time_unit(data.compiling, :native, :millisecond)
waiting = System.convert_time_unit(data.waiting, :native, :millisecond)
extra = if waiting > 0, do: " (plus #{waiting}ms waiting)", else: ""
compiling = to_padded_ms(data.compiling)
waiting = to_padded_ms(data.waiting)
relative = Path.relative_to_cwd(data.file)
IO.puts(
:stderr,
"[profile] #{Path.relative_to_cwd(data.file)} compiled in #{compiling}ms" <> extra
"[profile] #{compiling}ms compiling + #{waiting}ms waiting for #{relative}"
)
end
@@ -636,6 +640,13 @@ defmodule Kernel.ParallelCompiler do
end)
end
defp to_padded_ms(time) do
time
|> System.convert_time_unit(:native, :millisecond)
|> Integer.to_string()
|> String.pad_leading(6, " ")
end
defp discard_down(pid) do
receive do
{:DOWN, _, :process, ^pid, _} -> :ok
+1 -1
View File
@@ -1416,7 +1416,7 @@ defmodule Kernel.SpecialForms do
The `IO` module provides streams, that are both `Enumerable` and
`Collectable`, here is an upcase echo server using comprehensions:
for line <- IO.stream(:stdio, :line), into: IO.stream(:stdio, :line) do
for line <- IO.stream(), into: IO.stream() do
String.upcase(line)
end
+5 -1
View File
@@ -1022,7 +1022,11 @@ defmodule Kernel.Typespec do
:elixir_errors.erl_warn(caller.line, caller.file, warning)
{_, :used_once} ->
compile_error(caller, "type variable #{name} is unused")
compile_error(
caller,
"type variable #{name} is used only once. Type variables in typespecs " <>
"must be referenced at least twice, otherwise it is equivalent to term()"
)
_ ->
:ok
+1 -3
View File
@@ -1087,8 +1087,6 @@ defmodule Macro do
"\#{" <> to_string(arg, fun) <> "}"
binary when is_binary(binary) ->
binary = inspect_no_limit(binary)
binary = binary_part(binary, 1, byte_size(binary) - 2)
escape_sigil(binary, left)
end)
@@ -1143,7 +1141,7 @@ defmodule Macro do
:error
end
defp op_call({:..//, _, [left, middle, right]} = ast, fun) do
defp op_call({:"..//", _, [left, middle, right]} = ast, fun) do
left = op_to_string(left, fun, :.., :left)
middle = op_to_string(middle, fun, :.., :right)
right = op_to_string(right, fun, :"//", :right)
+3
View File
@@ -105,7 +105,9 @@ defmodule Macro.Env do
vars: vars
}
# Define the __struct__ callbacks by hand for bootstrap reasons.
# TODO: Remove :vars field on v2.0
@doc false
def __struct__ do
%{
__struct__: __MODULE__,
@@ -130,6 +132,7 @@ defmodule Macro.Env do
}
end
@doc false
def __struct__(kv) do
Enum.reduce(kv, __struct__(), fn {k, v}, acc -> :maps.update(k, v, acc) end)
end
+1 -11
View File
@@ -216,20 +216,10 @@ defmodule Map do
@spec new(Enumerable.t(), (term -> {key, value})) :: map
def new(enumerable, transform) when is_function(transform, 1) do
enumerable
|> Enum.to_list()
|> new_transform(transform, [])
end
defp new_transform([], _fun, acc) do
acc
|> :lists.reverse()
|> Enum.map(transform)
|> :maps.from_list()
end
defp new_transform([element | rest], fun, acc) do
new_transform(rest, fun, [fun.(element) | acc])
end
@doc """
Returns whether the given `key` exists in the given `map`.
+107
View File
@@ -335,6 +335,16 @@ defmodule Module do
@vsn "1.0"
end
### Struct attributes
* `@derive` - derives an implementation for the given protocol for the
struct defined in the current module
* `@enforce_keys` - ensures the given keys are always set when building
the struct defined in the current module
See `Kernel.defstruct/1` for more information on building and using structs.
### Typespec attributes
The following attributes are part of typespecs and are also built-in in
@@ -543,6 +553,103 @@ defmodule Module do
@callback __info__(:md5) :: binary()
@callback __info__(:module) :: module()
@doc """
Returns information about module attributes used by Elixir.
See the "Module attributes" section in the module documentation for more
information on each attribute.
## Examples
iex> map = Module.reserved_attributes()
iex> Map.has_key?(map, :moduledoc)
true
iex> Map.has_key?(map, :doc)
true
"""
@doc since: "1.12.0"
def reserved_attributes() do
%{
after_compile: %{
doc: "A hook that will be invoked right after the current module is compiled."
},
before_compile: %{
doc: "A hook that will be invoked before the module is compiled."
},
behaviour: %{
doc: "Specifies that the current module implements a given behaviour."
},
on_definition: %{
doc:
"A hook that will be invoked when each function or macro in the current module is defined."
},
impl: %{
doc: "Declares an implementation of a callback function or macro."
},
compile: %{
doc: "Defines options for module compilation."
},
deprecated: %{
doc: "Provides the deprecation reason for a function."
},
moduledoc: %{
doc: "Provides documentation for the current module."
},
doc: %{
doc: "Provides documentation for a function/macro/callback."
},
typedoc: %{
doc: "Provides documentation for a type."
},
dialyzer: %{
doc: "Defines Dialyzer warnings to request or suppress."
},
external_resource: %{
doc: "Specifies an external resource for the current module."
},
file: %{
doc:
"Changes the filename used in stacktraces for the function or macro that follows the attribute."
},
on_load: %{
doc: "A hook that will be invoked whenever the module is loaded."
},
vsn: %{
doc: "Specify the module version."
},
type: %{
doc: "Defines a type to be used in `@spec`."
},
typep: %{
doc: "Defines a private type to be used in `@spec`."
},
opaque: %{
doc: "Defines an opaque type to be used in `@spec`."
},
spec: %{
doc: "Provides a specification for a function."
},
callback: %{
doc: "Provides a specification for a behaviour callback."
},
macrocallback: %{
doc: "Provides a specification for a macro behaviour callback."
},
optional_callbacks: %{
doc: "Specifies which behaviour callbacks and macro behaviour callbacks are optional."
},
derive: %{
doc:
"Derives an implementation for the given protocol for the struct defined in the current module."
},
enforce_keys: %{
doc:
"Ensures the given keys are always set when building the struct defined in the current module."
}
}
end
@doc """
Checks if a module is open.
+1 -1
View File
@@ -831,7 +831,7 @@ defmodule Module.Types.Unify do
end
def format_type({:var, index}, _simplify?) do
"var#{index}"
"var#{index + 1}"
end
def format_type(atom, _simplify?) when is_atom(atom) do
+16 -16
View File
@@ -66,7 +66,7 @@ defmodule Path do
case type(path) do
:relative ->
absname_join(relative_to, path)
absname_join([relative_to, path])
:absolute ->
absname_join([path])
@@ -80,11 +80,11 @@ defmodule Path do
# Absolute path on current drive
defp absname_vr(["/" | rest], [volume | _], _relative), do: absname_join([volume | rest])
# Relative to current directory on current drive.
# Relative to current directory on current drive
defp absname_vr([<<x, ?:>> | rest], [<<x, _::binary>> | _], relative),
do: absname(absname_join(rest), relative)
# Relative to current directory on another drive.
# Relative to current directory on another drive
defp absname_vr([<<x, ?:>> | name], _, _relative) do
cwd =
case :file.get_cwd([x, ?:]) do
@@ -97,25 +97,25 @@ defmodule Path do
@slash [?/, ?\\]
# Joins a list
defp absname_join([name1, name2 | rest]), do: absname_join([absname_join(name1, name2) | rest])
defp absname_join([]), do: ""
defp absname_join(list), do: absname_join(list, major_os_type())
defp absname_join([name]),
do: do_absname_join(IO.chardata_to_string(name), <<>>, [], major_os_type())
defp absname_join([name1, name2 | rest], os_type) do
joined = do_absname_join(IO.chardata_to_string(name1), relative(name2), [], os_type)
absname_join([joined | rest], os_type)
end
# Joins two paths
defp absname_join(left, right),
do: do_absname_join(IO.chardata_to_string(left), relative(right), [], major_os_type())
defp absname_join([name], os_type) do
do_absname_join(IO.chardata_to_string(name), <<>>, [], os_type)
end
defp do_absname_join(<<uc_letter, ?:, rest::binary>>, relativename, [], :win32)
when uc_letter in ?A..?Z do
do_absname_join(rest, relativename, [?:, uc_letter + ?a - ?A], :win32)
end
when uc_letter in ?A..?Z,
do: do_absname_join(rest, relativename, [?:, uc_letter + ?a - ?A], :win32)
defp do_absname_join(<<c1, c2, rest::binary>>, relativename, [], :win32)
when c1 in @slash and c2 in @slash do
do_absname_join(rest, relativename, '//', :win32)
end
when c1 in @slash and c2 in @slash,
do: do_absname_join(rest, relativename, '//', :win32)
defp do_absname_join(<<?\\, rest::binary>>, relativename, result, :win32),
do: do_absname_join(<<?/, rest::binary>>, relativename, result, :win32)
-2
View File
@@ -688,8 +688,6 @@ defmodule Protocol do
def: 2,
defp: 1,
defp: 2,
defdelegate: 2,
defexception: 1,
defguard: 1,
defguardp: 1,
defmacro: 1,
+63 -47
View File
@@ -1,13 +1,12 @@
defmodule Range do
@moduledoc """
Ranges represent a sequence of zero, one or many, ascending
or descending, consecutive integers.
or descending integers with a common difference called step.
Ranges are always inclusive and they may have custom steps.
The most common form of creating and matching on ranges is
via the `start..stop` and `start..stop//step` notations,
defined respectively as the `../2` and `..///3` macros
auto-imported from `Kernel`:
via the [`first..last`](`../2`) and [`first..last//step`](`..///3`)
notations, auto-imported from `Kernel`:
iex> Enum.to_list(1..3)
[1, 2, 3]
@@ -30,10 +29,10 @@ defmodule Range do
iex> Enum.to_list(0..10//-1)
[]
When defining a range without steps, the step will be
defined based on the start and stop position of the
range, If `start >= stop`, it will be an increasing range
with step of 1. Otherwise, it is a decreasing range.
When defining a range without a step, the step will be
defined based on the first and last position of the
range, If `first >= last`, it will be an increasing range
with a step of 1. Otherwise, it is a decreasing range.
Note however implicitly decreasing ranges are deprecated.
Therefore, if you need a decreasing range from `3` to `1`,
prefer to write `3..1//-1` instead.
@@ -68,6 +67,10 @@ defmodule Range do
iex> range.step
2
You can access the range fields (`first`, `last`, and `step`)
directly but you should not modify nor create ranges by hand.
Instead use the proper operators or `new/2` and `new/3`.
A range implements the `Enumerable` protocol, which means
functions in the `Enum` module can be used to work with
ranges:
@@ -92,22 +95,21 @@ defmodule Range do
@enforce_keys [:first, :last, :step]
defstruct first: nil, last: nil, step: nil
@type first :: integer
@type last :: integer
@type limit :: integer
@type step :: pos_integer | neg_integer
@type t :: %__MODULE__{first: first, last: last, step: step}
@type t(first, last) :: %__MODULE__{first: first, last: last}
@type t :: %__MODULE__{first: limit, last: limit, step: step}
@type t(first, last) :: %__MODULE__{first: first, last: last, step: step}
@doc """
Creates a new range.
If first is less than last, the range will be increasing from
first to last. If first is equal to last, the range will contain
If `first` is less than `last`, the range will be increasing from
`first` to `last`. If `first` is equal to `last`, the range will contain
one element, which is the number itself.
If first is more than last, the range will be decreasing from first
to last, albeit this behaviour is deprecated. Instead prefer to
explicitly list the step `new/3`.
If `first` is greater than `last`, the range will be decreasing from `first`
to `last`, albeit this behaviour is deprecated. Therefore, it is advised to
explicitly list the step with `new/3`.
## Examples
@@ -115,9 +117,10 @@ defmodule Range do
-100..100
"""
@spec new(integer, integer) :: t
@spec new(limit, limit) :: t
def new(first, last) when is_integer(first) and is_integer(last) do
# TODO: Deprecate inferring a range with step of -1 on Elixir v1.17
# TODO: Deprecate inferring a range with a step of -1 on Elixir v1.17
step = if first <= last, do: 1, else: -1
%Range{first: first, last: last, step: step}
end
@@ -129,7 +132,7 @@ defmodule Range do
end
@doc """
Creates a new range with step.
Creates a new range with `step`.
## Examples
@@ -138,7 +141,7 @@ defmodule Range do
"""
@doc since: "1.12.0"
@spec new(integer, integer, integer) :: t
@spec new(limit, limit, step) :: t
def new(first, last, step)
when is_integer(first) and is_integer(last) and is_integer(step) and step != 0 do
%Range{first: first, last: last, step: step}
@@ -146,32 +149,12 @@ defmodule Range do
def new(first, last, step) do
raise ArgumentError,
"ranges (first..last//step) expect both sides to be integers and the step to be an integer " <>
"different than zero, got: #{inspect(first)}..#{inspect(last)}//#{inspect(step)}"
"ranges (first..last//step) expect both sides to be integers and the step to be a " <>
"non-zero integer, got: #{inspect(first)}..#{inspect(last)}//#{inspect(step)}"
end
@doc """
Checks if the range is empty.
## Examples
iex> Range.empty?(1..0//1)
true
iex> Range.empty?(0..1//-1)
true
iex> Range.empty?(1..0)
false
iex> Range.empty?(0..1)
false
"""
@doc since: "1.12.0"
def empty?(first..last//step) when step > 0 and first > last, do: true
def empty?(first..last//step) when step < 0 and first < last, do: true
def empty?(_.._//_), do: false
@doc """
Returns the size of the range.
Returns the size of `range`.
## Examples
@@ -197,10 +180,17 @@ defmodule Range do
"""
@doc since: "1.12.0"
def size(range)
def size(first..last//step) when step > 0 and first > last, do: 0
def size(first..last//step) when step < 0 and first < last, do: 0
def size(first..last//step), do: abs(div(last - first, step)) + 1
# TODO: Remove me on v2.0
def size(%{__struct__: Range, first: first, last: last} = range) do
step = if first <= last, do: 1, else: -1
size(Map.put(range, :step, step))
end
@doc """
Checks if two ranges are disjoint.
@@ -242,7 +232,7 @@ defmodule Range do
@doc since: "1.8.0"
@spec disjoint?(t, t) :: boolean
def disjoint?(first1..last1//step1 = range1, first2..last2//step2 = range2) do
if empty?(range1) or empty?(range2) do
if size(range1) == 0 or size(range2) == 0 do
true
else
{first1, last1, step1} = normalize(first1, last1, step1)
@@ -273,7 +263,7 @@ defmodule Range do
end
end
@compile inline: [normalize: 3, empty?: 1]
@compile inline: [normalize: 3]
defp normalize(first, last, step) when first > last, do: {last, first, -step}
defp normalize(first, last, step), do: {first, last, step}
@@ -289,6 +279,12 @@ defimpl Enumerable, for: Range do
reduce(first, last, acc, fun, step)
end
# TODO: Remove me on v2.0
def reduce(%{__struct__: Range, first: first, last: last} = range, acc, fun) do
step = if first <= last, do: 1, else: -1
reduce(Map.put(range, :step, step), acc, fun)
end
defp reduce(_first, _last, {:halt, acc}, _fun, _step) do
{:halted, acc}
end
@@ -309,7 +305,7 @@ defimpl Enumerable, for: Range do
def member?(first..last//step = range, value) when is_integer(value) do
cond do
Range.empty?(range) ->
Range.size(range) == 0 ->
{:ok, false}
first <= last ->
@@ -320,6 +316,13 @@ defimpl Enumerable, for: Range do
end
end
# TODO: Remove me on v2.0
def member?(%{__struct__: Range, first: first, last: last} = range, value)
when is_integer(value) do
step = if first <= last, do: 1, else: -1
member?(Map.put(range, :step, step), value)
end
def member?(_, _value) do
{:ok, false}
end
@@ -332,12 +335,19 @@ defimpl Enumerable, for: Range do
{:ok, Range.size(range), &slice(first + &1 * step, step, &2)}
end
# TODO: Remove me on v2.0
def slice(%{__struct__: Range, first: first, last: last} = range) do
step = if first <= last, do: 1, else: -1
slice(Map.put(range, :step, step))
end
defp slice(current, _step, 1), do: [current]
defp slice(current, step, remaining), do: [current | slice(current + step, step, remaining - 1)]
end
defimpl Inspect, for: Range do
import Inspect.Algebra
import Kernel, except: [inspect: 2]
def inspect(first..last//1, opts) do
concat([to_doc(first, opts), "..", to_doc(last, opts)])
@@ -346,4 +356,10 @@ defimpl Inspect, for: Range do
def inspect(first..last//step, opts) do
concat([to_doc(first, opts), "..", to_doc(last, opts), "//", to_doc(step, opts)])
end
# TODO: Remove me on v2.0
def inspect(%{__struct__: Range, first: first, last: last} = range, opts) do
step = if first <= last, do: 1, else: -1
inspect(Map.put(range, :step, step), opts)
end
end
+58
View File
@@ -731,6 +731,64 @@ defmodule Registry do
acc
end
@doc """
Reads the values for the given `key` for `pid` in `registry`.
For unique registries, it is either an empty list or a list
with a single element. For duplicate registries, it is a list
with zero, one, or multiple elements.
## Examples
In the example below we register the current process and look it up
both from itself and other processes:
iex> Registry.start_link(keys: :unique, name: Registry.UniqueLookupTest)
iex> Registry.values(Registry.UniqueLookupTest, "hello", self())
[]
iex> {:ok, _} = Registry.register(Registry.UniqueLookupTest, "hello", :world)
iex> Registry.values(Registry.UniqueLookupTest, "hello", self())
[:world]
iex> Task.async(fn -> Registry.values(Registry.UniqueLookupTest, "hello", self()) end) |> Task.await()
[]
iex> parent = self()
iex> Task.async(fn -> Registry.values(Registry.UniqueLookupTest, "hello", parent) end) |> Task.await()
[:world]
The same applies to duplicate registries:
iex> Registry.start_link(keys: :duplicate, name: Registry.DuplicateLookupTest)
iex> Registry.values(Registry.DuplicateLookupTest, "hello", self())
[]
iex> {:ok, _} = Registry.register(Registry.DuplicateLookupTest, "hello", :world)
iex> Registry.values(Registry.DuplicateLookupTest, "hello", self())
[:world]
iex> {:ok, _} = Registry.register(Registry.DuplicateLookupTest, "hello", :another)
iex> Enum.sort(Registry.values(Registry.DuplicateLookupTest, "hello", self()))
[:another, :world]
"""
@doc since: "1.12.0"
@spec values(registry, key, pid) :: [value]
def values(registry, key, pid) when is_atom(registry) do
case key_info!(registry) do
{:unique, partitions, key_ets} ->
key_ets = key_ets || key_ets!(registry, key, partitions)
case safe_lookup_second(key_ets, key) do
{^pid, value} ->
[value]
_ ->
[]
end
{:duplicate, partitions, key_ets} ->
key_ets = key_ets || key_ets!(registry, pid, partitions)
for {^pid, value} <- safe_lookup_second(key_ets, key), do: value
end
end
@doc """
Unregisters all entries for the given `key` associated to the current
process in `registry`.
+2 -2
View File
@@ -1443,9 +1443,9 @@ defmodule Stream do
## Examples
# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exrop, {1, 2, 3})
iex> :rand.seed(:exsss, {1, 2, 3})
iex> Stream.repeatedly(&:rand.uniform/0) |> Enum.take(3)
[0.7498295129076106, 0.06161655489244533, 0.7924073127680873]
[0.5455598952593053, 0.6039309974353404, 0.6684893034823949]
"""
@spec repeatedly((() -> element)) :: Enumerable.t()
+7 -1
View File
@@ -69,7 +69,7 @@ defmodule String do
## Code points and grapheme cluster
The functions in this module act according to the Unicode
Standard, version 12.1.0.
Standard, version 13.0.0.
As per the standard, a code point is a single Unicode Character,
which may be represented by one or more bytes.
@@ -2098,6 +2098,12 @@ defmodule String do
end
end
# TODO: Remove me on v2.0
def slice(string, %{__struct__: Range, first: first, last: last} = range) do
step = if first <= last, do: 1, else: -1
slice(string, Map.put(range, :step, step))
end
defp slice_range("", _, _), do: ""
defp slice_range(string, first, -1) when first >= 0 do
+1 -1
View File
@@ -930,7 +930,7 @@ defmodule Supervisor do
"""
@spec which_children(supervisor) :: [
# inlining module() | :dynamic here because :supervisor.modules() is not exported
{term() | :undefined, child | :restarting, :worker | :supervisor, module() | :dynamic}
{term() | :undefined, child | :restarting, :worker | :supervisor, [module()] | :dynamic}
]
def which_children(supervisor) do
call(supervisor, :which_children)
+74 -9
View File
@@ -881,6 +881,62 @@ defmodule System do
:init.stop(String.to_charlist(status))
end
@doc ~S"""
Executes the given `command` in the OS shell.
It uses `sh` for Unix-like systems and `cmd` for Windows.
**Important**: Use this function with care. In particular, **never
pass untrusted user input to this function**, as the user would be
able to perform "command injection attacks" by executing any code
directly on the machine. Generally speaking, prefer to use `cmd/3`
over this function.
## Examples
iex> System.shell("echo hello")
{"hello\n", 0}
If you want to stream the devices to IO as they come:
iex> System.shell("echo hello", into: IO.stream())
hello
{%IO.Stream{}, 0}
## Options
It accepts the same options as `cmd/3`, except for `arg0`.
"""
@doc since: "1.12.0"
@spec shell(binary, keyword) :: {Collectable.t(), exit_status :: non_neg_integer}
def shell(command, opts \\ []) when is_binary(command) do
assert_no_null_byte!(command, "System.shell/2")
# Finding shell command logic from :os.cmd in OTP
# https://github.com/erlang/otp/blob/8deb96fb1d017307e22d2ab88968b9ef9f1b71d0/lib/kernel/src/os.erl#L184
command =
case :os.type() do
{:unix, _} ->
command =
command
|> String.replace("\"", "\\\"")
|> String.to_charlist()
'sh -c "' ++ command ++ '"'
{:win32, osname} ->
command = String.to_charlist(command)
case {System.get_env("COMSPEC"), osname} do
{nil, :windows} -> 'command.com /s /c ' ++ command
{nil, _} -> 'cmd /s /c ' ++ command
{cmd, _} -> '#{cmd} /s /c ' ++ command
end
end
do_cmd({:spawn, command}, [], opts)
end
@doc ~S"""
Executes the given `command` with `args`.
@@ -913,7 +969,9 @@ defmodule System do
iex> System.cmd("echo", ["hello"], env: [{"MIX_ENV", "test"}])
{"hello\n", 0}
iex> System.cmd("echo", ["hello"], into: IO.stream(:stdio, :line))
If you want to stream the devices to IO as they come:
iex> System.cmd("echo", ["hello"], into: IO.stream())
hello
{%IO.Stream{}, 0}
@@ -964,7 +1022,7 @@ defmodule System do
## Shell commands
If you desire to execute a trusted command inside a shell, with pipes,
redirecting and so on, please check `:os.cmd/1`.
redirecting and so on, please check `shell/2`.
"""
@spec cmd(binary, [binary], keyword) :: {Collectable.t(), exit_status :: non_neg_integer}
def cmd(command, args, opts \\ []) when is_binary(command) and is_list(args) do
@@ -983,11 +1041,15 @@ defmodule System do
:os.find_executable(cmd) || :erlang.error(:enoent, [command, args, opts])
end
{into, opts} = cmd_opts(opts, [:use_stdio, :exit_status, :binary, :hide, args: args], "")
do_cmd({:spawn_executable, cmd}, [args: args], opts)
end
defp do_cmd(port_init, base_opts, opts) do
{into, opts} = cmd_opts(opts, [:use_stdio, :exit_status, :binary, :hide] ++ base_opts, "")
{initial, fun} = Collectable.into(into)
try do
do_cmd(Port.open({:spawn_executable, cmd}, opts), initial, fun)
do_port(Port.open(port_init, opts), initial, fun)
catch
kind, reason ->
fun.(initial, :halt)
@@ -997,17 +1059,18 @@ defmodule System do
end
end
defp do_cmd(port, acc, fun) do
defp do_port(port, acc, fun) do
receive do
{^port, {:data, data}} ->
do_cmd(port, fun.(acc, {:cont, data}), fun)
do_port(port, fun.(acc, {:cont, data}), fun)
{^port, {:exit_status, status}} ->
{acc, status}
end
end
defp cmd_opts([{:into, any} | t], opts, _into), do: cmd_opts(t, opts, any)
defp cmd_opts([{:into, any} | t], opts, _into),
do: cmd_opts(t, opts, any)
defp cmd_opts([{:cd, bin} | t], opts, into) when is_binary(bin),
do: cmd_opts(t, [{:cd, bin} | opts], into)
@@ -1018,7 +1081,8 @@ defmodule System do
defp cmd_opts([{:stderr_to_stdout, true} | t], opts, into),
do: cmd_opts(t, [:stderr_to_stdout | opts], into)
defp cmd_opts([{:stderr_to_stdout, false} | t], opts, into), do: cmd_opts(t, opts, into)
defp cmd_opts([{:stderr_to_stdout, false} | t], opts, into),
do: cmd_opts(t, opts, into)
defp cmd_opts([{:parallelism, bool} | t], opts, into) when is_boolean(bool),
do: cmd_opts(t, [{:parallelism, bool} | opts], into)
@@ -1029,7 +1093,8 @@ defmodule System do
defp cmd_opts([{key, val} | _], _opts, _into),
do: raise(ArgumentError, "invalid option #{inspect(key)} with value #{inspect(val)}")
defp cmd_opts([], opts, into), do: {into, opts}
defp cmd_opts([], opts, into),
do: {into, opts}
defp validate_env(enum) do
Enum.map(enum, fn
+5
View File
@@ -177,6 +177,11 @@ defmodule Task.Supervised do
def stream(enumerable, acc, reducer, mfa, options, spawn) do
next = &Enumerable.reduce(enumerable, &1, fn x, acc -> {:suspend, [x | acc]} end)
max_concurrency = Keyword.get(options, :max_concurrency, System.schedulers_online())
unless is_integer(max_concurrency) and max_concurrency > 0 do
raise ArgumentError, ":max_concurrency must be an integer greater than zero"
end
ordered? = Keyword.get(options, :ordered, true)
timeout = Keyword.get(options, :timeout, 5000)
on_timeout = Keyword.get(options, :on_timeout, :exit)
+6 -7
View File
@@ -462,14 +462,13 @@ defmodule URI do
defp hex_to_dec(_n), do: throw(:malformed_uri)
@doc """
Parses a well-formed URI reference into its components.
Parses a well-formed URI into its components.
Note this function expects a well-formed URI and does not perform
any validation. See the "Examples" section below for examples of how
`URI.parse/1` can be used to parse a wide range of URIs.
This function uses the parsing regular expression as defined
in [RFC 3986, Appendix B](https://tools.ietf.org/html/rfc3986#appendix-B).
This function can parse both absolute and relative URLs. You can check
if a URI is absolute or relative by checking if the `scheme` field is
nil or not. Furthermore, this function expects both absolute and
relative URIs to be well-formed and does not perform any validation.
See the "Examples" section below.
When a URI is given without a port, the value returned by
`URI.default_port/1` for the URI's scheme is used for the `:port` field.
@@ -8,8 +8,8 @@ Elixir applies bug fixes only to the latest minor branch. Security patches are a
Elixir version | Support
:------------- | :-----------------------------
1.12 | Development
1.11 | Bug fixes and security patches
1.12 | Bug fixes and security patches
1.11 | Security patches only
1.10 | Security patches only
1.9 | Security patches only
1.8 | Security patches only
@@ -39,25 +39,25 @@ The only exception to the compatibility guarantees above are experimental featur
## Compatibility between Elixir and Erlang/OTP
Erlang/OTP versioning is independent from the versioning of Elixir. Each version of Elixir supports a specific range of Erlang/OTP versions. The compatibility table is shown below.
Erlang/OTP versioning is independent from the versioning of Elixir. Erlang releases a new major version yearly. Our goal is to support the last three Erlang major versions by the time Elixir is released. The compatibility table is shown below.
Elixir version | Supported Erlang/OTP versions
:------------- | :-------------------------------
1.0 | 17 - 17 (and Erlang/OTP 18 from v1.0.5)
1.1 | 17 - 18
1.2 | 18 - 18 (and Erlang/OTP 19 from v1.2.6)
1.3 | 18 - 19
1.4 | 18 - 19 (and Erlang/OTP 20 from v1.4.5)
1.5 | 18 - 20
1.6 | 19 - 20 (and Erlang/OTP 21 from v1.6.6)
1.7 | 19 - 22
1.8 | 20 - 22
1.9 | 20 - 22
1.12 | 22 - 24
1.11 | 21 - 23 (and Erlang/OTP 24 from v1.11.4)
1.10 | 21 - 22 (and Erlang/OTP 23 from v1.10.3)
1.11 | 21 - 23
1.12 | 21 - 23
1.9 | 20 - 22
1.8 | 20 - 22
1.7 | 19 - 22
1.6 | 19 - 20 (and Erlang/OTP 21 from v1.6.6)
1.5 | 18 - 20
1.4 | 18 - 19 (and Erlang/OTP 20 from v1.4.5)
1.3 | 18 - 19
1.2 | 18 - 18 (and Erlang/OTP 19 from v1.2.6)
1.1 | 17 - 18
1.0 | 17 - 17 (and Erlang/OTP 18 from v1.0.5)
While Elixir often adds compatibility to new Erlang/OTP versions on released branches, such as support for Erlang/OTP 20 in v1.4.5, those releases usually contain the minimum changes for Elixir to run without errors. Only the next minor release, in this case v1.5.0, does effectively leverage the new features provided by the latest Erlang/OTP release.
Note Elixir may add compatibility to new Erlang/OTP versions on patch releases, such as support for Erlang/OTP 20 in v1.4.5. Those releases are made for convenience and typically contain the minimum changes for Elixir to run without errors, if any changes are necessary. Only the next minor release, in this case v1.5.0, effectively leverages the new features provided by the latest Erlang/OTP release.
## Deprecations
@@ -77,6 +77,8 @@ The first column is the version the feature was hard deprecated. The second colu
Version | Deprecated feature | Replaced by (available since)
:-------| :-------------------------------------------------- | :---------------------------------------------------------------
[v1.12] | `^^^/2` | Use `bxor/2` instead (v1.0)
[v1.12] | `@foo()` to read module attributes | Remove the parenthesis (v1.0)
[v1.12] | `use EEx.Engine` | Explicitly delegate to EEx.Engine instead (v1.0)
[v1.12] | `:xref` compiler in Mix | Nothing (it always runs as part of the compiler now)
[v1.11] | `Mix.Project.compile/2` | `Mix.Task.run("compile", args)` (v1.0)
@@ -179,4 +181,4 @@ Version | Deprecated feature | Replaced by (ava
[v1.9]: https://github.com/elixir-lang/elixir/blob/v1.9/CHANGELOG.md#4-hard-deprecations
[v1.10]: https://github.com/elixir-lang/elixir/blob/v1.10/CHANGELOG.md#4-hard-deprecations
[v1.11]: https://github.com/elixir-lang/elixir/blob/v1.11/CHANGELOG.md#4-hard-deprecations
[v1.12]: https://github.com/elixir-lang/elixir/blob/master/CHANGELOG.md#4-hard-deprecations
[v1.12]: https://github.com/elixir-lang/elixir/blob/v1.12/CHANGELOG.md#4-hard-deprecations
+2 -2
View File
@@ -6,8 +6,8 @@ This document covers operators in Elixir, how they are parsed, how they can be d
The following is a list of all operators that Elixir is capable of parsing, ordered from higher to lower precedence, alongside their associativity:
Operator | Associativity
------------------------------------------------------| -------------
Operator | Associativity
----------------------------------------------------- | -------------
`@` | Unary
`.` | Left
`+` `-` `!` `^` `not` `~~~` | Unary
+19
View File
@@ -0,0 +1,19 @@
# Generate docs_config.js for version chooser in ExDoc
[app] = System.argv()
{text_tags, 0} = System.cmd("git", ["tag"])
skipped = Version.parse!("1.0.3")
list_contents =
text_tags
|> String.split()
|> Enum.map(fn "v" <> rest -> Version.parse!(rest) end)
|> Enum.filter(&(Version.compare(&1, skipped) == :gt))
|> Enum.sort({:desc, Version})
|> Enum.map_intersperse(", ", fn version ->
version_string = to_string(version)
~s[{"version":"v#{version_string}", "url":"https://hexdocs.pm/#{app}/#{version_string}"}]
end)
File.mkdir_p!("doc/#{app}")
File.write!("doc/#{app}/docs_config.js", ["var versionNodes = [", list_contents, "];\n"])
@@ -1,6 +1,16 @@
# Returns config for Elixir docs
canonical = System.fetch_env!("CANONICAL")
[
extras: Path.wildcard("lib/elixir/pages/*.md") ++ ["CHANGELOG.md"],
deps: [
eex: "https://hexdocs.pm/eex/#{canonical}",
ex_unit: "https://hexdocs.pm/ex_unit/#{canonical}",
iex: "https://hexdocs.pm/iex/#{canonical}",
logger: "https://hexdocs.pm/logger/#{canonical}",
mix: "https://hexdocs.pm/mix/#{canonical}"
],
groups_for_functions: [
Guards: &(&1[:guard] == true)
],
+12
View File
@@ -0,0 +1,12 @@
canonical = System.fetch_env!("CANONICAL")
[
deps: [
eex: "https://hexdocs.pm/eex/#{canonical}",
elixir: "https://hexdocs.pm/elixir/#{canonical}",
ex_unit: "https://hexdocs.pm/ex_unit/#{canonical}",
iex: "https://hexdocs.pm/iex/#{canonical}",
logger: "https://hexdocs.pm/logger/#{canonical}",
mix: "https://hexdocs.pm/mix/#{canonical}"
]
]
+3 -3
View File
@@ -111,10 +111,10 @@ preload_common_modules() ->
parse_otp_release() ->
%% Whenever we change this check, we should also change Makefile.
case string:to_integer(erlang:system_info(otp_release)) of
{Num, _} when Num >= 21 ->
{Num, _} when Num >= 22 ->
Num;
_ ->
io:format(standard_error, "ERROR! Unsupported Erlang/OTP version, expected Erlang/OTP 21+~n", []),
io:format(standard_error, "ERROR! Unsupported Erlang/OTP version, expected Erlang/OTP 22+~n", []),
erlang:halt(1)
end.
@@ -252,7 +252,7 @@ eval_forms(Tree, RawBinding, OE) ->
case Erl of
{atom, _, Atom} ->
{Atom, Binding, NewE};
{Atom, RawBinding, NewE};
_ ->
Exprs =
-8
View File
@@ -30,11 +30,3 @@
warn_on_unnecessary_quotes=true,
warnings=[]
}).
%% TODO: Remove this once we support Erlang/OTP 22+ exclusively.
%% See https://github.com/erlang/otp/pull/1972
-if(?OTP_RELEASE >= 22).
-define(NO_SPAWN_COMPILER_PROCESS, no_spawn_compiler_process).
-else.
-define(NO_SPAWN_COMPILER_PROCESS, dialyzer, no_spawn_compiler_process).
-endif.
+1 -7
View File
@@ -79,7 +79,7 @@ fetch_definition([Tuple | T], File, Module, Set, Bag, All, Private) ->
fetch_definition(T, File, Module, Set, Bag, NewAll, NewPrivate)
catch
error:badarg ->
check_bodiless_function(Check, Meta, File, Module, Kind, Tuple),
elixir_errors:form_error(Meta, File, ?MODULE, {function_head, Kind, Tuple}),
fetch_definition(T, File, Module, Set, Bag, All, Private)
end;
@@ -338,12 +338,6 @@ check_valid_defaults(Meta, File, Name, Arity, Kind, 0, _, LastDefaults, true, tr
check_valid_defaults(_Meta, _File, _Name, _Arity, _Kind, 0, _StoredDefaults, _LastDefaults, _HasBody, _LastHasBody) ->
ok.
check_bodiless_function(Check, _Meta, _File, Module, _Kind, _Tuple)
when Check == false; Module == 'Elixir.Module' ->
ok;
check_bodiless_function(_Check, Meta, File, _Module, Kind, Tuple) ->
elixir_errors:form_error(Meta, File, ?MODULE, {function_head, Kind, Tuple}).
check_args_for_function_head(Meta, Args, E) ->
[begin
elixir_errors:form_error(Meta, E, ?MODULE, invalid_args_for_function_head)
+11 -9
View File
@@ -77,7 +77,7 @@ require_function(Meta, Receiver, Name, Arity, E) ->
end.
remote_function(Meta, Receiver, Name, Arity, E) ->
check_deprecated(Meta, Receiver, Name, Arity, E),
check_deprecated(Meta, function, Receiver, Name, Arity, E),
case elixir_rewrite:inline(Receiver, Name, Arity) of
{AR, AN} -> {remote, AR, AN, Arity};
@@ -161,7 +161,7 @@ do_expand_import(Meta, {Name, Arity} = Tuple, Args, Module, E, Result) ->
elixir_locals:record_import(Tuple, Receiver, Module, ?key(E, function)),
{ok, Receiver, Name, Args};
{macro, Receiver} ->
check_deprecated(Meta, Receiver, Name, Arity, E),
check_deprecated(Meta, macro, Receiver, Name, Arity, E),
elixir_env:trace({imported_macro, Meta, Receiver, Name, Arity}, E),
elixir_locals:record_import(Tuple, Receiver, Module, ?key(E, function)),
{ok, Receiver, expand_macro_named(Meta, Receiver, Name, Arity, Args, E)};
@@ -180,17 +180,18 @@ do_expand_import(Meta, {Name, Arity} = Tuple, Args, Module, E, Result) ->
end.
expand_require(Meta, Receiver, {Name, Arity} = Tuple, Args, E) ->
check_deprecated(Meta, Receiver, Name, Arity, E),
Required = (Receiver == ?key(E, module)) orelse required(Meta) orelse is_element(Receiver, ?key(E, requires)),
case is_element(Tuple, get_macros(Receiver, Required)) of
true when Required ->
check_deprecated(Meta, macro, Receiver, Name, Arity, E),
elixir_env:trace({remote_macro, Meta, Receiver, Name, Arity}, E),
{ok, Receiver, expand_macro_named(Meta, Receiver, Name, Arity, Args, E)};
true ->
Info = {unrequired_module, {Receiver, Name, length(Args)}},
elixir_errors:form_error(Meta, E, ?MODULE, Info);
false ->
check_deprecated(Meta, function, Receiver, Name, Arity, E),
error
end.
@@ -361,12 +362,13 @@ elixir_imported_macros() ->
error:undef -> []
end.
check_deprecated(_, erlang, _, _, _) ->
ok;
check_deprecated(_, ?kernel, _, _, _) ->
ok;
check_deprecated(Meta, Receiver, Name, Arity, E) ->
case (?key(E, function) == nil) andalso get_deprecations(Receiver) of
check_deprecated(_, _, erlang, _, _, _) -> ok;
check_deprecated(_, _, elixir_def, _, _, _) -> ok;
check_deprecated(_, _, elixir_module, _, _, _) -> ok;
check_deprecated(_, _, ?kernel, _, _, _) -> ok;
check_deprecated(Meta, Kind, Receiver, Name, Arity, E) ->
%% Any compile time behaviour cannot be verified by the runtime group pass.
case ((?key(E, function) == nil) or (Kind == macro)) andalso get_deprecations(Receiver) of
[_ | _] = Deprecations ->
case lists:keyfind({Name, Arity}, 1, Deprecations) of
{_, Message} ->
+1 -1
View File
@@ -23,7 +23,7 @@ debug_info(core_v1, _Module, {elixir_v1, Map, Specs}, Opts) ->
%% warnings nor the other functionality provided there.
case elixir_erl_compiler:erl_to_core(Prefix ++ Specs ++ Forms, AllOpts) of
{ok, CoreForms, _} ->
try compile:noenv_forms(CoreForms, [?NO_SPAWN_COMPILER_PROCESS, from_core, core, return | AllOpts]) of
try compile:noenv_forms(CoreForms, [no_spawn_compiler_process, from_core, core, return | AllOpts]) of
{ok, _, Core, _} -> {ok, Core};
_What -> {error, failed_conversion}
catch
+2 -2
View File
@@ -36,7 +36,7 @@ erl_to_core(Forms, Opts) ->
[] ->
v3_core:module(Forms, Opts);
_ ->
case compile:noenv_forms(Forms, [?NO_SPAWN_COMPILER_PROCESS, to_core0, return, no_auto_import | Opts]) of
case compile:noenv_forms(Forms, [no_spawn_compiler_process, to_core0, return, no_auto_import | Opts]) of
{ok, _Module, Core, Warnings} -> {ok, Core, Warnings};
{error, Errors, Warnings} -> {error, Errors, Warnings}
end
@@ -48,7 +48,7 @@ compile(Forms, File, Opts) when is_list(Forms), is_list(Opts), is_binary(File) -
case erl_to_core(Forms, Opts) of
{ok, CoreForms, CoreWarnings} ->
format_warnings(Opts, CoreWarnings),
CompileOpts = [?NO_SPAWN_COMPILER_PROCESS, from_core, no_core_prepare,
CompileOpts = [no_spawn_compiler_process, from_core, no_core_prepare,
no_auto_import, return, {source, Source} | Opts],
case compile:noenv_forms(CoreForms, CompileOpts) of
+26 -14
View File
@@ -223,9 +223,9 @@ translate({{'.', _, [Left, Right]}, Meta, []}, S) when is_tuple(Left), is_atom(R
Ann = ?ann(Meta),
TRight = {atom, Ann, Right},
{Var, SV} = elixir_erl_var:build('_', SL),
TVar = {var, Ann, Var},
Generated = erl_anno:set_generated(true, Ann),
{Var, SV} = elixir_erl_var:build('_', SL),
TVar = {var, Generated, Var},
TError = {tuple, Ann, [{atom, Ann, badkey}, TRight, TVar]},
{{'case', Generated, TLeft, [
@@ -257,11 +257,11 @@ translate({{'.', _, [Expr]}, Meta, Args}, S) when is_list(Args) ->
%% Literals
translate(List, S) when is_list(List) ->
translate_list(List, S, []);
translate_list(List, S, [], 0);
translate({Left, Right}, S) ->
{TArgs, SE} = translate_args([Left, Right], S),
{{tuple, 0, TArgs}, SE};
{[TLeft, TRight], SE} = translate_args([Left, Right], S),
{{tuple, binary_ann(TLeft, TRight), [TLeft, TRight]}, SE};
translate(Other, S) ->
{elixir_erl:elixir_to_erl(Other), S}.
@@ -274,20 +274,32 @@ translate_case(Meta, Expr, Opts, S) ->
{TClauses, SC} = elixir_erl_clauses:clauses(Clauses, SE),
{{'case', ?ann(Meta), TExpr, TClauses}, SC}.
translate_list([{'|', _, [_, _]=Args}], Acc, List) ->
translate_list([{'|', _, [_, _]=Args}], Acc, List, Ann) ->
{[TLeft, TRight], TAcc} = lists:mapfoldl(fun translate/2, Acc, Args),
{build_list([TLeft | List], TRight), TAcc};
translate_list([H | T], Acc, List) ->
TAnn = if Ann == 0 -> binary_ann(TLeft, TRight); true -> Ann end,
{build_list([TLeft | List], TRight, TAnn), TAcc};
translate_list([H | T], Acc, List, Ann) ->
{TH, TAcc} = translate(H, Acc),
translate_list(T, TAcc, [TH | List]);
translate_list([], Acc, List) ->
{build_list(List, {nil, 0}), Acc}.
TAnn = if Ann == 0 -> element(2, TH); true -> Ann end,
translate_list(T, TAcc, [TH | List], TAnn);
translate_list([], Acc, List, Ann) ->
{build_list(List, {nil, 0}, Ann), Acc}.
build_list([H | T], Acc) ->
build_list(T, {cons, 0, H, Acc});
build_list([], Acc) ->
build_list([H | T], Acc, Ann) ->
build_list(T, {cons, Ann, H, Acc}, Ann);
build_list([], Acc, _Ann) ->
Acc.
binary_ann(Left, Right) ->
AnnLeft = element(2, Right),
AnnRight = element(2, Left),
if
AnnLeft /= 0 -> AnnLeft;
AnnRight /= 0 -> AnnRight;
true -> 0
end.
%% Pack a list of expressions from a block.
unblock({'block', _, Exprs}) -> Exprs;
unblock(Expr) -> [Expr].
+6 -10
View File
@@ -1161,23 +1161,19 @@ format_error({invalid_alias, Expr}) ->
"it at runtime. If instead you wanted to invoke a function or access a field, "
"wrap the function or field name in double quotes",
io_lib:format(Message, ['Elixir.Macro':to_string(Expr)]);
format_error({op_ambiguity, Name, {Op, _, [Arg]}}) ->
format_error({op_ambiguity, Name, Arg}) ->
NameString = atom_to_binary(Name, utf8),
OpString = atom_to_binary(Op, utf8),
ArgString = 'Elixir.Macro':to_string(Arg),
Message =
"\"~ts ~ts~ts\" looks like a function call but there is a variable named \"~ts\".\n"
"\"~ts ~ts\" looks like a function call but there is a variable named \"~ts\". "
"If you want to perform a function call, use parentheses:\n"
"\n"
" ~ts(~ts~ts)\n"
" ~ts(~ts)\n"
"\n"
"If you want to perform an operation on the variable ~ts, use even spaces instead:\n"
"\n"
" ~ts ~ts ~ts",
io_lib:format(Message, [NameString, OpString, ArgString, NameString,
NameString, OpString, ArgString, NameString,
NameString, OpString, ArgString]);
"If you want to perform an operation on the variable ~ts, use spaces "
"around the unary operator",
io_lib:format(Message, [NameString, ArgString, NameString, NameString, ArgString, NameString]);
format_error({invalid_clauses, Name}) ->
Message =
"the function \"~ts\" cannot handle clauses with the -> operator because it is not a macro. "
+49 -23
View File
@@ -20,7 +20,7 @@ Nonterminals
call_args_no_parens_comma_expr call_args_no_parens_all call_args_no_parens_many
call_args_no_parens_many_strict
stab stab_eoe stab_expr stab_op_eol_and_expr stab_parens_many
kw_eol kw_base kw call_args_no_parens_kw_expr call_args_no_parens_kw
kw_eol kw_base kw_data kw_call call_args_no_parens_kw_expr call_args_no_parens_kw
dot_op dot_alias dot_bracket_identifier dot_call_identifier
dot_identifier dot_op_identifier dot_do_identifier dot_paren_identifier
do_block fn_eoe do_eoe end_eoe block_eoe block_item block_list
@@ -285,9 +285,9 @@ number -> char : handle_number(?exprs('$1'), '$1', number_value('$1')).
parens_call -> dot_call_identifier call_args_parens : build_parens('$1', '$2', {[], []}).
parens_call -> dot_call_identifier call_args_parens call_args_parens : build_nested_parens('$1', '$2', '$3', {[], []}).
bracket_arg -> open_bracket kw close_bracket : build_list('$1', '$2', '$3').
bracket_arg -> open_bracket container_expr close_bracket : build_list('$1', '$2', '$3').
bracket_arg -> open_bracket container_expr ',' close_bracket : build_list('$1', '$2', '$4').
bracket_arg -> open_bracket kw_data close_bracket : build_access_arg('$1', '$2', '$3').
bracket_arg -> open_bracket container_expr close_bracket : build_access_arg('$1', '$2', '$3').
bracket_arg -> open_bracket container_expr ',' close_bracket : build_access_arg('$1', '$2', '$4').
bracket_expr -> dot_bracket_identifier bracket_arg : build_access(build_no_parens('$1', nil), '$2').
bracket_expr -> access_expr bracket_arg : build_access('$1', '$2').
@@ -513,7 +513,7 @@ container_args_base -> container_args_base ',' container_expr : ['$3' | '$1'].
container_args -> container_args_base : reverse('$1').
container_args -> container_args_base ',' : reverse('$1').
container_args -> container_args_base ',' kw : reverse(['$3' | '$1']).
container_args -> container_args_base ',' kw_call : reverse(['$3' | '$1']).
% Function calls with parentheses
@@ -528,16 +528,16 @@ call_args_parens -> open_paren ')' :
{newlines_pair('$1', '$2'), []}.
call_args_parens -> open_paren no_parens_expr close_paren :
{newlines_pair('$1', '$3'), ['$2']}.
call_args_parens -> open_paren kw_base close_paren :
{newlines_pair('$1', '$3'), [reverse('$2')]}.
call_args_parens -> open_paren kw_base ',' close_paren :
warn_trailing_comma('$3'), {newlines_pair('$1', '$4'), [reverse('$2')]}.
call_args_parens -> open_paren kw_call close_paren :
{newlines_pair('$1', '$3'), ['$2']}.
call_args_parens -> open_paren kw_call ',' close_paren :
warn_trailing_comma('$3'), {newlines_pair('$1', '$4'), ['$2']}.
call_args_parens -> open_paren call_args_parens_base close_paren :
{newlines_pair('$1', '$3'), reverse('$2')}.
call_args_parens -> open_paren call_args_parens_base ',' kw_base close_paren :
{newlines_pair('$1', '$5'), reverse([reverse('$4') | '$2'])}.
call_args_parens -> open_paren call_args_parens_base ',' kw_base ',' close_paren :
warn_trailing_comma('$5'), {newlines_pair('$1', '$6'), reverse([reverse('$4') | '$2'])}.
call_args_parens -> open_paren call_args_parens_base ',' kw_call close_paren :
{newlines_pair('$1', '$5'), reverse(['$4' | '$2'])}.
call_args_parens -> open_paren call_args_parens_base ',' kw_call ',' close_paren :
warn_trailing_comma('$5'), {newlines_pair('$1', '$6'), reverse(['$4' | '$2'])}.
% KV
@@ -551,21 +551,27 @@ kw_eol -> kw_identifier_unsafe eol : build_quoted_atom('$1', false, [{format, ke
kw_base -> kw_eol container_expr : [{'$1', '$2'}].
kw_base -> kw_base ',' kw_eol container_expr : [{'$3', '$4'} | '$1'].
kw -> kw_base : reverse('$1').
kw -> kw_base ',' : reverse('$1').
kw_call -> kw_base : reverse('$1').
kw_call -> kw_base ',' : reverse('$1').
kw_call -> kw_base ',' matched_expr : error_bad_keyword_call_follow_up('$2').
kw_data -> kw_base : reverse('$1').
kw_data -> kw_base ',' : reverse('$1').
kw_data -> kw_base ',' matched_expr : error_bad_keyword_data_follow_up('$2').
call_args_no_parens_kw_expr -> kw_eol matched_expr : {'$1', '$2'}.
call_args_no_parens_kw_expr -> kw_eol no_parens_expr : {'$1', '$2'}.
call_args_no_parens_kw -> call_args_no_parens_kw_expr : ['$1'].
call_args_no_parens_kw -> call_args_no_parens_kw_expr ',' call_args_no_parens_kw : ['$1' | '$3'].
call_args_no_parens_kw -> call_args_no_parens_kw_expr ',' matched_expr : error_bad_keyword_call_follow_up('$2').
% Lists
list_args -> kw : '$1'.
list_args -> kw_data : '$1'.
list_args -> container_args_base : reverse('$1').
list_args -> container_args_base ',' : reverse('$1').
list_args -> container_args_base ',' kw : reverse('$1', '$3').
list_args -> container_args_base ',' kw_data : reverse('$1', '$3').
list -> open_bracket ']' : build_list('$1', [], '$2').
list -> open_bracket list_args close_bracket : build_list('$1', '$2', '$3').
@@ -595,8 +601,8 @@ assoc_expr -> parens_call : '$1'.
assoc_update -> matched_expr pipe_op_eol assoc_expr : {'$2', '$1', ['$3']}.
assoc_update -> unmatched_expr pipe_op_eol assoc_expr : {'$2', '$1', ['$3']}.
assoc_update_kw -> matched_expr pipe_op_eol kw : {'$2', '$1', '$3'}.
assoc_update_kw -> unmatched_expr pipe_op_eol kw : {'$2', '$1', '$3'}.
assoc_update_kw -> matched_expr pipe_op_eol kw_data : {'$2', '$1', '$3'}.
assoc_update_kw -> unmatched_expr pipe_op_eol kw_data : {'$2', '$1', '$3'}.
assoc_base -> assoc_expr : ['$1'].
assoc_base -> assoc_base ',' assoc_expr : ['$3' | '$1'].
@@ -607,9 +613,9 @@ assoc -> assoc_base ',' : reverse('$1').
map_op -> '%{}' : '$1'.
map_op -> '%{}' eol : '$1'.
map_close -> kw close_curly : {'$1', '$2'}.
map_close -> kw_data close_curly : {'$1', '$2'}.
map_close -> assoc close_curly : {'$1', '$2'}.
map_close -> assoc_base ',' kw close_curly : {reverse('$1', '$3'), '$4'}.
map_close -> assoc_base ',' kw_data close_curly : {reverse('$1', '$3'), '$4'}.
map_args -> open_curly '}' : build_map('$1', [], '$2').
map_args -> open_curly map_close : build_map('$1', element(1, '$2'), element(2, '$2')).
@@ -882,8 +888,10 @@ build_fn(Fn, Stab, End) ->
%% Access
build_access(Expr, {List, Location}) ->
Meta = meta_from_location(Location),
build_access_arg(Left, Args, Right) ->
{Args, newlines_pair(Left, Right) ++ meta_from_token(Left)}.
build_access(Expr, {List, Meta}) ->
{{'.', Meta, ['Elixir.Access', get]}, Meta, [Expr, List]}.
%% Interpolation aware
@@ -1051,6 +1059,24 @@ error_bad_atom(Token) ->
"If the '.' was meant to be part of the atom's name, "
"the atom name must be quoted. Syntax error before: ", "'.'").
error_bad_keyword_call_follow_up(Token) ->
return_error(meta_from_token(Token),
"unexpected expression after keyword list. Keyword lists must always come as the last argument. Therefore, this is not allowed:\n\n"
" function_call(1, some: :option, 2)\n\n"
"Instead, wrap the keyword in brackets:\n\n"
" function_call(1, [some: :option], 2)\n\n"
"Syntax error after: ", "','").
error_bad_keyword_data_follow_up(Token) ->
return_error(meta_from_token(Token),
"unexpected expression after keyword list. Keyword lists must always come last in lists and maps. Therefore, this is not allowed:\n\n"
" [some: :value, :another]\n"
" %{some: :value, another => value}\n\n"
"Instead, reorder it to be the last entry:\n\n"
" [:another, some: :value]\n"
" %{another => value, some: :value}\n\n"
"Syntax error after: ", "','").
error_no_parens_strict(Token) ->
return_error(meta_from_token(Token), "unexpected parentheses. If you are making a "
"function call, do not insert spaces between the function name and the "
@@ -128,17 +128,84 @@ defmodule Date.RangeTest do
test "step is a non-zero integer" do
step = 1.0
message = ~r"the step must be an integer different than zero"
message = ~r"the step must be a non-zero integer"
assert_raise ArgumentError, message, fn ->
Date.range(~D[2000-01-01], ~D[2000-01-31], step)
end
step = 0
message = ~r"the step must be an integer different than zero"
message = ~r"the step must be a non-zero integer"
assert_raise ArgumentError, message, fn ->
Date.range(~D[2000-01-01], ~D[2000-01-31], step)
end
end
describe "old date ranges" do
test "inspect" do
asc = %{
__struct__: Date.Range,
first: ~D[2021-07-14],
first_in_iso_days: 738_350,
last: ~D[2021-07-17],
last_in_iso_days: 738_353
}
desc = %{
__struct__: Date.Range,
first: ~D[2021-07-17],
first_in_iso_days: 738_353,
last: ~D[2021-07-14],
last_in_iso_days: 738_350
}
assert inspect(asc) == "#DateRange<~D[2021-07-14], ~D[2021-07-17]>"
assert inspect(desc) == "#DateRange<~D[2021-07-17], ~D[2021-07-14], -1>"
end
test "enumerable" do
asc = %{
__struct__: Date.Range,
first: ~D[2021-07-14],
first_in_iso_days: 738_350,
last: ~D[2021-07-17],
last_in_iso_days: 738_353
}
desc = %{
__struct__: Date.Range,
first: ~D[2021-07-17],
first_in_iso_days: 738_353,
last: ~D[2021-07-14],
last_in_iso_days: 738_350
}
# member? implementations tests also empty?
assert Enumerable.member?(asc, ~D[2021-07-15])
assert {:ok, 4, _} = Enumerable.slice(asc)
assert Enum.reduce(asc, [], fn x, acc -> [x | acc] end) == [
~D[2021-07-17],
~D[2021-07-16],
~D[2021-07-15],
~D[2021-07-14]
]
assert Enum.count(asc) == 4
# member? implementations tests also empty?
assert Enumerable.member?(desc, ~D[2021-07-15])
assert {:ok, 4, _} = Enumerable.slice(desc)
assert Enum.reduce(desc, [], fn x, acc -> [x | acc] end) == [
~D[2021-07-14],
~D[2021-07-15],
~D[2021-07-16],
~D[2021-07-17]
]
assert Enum.count(desc) == 4
end
end
end
@@ -1215,7 +1215,9 @@ defmodule Code.Formatter.CallsTest do
end
test "with keywords" do
assert_format "expr[foo: bar, baz: bat]", "expr[[foo: bar, baz: bat]]"
assert_format "expr[[]]", "expr[[]]"
assert_format "expr[foo: bar, baz: bat]", "expr[foo: bar, baz: bat]"
assert_format "expr[[foo: bar, baz: bat]]", "expr[[foo: bar, baz: bat]]"
end
end
end
@@ -358,6 +358,30 @@ defmodule Code.Formatter.CommentsTest do
end
end
describe "access" do
test "before and after single arg" do
assert_same ~S"""
foo[
# bar
baz
# bat
]
"""
end
test "before and after keywords" do
assert_same ~S"""
foo[
# bar
one: :two,
# baz
three: :four
# bat
]
"""
end
end
describe "calls" do
test "local with parens inside before and after" do
assert_same ~S"""
@@ -548,6 +548,21 @@ defmodule Code.Formatter.IntegrationTest do
"""
end
test "multiline expression inside interpolation" do
bad = ~S"""
Logger.info("Example: #{
inspect(%{
a: 1,
b: 2
})
}")
"""
assert_format bad, ~S"""
Logger.info("Example: #{inspect(%{a: 1, b: 2})}")
"""
end
test "comment inside operator with when" do
bad = """
raise function(x) ::
@@ -107,6 +107,14 @@ defmodule Code.Formatter.LiteralsTest do
assert_format ~S[:"++"], ~S[:++]
end
test "quoted operators" do
assert_same ~S[:"::"]
assert_same ~S[:"..//"]
assert_format ~S[:..//], ~S[:"..//"]
assert_format ~S{[..//: 1]}, ~S{["..//": 1]}
assert_same ~S{["..//": 1]}
end
test "uses double quotes even when single quotes are used" do
assert_format ~S[:'foo bar'], ~S[:"foo bar"]
end
+144
View File
@@ -21,12 +21,156 @@ defmodule CodeTest do
Code.eval_quoted(contents, [], file: "sample.ex", line: 13)
describe "cursor_context/2" do
test "expressions" do
assert Code.cursor_context([]) == :expr
assert Code.cursor_context("++") == :expr
assert Code.cursor_context(",") == :expr
assert Code.cursor_context("[") == :expr
assert Code.cursor_context("hello: ") == :expr
assert Code.cursor_context("\n") == :expr
assert Code.cursor_context('\n') == :expr
assert Code.cursor_context("\n\n") == :expr
assert Code.cursor_context('\n\n') == :expr
end
test "local_or_var" do
assert Code.cursor_context("hello_wo") == {:local_or_var, 'hello_wo'}
assert Code.cursor_context("hello_world?") == {:local_or_var, 'hello_world?'}
assert Code.cursor_context("hello_world!") == {:local_or_var, 'hello_world!'}
assert Code.cursor_context("hello/wor") == {:local_or_var, 'wor'}
assert Code.cursor_context("hello..wor") == {:local_or_var, 'wor'}
assert Code.cursor_context("hello::wor") == {:local_or_var, 'wor'}
assert Code.cursor_context("[hello_wo") == {:local_or_var, 'hello_wo'}
assert Code.cursor_context("hellò_wó") == {:local_or_var, 'hellò_wó'}
end
test "dot" do
assert Code.cursor_context("hello.") == {:dot, {:var, 'hello'}, ''}
assert Code.cursor_context(":hello.") == {:dot, {:unquoted_atom, 'hello'}, ''}
assert Code.cursor_context("nested.map.") == {:dot, {:dot, {:var, 'nested'}, 'map'}, ''}
assert Code.cursor_context("Hello.") == {:dot, {:alias, 'Hello'}, ''}
assert Code.cursor_context("Hello.World.") == {:dot, {:alias, 'Hello.World'}, ''}
assert Code.cursor_context("Hello.wor") == {:dot, {:alias, 'Hello'}, 'wor'}
assert Code.cursor_context("hello.wor") == {:dot, {:var, 'hello'}, 'wor'}
assert Code.cursor_context(":hello.wor") == {:dot, {:unquoted_atom, 'hello'}, 'wor'}
assert Code.cursor_context("@hello.wor") == {:dot, {:module_attribute, 'hello'}, 'wor'}
assert Code.cursor_context("nested.map.wor") ==
{:dot, {:dot, {:var, 'nested'}, 'map'}, 'wor'}
end
test "local_arity" do
assert Code.cursor_context("hello/") == {:local_arity, 'hello'}
end
test "local_call" do
assert Code.cursor_context("hello\s") == {:local_call, 'hello'}
assert Code.cursor_context("hello\t") == {:local_call, 'hello'}
assert Code.cursor_context("hello(") == {:local_call, 'hello'}
assert Code.cursor_context("hello(\s") == {:local_call, 'hello'}
assert Code.cursor_context("hello(\t") == {:local_call, 'hello'}
end
test "dot_arity" do
assert Code.cursor_context("Foo.hello/") == {:dot_arity, {:alias, 'Foo'}, 'hello'}
assert Code.cursor_context(":foo.hello/") == {:dot_arity, {:unquoted_atom, 'foo'}, 'hello'}
assert Code.cursor_context("foo.hello/") == {:dot_arity, {:var, 'foo'}, 'hello'}
assert Code.cursor_context("@f.hello/") == {:dot_arity, {:module_attribute, 'f'}, 'hello'}
end
test "dot_call" do
assert Code.cursor_context("Foo.hello\s") == {:dot_call, {:alias, 'Foo'}, 'hello'}
assert Code.cursor_context("Foo.hello\t") == {:dot_call, {:alias, 'Foo'}, 'hello'}
assert Code.cursor_context("Foo.hello(") == {:dot_call, {:alias, 'Foo'}, 'hello'}
assert Code.cursor_context("Foo.hello(\s") == {:dot_call, {:alias, 'Foo'}, 'hello'}
assert Code.cursor_context("Foo.hello(\t") == {:dot_call, {:alias, 'Foo'}, 'hello'}
assert Code.cursor_context(":foo.hello\s") == {:dot_call, {:unquoted_atom, 'foo'}, 'hello'}
assert Code.cursor_context(":foo.hello\t") == {:dot_call, {:unquoted_atom, 'foo'}, 'hello'}
assert Code.cursor_context(":foo.hello(") == {:dot_call, {:unquoted_atom, 'foo'}, 'hello'}
assert Code.cursor_context(":foo.hello(\s") == {:dot_call, {:unquoted_atom, 'foo'}, 'hello'}
assert Code.cursor_context(":foo.hello(\t") == {:dot_call, {:unquoted_atom, 'foo'}, 'hello'}
assert Code.cursor_context("foo.hello\s") == {:dot_call, {:var, 'foo'}, 'hello'}
assert Code.cursor_context("foo.hello\t") == {:dot_call, {:var, 'foo'}, 'hello'}
assert Code.cursor_context("foo.hello(") == {:dot_call, {:var, 'foo'}, 'hello'}
assert Code.cursor_context("foo.hello(\s") == {:dot_call, {:var, 'foo'}, 'hello'}
assert Code.cursor_context("foo.hello(\t") == {:dot_call, {:var, 'foo'}, 'hello'}
assert Code.cursor_context("@f.hello\s") == {:dot_call, {:module_attribute, 'f'}, 'hello'}
assert Code.cursor_context("@f.hello\t") == {:dot_call, {:module_attribute, 'f'}, 'hello'}
assert Code.cursor_context("@f.hello(") == {:dot_call, {:module_attribute, 'f'}, 'hello'}
assert Code.cursor_context("@f.hello(\s") == {:dot_call, {:module_attribute, 'f'}, 'hello'}
assert Code.cursor_context("@f.hello(\t") == {:dot_call, {:module_attribute, 'f'}, 'hello'}
end
test "alias" do
assert Code.cursor_context("HelloWor") == {:alias, 'HelloWor'}
assert Code.cursor_context("Hello.Wor") == {:alias, 'Hello.Wor'}
assert Code.cursor_context("Hello::Wor") == {:alias, 'Wor'}
assert Code.cursor_context("Hello..Wor") == {:alias, 'Wor'}
assert Code.cursor_context("%Hello.Wor") == {:alias, 'Hello.Wor'}
end
test "unquoted atom" do
assert Code.cursor_context(":") == {:unquoted_atom, ''}
assert Code.cursor_context(":HelloWor") == {:unquoted_atom, 'HelloWor'}
assert Code.cursor_context(":HelloWór") == {:unquoted_atom, 'HelloWór'}
assert Code.cursor_context(":hello_wor") == {:unquoted_atom, 'hello_wor'}
assert Code.cursor_context(":Óla_mundo") == {:unquoted_atom, 'Óla_mundo'}
assert Code.cursor_context("foo:hello_wor") == {:unquoted_atom, 'hello_wor'}
end
test "module attribute" do
assert Code.cursor_context("@") == {:module_attribute, ''}
assert Code.cursor_context("@hello_wo") == {:module_attribute, 'hello_wo'}
end
test "none" do
# Containers
assert Code.cursor_context(")") == :none
assert Code.cursor_context("}") == :none
# Numbers
assert Code.cursor_context("123") == :none
assert Code.cursor_context("123?") == :none
assert Code.cursor_context("123!") == :none
assert Code.cursor_context("123var?") == :none
assert Code.cursor_context("0x") == :none
# Dots
assert Code.cursor_context("Mundo.Óla") == :none
assert Code.cursor_context(":hello.World") == :none
# Aliases
assert Code.cursor_context("Hello::Wór") == :none
assert Code.cursor_context("ÓlaMundo") == :none
assert Code.cursor_context("HelloWór") == :none
assert Code.cursor_context("@Hello") == :none
assert Code.cursor_context("Hello(") == :none
assert Code.cursor_context("Hello ") == :none
assert Code.cursor_context("hello.World") == :none
end
test "newlines" do
assert Code.cursor_context("this+does-not*matter\nHello.") == {:dot, {:alias, 'Hello'}, ''}
assert Code.cursor_context('this+does-not*matter\nHello.') == {:dot, {:alias, 'Hello'}, ''}
end
end
describe "eval_string/1,2,3" do
test "correctly evaluates a string of code" do
assert Code.eval_string("1 + 2") == {3, []}
assert Code.eval_string("two = 1 + 1") == {2, [two: 2]}
end
test "keeps bindings on optimized evals" do
assert Code.eval_string("import Enum", x: 1) == {Enum, [x: 1]}
end
test "supports a %Macro.Env{} struct as the third argument" do
assert {3, _} = Code.eval_string("a + b", [a: 1, b: 2], __ENV__)
end
+15 -1
View File
@@ -230,6 +230,18 @@ defmodule EnumTest do
assert Enum.dedup([nil]) == [nil]
end
test "dedup/1 with streams" do
dedup_stream = fn list -> list |> Stream.map(& &1) |> Enum.dedup() end
assert dedup_stream.([1, 1, 2, 1, 1, 2, 1]) == [1, 2, 1, 2, 1]
assert dedup_stream.([2, 1, 1, 2, 1]) == [2, 1, 2, 1]
assert dedup_stream.([1, 2, 3, 4]) == [1, 2, 3, 4]
assert dedup_stream.([1, 1.0, 2.0, 2]) == [1, 1.0, 2.0, 2]
assert dedup_stream.([]) == []
assert dedup_stream.([nil, nil, true, {:value, true}]) == [nil, true, {:value, true}]
assert dedup_stream.([nil]) == [nil]
end
test "dedup_by/2" do
assert Enum.dedup_by([{1, :x}, {2, :y}, {2, :z}, {1, :x}], fn {x, _} -> x end) ==
[{1, :x}, {2, :y}, {1, :x}]
@@ -384,6 +396,8 @@ defmodule EnumTest do
test "into/2" do
assert Enum.into([a: 1, b: 2], %{}) == %{a: 1, b: 2}
assert Enum.into([a: 1, b: 2], %{c: 3}) == %{a: 1, b: 2, c: 3}
assert Enum.into(MapSet.new(a: 1, b: 2), %{}) == %{a: 1, b: 2}
assert Enum.into(MapSet.new(a: 1, b: 2), %{c: 3}) == %{a: 1, b: 2, c: 3}
assert Enum.into(%{a: 1, b: 2}, []) == [a: 1, b: 2]
assert Enum.into(1..3, []) == [1, 2, 3]
assert Enum.into(["H", "i"], "") == "Hi"
@@ -393,7 +407,7 @@ defmodule EnumTest do
assert Enum.into([1, 2, 3], [], fn x -> x * 2 end) == [2, 4, 6]
assert Enum.into([1, 2, 3], "numbers: ", &to_string/1) == "numbers: 123"
assert_raise FunctionClauseError, fn ->
assert_raise MatchError, fn ->
Enum.into([2, 3], %{a: 1}, & &1)
end
end
+5 -4
View File
@@ -470,11 +470,12 @@ defmodule ExceptionTest do
* min/1
"""
assert blame_message(:erlang, & &1.gt_cookie()) == """
function :erlang.gt_cookie/0 is undefined or private. Did you mean one of:
assert blame_message(:erlang, & &1.hal()) == """
function :erlang.hal/0 is undefined or private. Did you mean one of:
* get_cookie/0
* set_cookie/2
* halt/0
* halt/1
* halt/2
"""
end
+5 -14
View File
@@ -152,7 +152,7 @@ defmodule IntegerTest do
assert_raise ArgumentError, "invalid base nil", fn -> Integer.parse("2", nil) end
end
test "to_string/1" do
test "to_string/2" do
assert Integer.to_string(42) == "42"
assert Integer.to_string(+42) == "42"
assert Integer.to_string(-42) == "-42"
@@ -163,9 +163,7 @@ defmodule IntegerTest do
Integer.to_string(n)
end
end
end
test "to_string/2" do
assert Integer.to_string(42, 2) == "101010"
assert Integer.to_string(42, 10) == "42"
assert Integer.to_string(42, 16) == "2A"
@@ -190,7 +188,9 @@ defmodule IntegerTest do
end
end
test "to_charlist/1" do
test "to_charlist/2" do
module = Integer
assert Integer.to_charlist(42) == '42'
assert Integer.to_charlist(+42) == '42'
assert Integer.to_charlist(-42) == '-42'
@@ -201,14 +201,10 @@ defmodule IntegerTest do
Integer.to_charlist(n)
end
end
end
test "to_char_list/1" do
module = Integer
assert module.to_char_list(42) == '42'
end
assert module.to_char_list(42, 2) == '101010'
test "to_charlist/2" do
assert Integer.to_charlist(42, 2) == '101010'
assert Integer.to_charlist(42, 10) == '42'
assert Integer.to_charlist(42, 16) == '2A'
@@ -233,11 +229,6 @@ defmodule IntegerTest do
end
end
test "to_char_list/2" do
module = Integer
assert module.to_char_list(42, 2) == '101010'
end
test "gcd/2" do
assert Integer.gcd(1, 5) == 1
assert Integer.gcd(2, 3) == 1
+5
View File
@@ -210,4 +210,9 @@ defmodule IOTest do
assert capture_io(fn -> IO.inspect(1, label: "foo") end) == "foo: 1\n"
assert capture_io(fn -> IO.inspect(1, label: :foo) end) == "foo: 1\n"
end
test "stream" do
assert IO.stream() == IO.stream(:stdio, :line)
assert IO.binstream() == IO.binstream(:stdio, :line)
end
end
@@ -177,6 +177,22 @@ defmodule Kernel.ErrorsTest do
def foo
end
'''
assert_eval_raise CompileError,
"nofile:10: implementation not provided for predefined def example/2",
'''
defmodule Kernel.ErrorsTest.FunctionTemplate do
defmacro __using__(_) do
quote do
def example(foo, bar \\\\ [])
end
end
end
defmodule Kernel.ErrorsTest.UseFunctionTemplate do
use Kernel.ErrorsTest.FunctionTemplate
end
'''
end
test "guard without definition" do
@@ -195,6 +211,24 @@ defmodule Kernel.ErrorsTest do
'foo = 1; %{put_in(foo.bar.baz, nil), foo}'
end
test "expression after keyword lists" do
assert_eval_raise SyntaxError,
~r"unexpected expression after keyword list",
'call foo: 1, :bar'
assert_eval_raise SyntaxError,
~r"unexpected expression after keyword list",
'call(foo: 1, :bar)'
assert_eval_raise SyntaxError,
~r"unexpected expression after keyword list",
'[foo: 1, :bar]'
assert_eval_raise SyntaxError,
~r"unexpected expression after keyword list",
'%{foo: 1, :bar => :bar}'
end
test "struct fields on defstruct" do
assert_eval_raise ArgumentError, "struct field names must be atoms, got: 1", '''
defmodule Kernel.ErrorsTest.StructFieldsOnDefstruct do
@@ -2538,10 +2538,10 @@ defmodule Kernel.ExpansionTest do
describe "op ambiguity" do
test "raises when a call is ambiguous" do
# We use string_to_quoted! here to avoid the formatter adding parentheses
message = ~r["a -1" looks like a function call but there is a variable named "a"]
assert_raise CompileError, message, fn ->
# We use string_to_quoted! here to avoid the formatter adding parentheses to "a -1".
code =
Code.string_to_quoted!("""
a = 1
@@ -2550,6 +2550,18 @@ defmodule Kernel.ExpansionTest do
expand(code)
end
message = ~r["a -1\.\.a \+ 1" looks like a function call but there is a variable named "a"]
assert_raise CompileError, message, fn ->
code =
Code.string_to_quoted!("""
a = 1
a -1 .. a + 1
""")
expand(code)
end
end
end
@@ -202,5 +202,20 @@ defmodule Kernel.LexicalTrackerTest do
assert URI in exports
refute URI in runtime
end
test "compile_env! does not add a compile dependency" do
{{compile, exports, runtime, _}, _binding} =
Code.eval_string("""
defmodule Kernel.LexicalTrackerTest.CompileEnvStruct do
Application.compile_env(:elixir, URI)
Application.compile_env(:elixir, [:foo, URI, :bar])
Kernel.LexicalTracker.references(__ENV__.lexical_tracker)
end |> elem(3)
""")
refute URI in compile
refute URI in exports
assert URI in runtime
end
end
end
@@ -43,7 +43,9 @@ defmodule Kernel.ParallelCompilerTest do
assert HelloWorld in modules
end)
assert profile =~ ~r"\[profile\] .*tmp/profile_time/bar.ex compiled in \d+ms"
assert profile =~
~r"\[profile\] [\s\d]{6}ms compiling \+ 0ms waiting for .*tmp/profile_time/bar.ex"
assert profile =~ ~r"\[profile\] Finished compilation cycle of 1 modules in \d+ms"
assert profile =~ ~r"\[profile\] Finished group pass check of 1 modules in \d+ms"
after
+30 -4
View File
@@ -17,13 +17,13 @@ defmodule Kernel.ParserTest do
describe "ternary ops" do
test "root" do
assert parse!("1..2//3") == {:..//, [line: 1], [1, 2, 3]}
assert parse!("(1..2)//3") == {:..//, [line: 1], [1, 2, 3]}
assert parse!("1..2//3") == {:"..//", [line: 1], [1, 2, 3]}
assert parse!("(1..2)//3") == {:"..//", [line: 1], [1, 2, 3]}
end
test "with do-blocks" do
assert parse!("foo do end..bar do end//baz do end") == {
:..//,
:"..//",
[line: 1],
[
{:foo, [line: 1], [[do: {:__block__, [], []}]]},
@@ -35,7 +35,7 @@ defmodule Kernel.ParserTest do
test "with no parens" do
assert parse!("1..foo do end//bar bat, baz") == {
:..//,
:"..//",
[line: 1],
[
1,
@@ -780,6 +780,32 @@ defmodule Kernel.ParserTest do
end
end
describe "down to Erlang" do
test "contains of non-literals" do
assert to_erl!("{:ok, make_ref()}") ==
{:tuple, 1,
[
{:atom, 0, :ok},
{:call, 1, {:remote, 1, {:atom, 0, :erlang}, {:atom, 1, :make_ref}}, []}
]}
assert to_erl!("[:ok, make_ref()]") ==
{:cons, 1, {:atom, 0, :ok},
{:cons, 1,
{:call, 1, {:remote, 1, {:atom, 0, :erlang}, {:atom, 1, :make_ref}}, []},
{nil, 0}}}
end
defp to_erl!(code) do
{expr, _, _} =
code
|> Code.string_to_quoted!()
|> :elixir.quoted_to_erl(:elixir.env_for_eval([]))
expr
end
end
defp parse!(string), do: Code.string_to_quoted!(string)
defp assert_token_missing(given_message, string) do
+6 -4
View File
@@ -327,12 +327,12 @@ defmodule MacroTest do
test "sigil call" do
assert Macro.to_string(quote(do: ~r"123")) == ~S/~r"123"/
assert Macro.to_string(quote(do: ~r"\n123")) == ~S/~r"\\n123"/
assert Macro.to_string(quote(do: ~r"12\"3")) == ~S/~r"12\\"3"/
assert Macro.to_string(quote(do: ~r"\n123")) == ~S/~r"\n123"/
assert Macro.to_string(quote(do: ~r"12\"3")) == ~S/~r"12\"3"/
assert Macro.to_string(quote(do: ~r/12\/3/u)) == ~S"~r/12\/3/u"
assert Macro.to_string(quote(do: ~r{\n123})) == ~S/~r{\\n123}/
assert Macro.to_string(quote(do: ~r{\n123})) == ~S/~r{\n123}/
assert Macro.to_string(quote(do: ~r((1\)(2\)3))) == ~S/~r((1\)(2\)3)/
assert Macro.to_string(quote(do: ~r{\n1{1\}23})) == ~S/~r{\\n1{1\}23}/
assert Macro.to_string(quote(do: ~r{\n1{1\}23})) == ~S/~r{\n1{1\}23}/
assert Macro.to_string(quote(do: ~r|12\|3|)) == ~S"~r|12\|3|"
assert Macro.to_string(quote(do: ~r[1#{two}3])) == ~S/~r[1#{two}3]/
@@ -1036,6 +1036,8 @@ defmodule MacroTest do
assert Macro.camelize("foo__bar") == "FooBar"
assert Macro.camelize("foo/bar") == "Foo.Bar"
assert Macro.camelize("Foo.Bar") == "Foo.Bar"
assert Macro.camelize("foo1_0") == "Foo10"
assert Macro.camelize("foo_123_4_567") == "Foo1234567"
assert Macro.camelize("FOO_BAR") == "FOO_BAR"
assert Macro.camelize("FOO.BAR") == "FOO.BAR"
assert Macro.camelize("") == ""
@@ -663,6 +663,31 @@ defmodule Module.Types.IntegrationTest do
assert_warnings(files, warning)
end
test "reports macro" do
files = %{
"a.ex" => """
defmodule A do
@deprecated "oops"
defmacro a, do: :ok
end
""",
"b.ex" => """
defmodule B do
require A
def b, do: A.a()
end
"""
}
warning = """
warning: A.a/0 is deprecated. oops
b.ex:3: B.b/0
"""
assert_warnings(files, warning)
end
end
defp assert_warnings(files, expected) when is_binary(expected) do
@@ -144,14 +144,14 @@ defmodule Module.Types.TypesTest do
assert string == """
incompatible types:
{var0} !~ var0
{var1} !~ var1
in expression:
# types_test.ex:1
{var} = var
where "var" was given the type {var0} in:
where "var" was given the type {var1} in:
# types_test.ex:1
{var} = var
+10
View File
@@ -50,6 +50,16 @@ defmodule PathTest do
assert Path.absname("\\\\host\\path") == "//host/path"
assert Path.absname("\\/host\\path") == "//host/path"
assert Path.absname("/\\host\\path") == "//host/path"
assert Path.absname("c:/") == "c:/"
assert Path.absname("c:/host/path") == "c:/host/path"
cwd = File.cwd!()
assert Path.absname(cwd |> String.split("/") |> hd()) == cwd
<<letter, _::binary>> = cwd
random = Enum.random(Enum.to_list(?c..?z) -- [letter])
assert Path.absname(<<random, ?:>>) == <<random, ?:, ?/>>
end
test "relative/1" do
+47 -2
View File
@@ -62,11 +62,11 @@ defmodule RangeTest do
test "step is a non-zero integer" do
step = 1.0
message = ~r"the step to be an integer different than zero"
message = ~r"the step to be a non-zero integer"
assert_raise ArgumentError, message, fn -> 1..3//step end
step = 0
message = ~r"the step to be an integer different than zero"
message = ~r"the step to be a non-zero integer"
assert_raise ArgumentError, message, fn -> 1..3//step end
end
@@ -94,4 +94,49 @@ defmodule RangeTest do
assert Range.disjoint?(1..1, 1..1) == false
end
end
describe "old ranges" do
test "inspect" do
asc = %{__struct__: Range, first: 1, last: 3}
desc = %{__struct__: Range, first: 3, last: 1}
assert inspect(asc) == "1..3"
assert inspect(desc) == "3..1//-1"
end
test "enum" do
asc = %{__struct__: Range, first: 1, last: 3}
desc = %{__struct__: Range, first: 3, last: 1}
assert Enum.to_list(asc) == [1, 2, 3]
assert Enum.member?(asc, 2)
assert Enum.count(asc) == 3
assert Enum.drop(asc, 1) == [2, 3]
assert Enum.slice([1, 2, 3, 4, 5, 6], asc) == [2, 3, 4]
# testing private Enum.aggregate
assert Enum.max(asc) == 3
assert Enum.sum(asc) == 6
assert Enum.min_max(asc) == {1, 3}
assert Enum.reduce(asc, 0, fn a, b -> a + b end) == 6
assert Enum.to_list(desc) == [3, 2, 1]
assert Enum.member?(desc, 2)
assert Enum.count(desc) == 3
assert Enum.drop(desc, 1) == [2, 1]
assert Enum.slice([1, 2, 3, 4, 5, 6], desc) == []
# testing private Enum.aggregate
assert Enum.max(desc) == 3
assert Enum.sum(desc) == 6
assert Enum.min_max(desc) == {1, 3}
assert Enum.reduce(desc, 0, fn a, b -> a + b end) == 6
end
test "string" do
asc = %{__struct__: Range, first: 1, last: 3}
desc = %{__struct__: Range, first: 3, last: 1}
assert String.slice("elixir", asc) == "lix"
assert String.slice("elixir", desc) == ""
end
end
end
+20
View File
@@ -36,10 +36,12 @@ defmodule RegistryTest do
{:ok, pid} = Registry.register(registry, "hello", :value)
assert is_pid(pid)
assert Registry.keys(registry, self()) == ["hello"]
assert Registry.values(registry, "hello", self()) == [:value]
assert {:error, {:already_registered, pid}} = Registry.register(registry, "hello", :value)
assert pid == self()
assert Registry.keys(registry, self()) == ["hello"]
assert Registry.values(registry, "hello", self()) == [:value]
{:ok, pid} = Registry.register(registry, "world", :value)
assert is_pid(pid)
@@ -49,11 +51,15 @@ defmodule RegistryTest do
test "has unique registrations across processes", %{registry: registry} do
{_, task} = register_task(registry, "hello", :value)
Process.link(Process.whereis(registry))
assert Registry.keys(registry, task) == ["hello"]
assert Registry.values(registry, "hello", task) == [:value]
assert {:error, {:already_registered, ^task}} =
Registry.register(registry, "hello", :recent)
assert Registry.keys(registry, self()) == []
assert Registry.values(registry, "hello", self()) == []
{:links, links} = Process.info(self(), :links)
assert Process.whereis(registry) in links
end
@@ -433,16 +439,30 @@ defmodule RegistryTest do
{:ok, pid} = Registry.register(registry, "hello", :value)
assert is_pid(pid)
assert Registry.keys(registry, self()) == ["hello"]
assert Registry.values(registry, "hello", self()) == [:value]
assert {:ok, pid} = Registry.register(registry, "hello", :value)
assert is_pid(pid)
assert Registry.keys(registry, self()) == ["hello", "hello"]
assert Registry.values(registry, "hello", self()) == [:value, :value]
{:ok, pid} = Registry.register(registry, "world", :value)
assert is_pid(pid)
assert Registry.keys(registry, self()) |> Enum.sort() == ["hello", "hello", "world"]
end
test "has duplicate registrations across processes", %{registry: registry} do
{_, task} = register_task(registry, "hello", :world)
assert Registry.keys(registry, self()) == []
assert Registry.keys(registry, task) == ["hello"]
assert Registry.values(registry, "hello", self()) == []
assert Registry.values(registry, "hello", task) == [:world]
assert {:ok, _pid} = Registry.register(registry, "hello", :value)
assert Registry.keys(registry, self()) == ["hello"]
assert Registry.values(registry, "hello", self()) == [:value]
end
test "compares using matches", %{registry: registry} do
{:ok, _} = Registry.register(registry, 1.0, :value)
{:ok, _} = Registry.register(registry, 1, :value)
+43 -13
View File
@@ -96,22 +96,21 @@ defmodule SystemTest do
end
test "cmd/3 (with options)" do
assert {["hello\r\n"], 0} =
System.cmd(
"cmd",
~w[/c echo hello],
into: [],
cd: File.cwd!(),
env: %{"foo" => "bar", "baz" => nil},
arg0: "echo",
stderr_to_stdout: true,
parallelism: true
)
opts = [
into: [],
cd: File.cwd!(),
env: %{"foo" => "bar", "baz" => nil},
arg0: "echo",
stderr_to_stdout: true,
parallelism: true
]
assert {["hello\r\n"], 0} = System.cmd("cmd", ~w[/c echo hello], opts)
end
@echo "echo-elixir-test"
@tag :tmp_dir
test "cmd/2 with absolute and relative paths", config do
test "cmd/3 with absolute and relative paths", config do
echo = Path.join(config.tmp_dir, @echo)
File.mkdir_p!(Path.dirname(echo))
File.cp!(System.find_executable("cmd"), echo)
@@ -128,6 +127,22 @@ defmodule SystemTest do
System.cmd(Path.join(File.cwd!(), @echo), ~w[/c echo hello], [{:arg0, "echo"}])
end)
end
test "shell/1" do
assert {"hello\r\n", 0} = System.shell("echo hello")
end
test "shell/2 (with options)" do
opts = [
into: [],
cd: File.cwd!(),
env: %{"foo" => "bar", "baz" => nil},
stderr_to_stdout: true,
parallelism: true
]
assert {["bar\r\n"], 0} = System.shell("echo %foo%", opts)
end
end
describe "Unix" do
@@ -152,7 +167,7 @@ defmodule SystemTest do
@echo "echo-elixir-test"
@tag :tmp_dir
test "cmd/2 with absolute and relative paths", config do
test "cmd/3 with absolute and relative paths", config do
echo = Path.join(config.tmp_dir, @echo)
File.mkdir_p!(Path.dirname(echo))
File.cp!(System.find_executable("echo"), echo)
@@ -169,6 +184,21 @@ defmodule SystemTest do
System.cmd(Path.join(File.cwd!(), @echo), ["hello"], [{:arg0, "echo"}])
end)
end
test "shell/1" do
assert {"hello\n", 0} = System.shell("echo hello")
end
test "shell/2 (with options)" do
opts = [
into: [],
cd: File.cwd!(),
env: %{"foo" => "bar", "baz" => nil},
stderr_to_stdout: true
]
assert {["bar\n"], 0} = System.shell("echo $foo", opts)
end
end
@tag :unix
+6
View File
@@ -717,6 +717,12 @@ defmodule TaskTest do
[ok: :ok] = Task.async_stream([1], fn _ -> :ok end, timeout: :infinity) |> Enum.to_list()
end
test "does not allow streaming with max_concurrency = 0" do
assert_raise ArgumentError, ":max_concurrency must be an integer greater than zero", fn ->
Task.async_stream([1], fn _ -> :ok end, max_concurrency: 0) |> Enum.to_list()
end
end
test "streams with fake down messages on the inbox" do
parent = self()
+3 -3
View File
@@ -133,7 +133,7 @@ defmodule TypespecTest do
end
test "type variable unused (singleton type variable)" do
assert_raise CompileError, ~r"type variable x is unused", fn ->
assert_raise CompileError, ~r"type variable x is used only once", fn ->
test_module do
@type foo(x) :: integer
end
@@ -168,8 +168,8 @@ defmodule TypespecTest do
end
end
test "spec variable unused (singleton type variable)" do
assert_raise CompileError, ~r"type variable x is unused", fn ->
test "spec variable used only once (singleton type variable)" do
assert_raise CompileError, ~r"type variable x is used only once", fn ->
test_module do
@spec foo(x, integer) :: integer when x: var
def foo(x, y), do: x + y
+527 -269
View File
@@ -1,5 +1,5 @@
# GraphemeBreakProperty-12.1.0.txt
# Date: 2019-03-10, 10:53:12 GMT
# GraphemeBreakProperty-13.0.0.txt
# Date: 2019-10-21, 14:30:35 GMT
# © 2019 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
@@ -9,7 +9,7 @@
# ================================================
# Property: Grapheme_Cluster_Break
# Property: Grapheme_Cluster_Break
# All code points not explicitly listed for Grapheme_Cluster_Break
# have the value Other (XX).
@@ -26,11 +26,13 @@
110BD ; Prepend # Cf KAITHI NUMBER SIGN
110CD ; Prepend # Cf KAITHI NUMBER SIGN ABOVE
111C2..111C3 ; Prepend # Lo [2] SHARADA SIGN JIHVAMULIYA..SHARADA SIGN UPADHMANIYA
1193F ; Prepend # Lo DIVES AKURU PREFIXED NASAL SIGN
11941 ; Prepend # Lo DIVES AKURU INITIAL RA
11A3A ; Prepend # Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA
11A84..11A89 ; Prepend # Lo [6] SOYOMBO SIGN JIHVAMULIYA..SOYOMBO CLUSTER-INITIAL LETTER SA
11D46 ; Prepend # Lo MASARAM GONDI REPHA
# Total code points: 22
# Total code points: 24
# ================================================
@@ -139,7 +141,7 @@ E01F0..E0FFF ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
0B3F ; Extend # Mn ORIYA VOWEL SIGN I
0B41..0B44 ; Extend # Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR
0B4D ; Extend # Mn ORIYA SIGN VIRAMA
0B56 ; Extend # Mn ORIYA AI LENGTH MARK
0B55..0B56 ; Extend # Mn [2] ORIYA SIGN OVERLINE..ORIYA AI LENGTH MARK
0B57 ; Extend # Mc ORIYA AU LENGTH MARK
0B62..0B63 ; Extend # Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL
0B82 ; Extend # Mn TAMIL SIGN ANUSVARA
@@ -169,6 +171,7 @@ E01F0..E0FFF ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
0D4D ; Extend # Mn MALAYALAM SIGN VIRAMA
0D57 ; Extend # Mc MALAYALAM AU LENGTH MARK
0D62..0D63 ; Extend # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL
0D81 ; Extend # Mn SINHALA SIGN CANDRABINDU
0DCA ; Extend # Mn SINHALA SIGN AL-LAKUNA
0DCF ; Extend # Mc SINHALA VOWEL SIGN AELA-PILLA
0DD2..0DD4 ; Extend # Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA
@@ -229,6 +232,7 @@ E01F0..E0FFF ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
1A7F ; Extend # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT
1AB0..1ABD ; Extend # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
1ABE ; Extend # Me COMBINING PARENTHESES OVERLAY
1ABF..1AC0 ; Extend # Mn [2] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER TURNED W BELOW
1B00..1B03 ; Extend # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG
1B34 ; Extend # Mn BALINESE SIGN REREKAN
1B35 ; Extend # Mc BALINESE VOWEL SIGN TEDUNG
@@ -275,6 +279,7 @@ A802 ; Extend # Mn SYLOTI NAGRI SIGN DVISVARA
A806 ; Extend # Mn SYLOTI NAGRI SIGN HASANTA
A80B ; Extend # Mn SYLOTI NAGRI SIGN ANUSVARA
A825..A826 ; Extend # Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E
A82C ; Extend # Mn SYLOTI NAGRI SIGN ALTERNATE HASANTA
A8C4..A8C5 ; Extend # Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU
A8E0..A8F1 ; Extend # Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA
A8FF ; Extend # Mn DEVANAGARI VOWEL SIGN AY
@@ -315,6 +320,7 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
10A3F ; Extend # Mn KHAROSHTHI VIRAMA
10AE5..10AE6 ; Extend # Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW
10D24..10D27 ; Extend # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
10EAB..10EAC ; Extend # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
10F46..10F50 ; Extend # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
11001 ; Extend # Mn BRAHMI SIGN ANUSVARA
11038..11046 ; Extend # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA
@@ -328,6 +334,7 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
11180..11181 ; Extend # Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA
111B6..111BE ; Extend # Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O
111C9..111CC ; Extend # Mn [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK
111CF ; Extend # Mn SHARADA SIGN INVERTED CANDRABINDU
1122F..11231 ; Extend # Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI
11234 ; Extend # Mn KHOJKI SIGN ANUSVARA
11236..11237 ; Extend # Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA
@@ -368,6 +375,10 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
11727..1172B ; Extend # Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER
1182F..11837 ; Extend # Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA
11839..1183A ; Extend # Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA
11930 ; Extend # Mc DIVES AKURU VOWEL SIGN AA
1193B..1193C ; Extend # Mn [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU
1193E ; Extend # Mn DIVES AKURU VIRAMA
11943 ; Extend # Mn DIVES AKURU SIGN NUKTA
119D4..119D7 ; Extend # Mn [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR
119DA..119DB ; Extend # Mn [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI
119E0 ; Extend # Mn NANDINAGARI SIGN VIRAMA
@@ -399,6 +410,7 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
16B30..16B36 ; Extend # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
16F4F ; Extend # Mn MIAO SIGN CONSONANT MODIFIER BAR
16F8F..16F92 ; Extend # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
16FE4 ; Extend # Mn KHITAN SMALL SCRIPT FILLER
1BC9D..1BC9E ; Extend # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
1D165 ; Extend # Mc MUSICAL SYMBOL COMBINING STEM
1D167..1D169 ; Extend # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3
@@ -426,7 +438,7 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
E0020..E007F ; Extend # Cf [96] TAG SPACE..CANCEL TAG
E0100..E01EF ; Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
# Total code points: 1970
# Total code points: 1984
# ================================================
@@ -539,6 +551,7 @@ ABEC ; SpacingMark # Mc MEETEI MAYEK LUM IYEK
11182 ; SpacingMark # Mc SHARADA SIGN VISARGA
111B3..111B5 ; SpacingMark # Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II
111BF..111C0 ; SpacingMark # Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA
111CE ; SpacingMark # Mc SHARADA VOWEL SIGN PRISHTHAMATRA E
1122C..1122E ; SpacingMark # Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II
11232..11233 ; SpacingMark # Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU
11235 ; SpacingMark # Mc KHOJKI SIGN VIRAMA
@@ -570,6 +583,11 @@ ABEC ; SpacingMark # Mc MEETEI MAYEK LUM IYEK
11726 ; SpacingMark # Mc AHOM VOWEL SIGN E
1182C..1182E ; SpacingMark # Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II
11838 ; SpacingMark # Mc DOGRA SIGN VISARGA
11931..11935 ; SpacingMark # Mc [5] DIVES AKURU VOWEL SIGN I..DIVES AKURU VOWEL SIGN E
11937..11938 ; SpacingMark # Mc [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O
1193D ; SpacingMark # Mc DIVES AKURU SIGN HALANTA
11940 ; SpacingMark # Mc DIVES AKURU MEDIAL YA
11942 ; SpacingMark # Mc DIVES AKURU MEDIAL RA
119D1..119D3 ; SpacingMark # Mc [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II
119DC..119DF ; SpacingMark # Mc [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA
119E4 ; SpacingMark # Mc NANDINAGARI VOWEL SIGN PRISHTHAMATRA E
@@ -586,10 +604,11 @@ ABEC ; SpacingMark # Mc MEETEI MAYEK LUM IYEK
11D96 ; SpacingMark # Mc GUNJALA GONDI SIGN VISARGA
11EF5..11EF6 ; SpacingMark # Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O
16F51..16F87 ; SpacingMark # Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI
16FF0..16FF1 ; SpacingMark # Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY
1D166 ; SpacingMark # Mc MUSICAL SYMBOL COMBINING SPRECHGESANG STEM
1D16D ; SpacingMark # Mc MUSICAL SYMBOL COMBINING AUGMENTATION DOT
# Total code points: 375
# Total code points: 388
# ================================================
@@ -1427,13 +1446,13 @@ D789..D7A3 ; LVT # Lo [27] HANGUL SYLLABLE HIG..HANGUL SYLLABLE HIH
# Total code points: 1
# emoji-data.txt
# Date: 2019-01-15, 12:10:05 GMT
# © 2019 Unicode®, Inc.
# Date: 2020-01-28, 20:52:38 GMT
# © 2020 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
# Emoji Data for UTS #51
# Version: 12.0
# Version: 13.0
#
# For documentation and usage, see http://www.unicode.org/reports/tr51
#
@@ -1444,264 +1463,503 @@ D789..D7A3 ; LVT # Lo [27] HANGUL SYLLABLE HIG..HANGUL SYLLABLE HIH
# Characters and sequences are listed in code point order. Users should be shown a more natural order.
# See the CLDR collation order for Emoji.
00A9 ; Extended_Pictographic# 1.1 [1] (©️) copyright
00AE ; Extended_Pictographic# 1.1 [1] (®️) registered
203C ; Extended_Pictographic# 1.1 [1] (‼️) double exclamation mark
2049 ; Extended_Pictographic# 3.0 [1] (⁉️) exclamation question mark
2122 ; Extended_Pictographic# 1.1 [1] (™️) trade mark
2139 ; Extended_Pictographic# 3.0 [1] (ℹ️) information
2194..2199 ; Extended_Pictographic# 1.1 [6] (↔️..↙️) left-right arrow..down-left arrow
21A9..21AA ; Extended_Pictographic# 1.1 [2] (↩️..↪️) right arrow curving left..left arrow curving right
231A..231B ; Extended_Pictographic# 1.1 [2] (⌚..⌛) watch..hourglass done
2328 ; Extended_Pictographic# 1.1 [1] (⌨️) keyboard
2388 ; Extended_Pictographic# 3.0 [1] (⎈) HELM SYMBOL
23CF ; Extended_Pictographic# 4.0 [1] (⏏️) eject button
23E9..23F3 ; Extended_Pictographic# 6.0 [11] (⏩..⏳) fast-forward button..hourglass not done
23F8..23FA ; Extended_Pictographic# 7.0 [3] (⏸️..⏺️) pause button..record button
24C2 ; Extended_Pictographic# 1.1 [1] (Ⓜ️) circled M
25AA..25AB ; Extended_Pictographic# 1.1 [2] (▪️..▫️) black small square..white small square
25B6 ; Extended_Pictographic# 1.1 [1] (▶️) play button
25C0 ; Extended_Pictographic# 1.1 [1] (◀️) reverse button
25FB..25FE ; Extended_Pictographic# 3.2 [4] (◻️..◾) white medium square..black medium-small square
2600..2605 ; Extended_Pictographic# 1.1 [6] (☀️..★) sun..BLACK STAR
2607..2612 ; Extended_Pictographic# 1.1 [12] (☇..☒) LIGHTNING..BALLOT BOX WITH X
2614..2615 ; Extended_Pictographic# 4.0 [2] (☔..☕) umbrella with rain drops..hot beverage
2616..2617 ; Extended_Pictographic# 3.2 [2] (☖..☗) WHITE SHOGI PIECE..BLACK SHOGI PIECE
2618 ; Extended_Pictographic# 4.1 [1] (☘️) shamrock
2619 ; Extended_Pictographic# 3.0 [1] (☙) REVERSED ROTATED FLORAL HEART BULLET
261A..266F ; Extended_Pictographic# 1.1 [86] (☚..♯) BLACK LEFT POINTING INDEX..MUSIC SHARP SIGN
2670..2671 ; Extended_Pictographic# 3.0 [2] (♰..♱) WEST SYRIAC CROSS..EAST SYRIAC CROSS
2672..267D ; Extended_Pictographic# 3.2 [12] (♲..♽) UNIVERSAL RECYCLING SYMBOL..PARTIALLY-RECYCLED PAPER SYMBOL
267E..267F ; Extended_Pictographic# 4.1 [2] (♾️..♿) infinity..wheelchair symbol
2680..2685 ; Extended_Pictographic# 3.2 [6] (⚀..⚅) DIE FACE-1..DIE FACE-6
2690..2691 ; Extended_Pictographic# 4.0 [2] (⚐..⚑) WHITE FLAG..BLACK FLAG
2692..269C ; Extended_Pictographic# 4.1 [11] (⚒️..⚜️) hammer and pick..fleur-de-lis
269D ; Extended_Pictographic# 5.1 [1] (⚝) OUTLINED WHITE STAR
269E..269F ; Extended_Pictographic# 5.2 [2] (⚞..⚟) THREE LINES CONVERGING RIGHT..THREE LINES CONVERGING LEFT
26A0..26A1 ; Extended_Pictographic# 4.0 [2] (⚠️..⚡) warning..high voltage
26A2..26B1 ; Extended_Pictographic# 4.1 [16] (⚢..⚱️) DOUBLED FEMALE SIGN..funeral urn
26B2 ; Extended_Pictographic# 5.0 [1] (⚲) NEUTER
26B3..26BC ; Extended_Pictographic# 5.1 [10] (⚳..⚼) CERES..SESQUIQUADRATE
26BD..26BF ; Extended_Pictographic# 5.2 [3] (⚽..⚿) soccer ball..SQUARED KEY
26C0..26C3 ; Extended_Pictographic# 5.1 [4] (⛀..⛃) WHITE DRAUGHTS MAN..BLACK DRAUGHTS KING
26C4..26CD ; Extended_Pictographic# 5.2 [10] (⛄..⛍) snowman without snow..DISABLED CAR
26CE ; Extended_Pictographic# 6.0 [1] (⛎) Ophiuchus
26CF..26E1 ; Extended_Pictographic# 5.2 [19] (⛏️..⛡) pick..RESTRICTED LEFT ENTRY-2
26E2 ; Extended_Pictographic# 6.0 [1] (⛢) ASTRONOMICAL SYMBOL FOR URANUS
26E3 ; Extended_Pictographic# 5.2 [1] (⛣) HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE
26E4..26E7 ; Extended_Pictographic# 6.0 [4] (⛤..⛧) PENTAGRAM..INVERTED PENTAGRAM
26E8..26FF ; Extended_Pictographic# 5.2 [24] (⛨..⛿) BLACK CROSS ON SHIELD..WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE
2700 ; Extended_Pictographic# 7.0 [1] (✀) BLACK SAFETY SCISSORS
2701..2704 ; Extended_Pictographic# 1.1 [4] (✁..✄) UPPER BLADE SCISSORS..WHITE SCISSORS
2705 ; Extended_Pictographic# 6.0 [1] (✅) check mark button
2708..2709 ; Extended_Pictographic# 1.1 [2] (✈️..✉️) airplane..envelope
270A..270B ; Extended_Pictographic# 6.0 [2] (✊..✋) raised fist..raised hand
270C..2712 ; Extended_Pictographic# 1.1 [7] (✌️..✒️) victory hand..black nib
2714 ; Extended_Pictographic# 1.1 [1] (✔️) check mark
2716 ; Extended_Pictographic# 1.1 [1] (✖️) multiplication sign
271D ; Extended_Pictographic# 1.1 [1] (✝️) latin cross
2721 ; Extended_Pictographic# 1.1 [1] (✡️) star of David
2728 ; Extended_Pictographic# 6.0 [1] (✨) sparkles
2733..2734 ; Extended_Pictographic# 1.1 [2] (✳️..✴️) eight-spoked asterisk..eight-pointed star
2744 ; Extended_Pictographic# 1.1 [1] (❄️) snowflake
2747 ; Extended_Pictographic# 1.1 [1] (❇️) sparkle
274C ; Extended_Pictographic# 6.0 [1] (❌) cross mark
274E ; Extended_Pictographic# 6.0 [1] (❎) cross mark button
2753..2755 ; Extended_Pictographic# 6.0 [3] (❓..❕) question mark..white exclamation mark
2757 ; Extended_Pictographic# 5.2 [1] (❗) exclamation mark
2763..2767 ; Extended_Pictographic# 1.1 [5] (❣️..❧) heart exclamation..ROTATED FLORAL HEART BULLET
2795..2797 ; Extended_Pictographic# 6.0 [3] (➕..➗) plus sign..division sign
27A1 ; Extended_Pictographic# 1.1 [1] (➡️) right arrow
27B0 ; Extended_Pictographic# 6.0 [1] (➰) curly loop
27BF ; Extended_Pictographic# 6.0 [1] (➿) double curly loop
2934..2935 ; Extended_Pictographic# 3.2 [2] (⤴️..⤵️) right arrow curving up..right arrow curving down
2B05..2B07 ; Extended_Pictographic# 4.0 [3] (⬅️..⬇️) left arrow..down arrow
2B1B..2B1C ; Extended_Pictographic# 5.1 [2] (⬛..⬜) black large square..white large square
2B50 ; Extended_Pictographic# 5.1 [1] (⭐) star
2B55 ; Extended_Pictographic# 5.2 [1] (⭕) hollow red circle
3030 ; Extended_Pictographic# 1.1 [1] (〰️) wavy dash
303D ; Extended_Pictographic# 3.2 [1] (〽️) part alternation mark
3297 ; Extended_Pictographic# 1.1 [1] (㊗️) Japanese “congratulations” button
3299 ; Extended_Pictographic# 1.1 [1] (㊙️) Japanese “secret” button
1F000..1F02B ; Extended_Pictographic# 5.1 [44] (🀀..🀫) MAHJONG TILE EAST WIND..MAHJONG TILE BACK
1F02C..1F02F ; Extended_Pictographic# NA [4] (🀬..🀯) <reserved-1F02C>..<reserved-1F02F>
1F030..1F093 ; Extended_Pictographic# 5.1[100] (🀰..🂓) DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06
1F094..1F09F ; Extended_Pictographic# NA [12] (🂔..🂟) <reserved-1F094>..<reserved-1F09F>
1F0A0..1F0AE ; Extended_Pictographic# 6.0 [15] (🂠..🂮) PLAYING CARD BACK..PLAYING CARD KING OF SPADES
1F0AF..1F0B0 ; Extended_Pictographic# NA [2] (🂯..🂰) <reserved-1F0AF>..<reserved-1F0B0>
1F0B1..1F0BE ; Extended_Pictographic# 6.0 [14] (🂱..🂾) PLAYING CARD ACE OF HEARTS..PLAYING CARD KING OF HEARTS
1F0BF ; Extended_Pictographic# 7.0 [1] (🂿) PLAYING CARD RED JOKER
1F0C0 ; Extended_Pictographic# NA [1] (🃀) <reserved-1F0C0>
1F0C1..1F0CF ; Extended_Pictographic# 6.0 [15] (🃁..🃏) PLAYING CARD ACE OF DIAMONDS..joker
1F0D0 ; Extended_Pictographic# NA [1] (🃐) <reserved-1F0D0>
1F0D1..1F0DF ; Extended_Pictographic# 6.0 [15] (🃑..🃟) PLAYING CARD ACE OF CLUBS..PLAYING CARD WHITE JOKER
1F0E0..1F0F5 ; Extended_Pictographic# 7.0 [22] (🃠..🃵) PLAYING CARD FOOL..PLAYING CARD TRUMP-21
1F0F6..1F0FF ; Extended_Pictographic# NA [10] (🃶..🃿) <reserved-1F0F6>..<reserved-1F0FF>
1F10D..1F10F ; Extended_Pictographic# NA [3] (🄍..🄏) <reserved-1F10D>..<reserved-1F10F>
1F12F ; Extended_Pictographic# 11.0 [1] (🄯) COPYLEFT SYMBOL
1F16C ; Extended_Pictographic# 12.0 [1] (🅬) RAISED MR SIGN
1F16D..1F16F ; Extended_Pictographic# NA [3] (🅭..🅯) <reserved-1F16D>..<reserved-1F16F>
1F170..1F171 ; Extended_Pictographic# 6.0 [2] (🅰️..🅱️) A button (blood type)..B button (blood type)
1F17E ; Extended_Pictographic# 6.0 [1] (🅾️) O button (blood type)
1F17F ; Extended_Pictographic# 5.2 [1] (🅿️) P button
1F18E ; Extended_Pictographic# 6.0 [1] (🆎) AB button (blood type)
1F191..1F19A ; Extended_Pictographic# 6.0 [10] (🆑..🆚) CL button..VS button
1F1AD..1F1E5 ; Extended_Pictographic# NA [57] (🆭..🇥) <reserved-1F1AD>..<reserved-1F1E5>
1F201..1F202 ; Extended_Pictographic# 6.0 [2] (🈁..🈂️) Japanese “here” button..Japanese “service charge” button
1F203..1F20F ; Extended_Pictographic# NA [13] (🈃..🈏) <reserved-1F203>..<reserved-1F20F>
1F21A ; Extended_Pictographic# 5.2 [1] (🈚) Japanese “free of charge” button
1F22F ; Extended_Pictographic# 5.2 [1] (🈯) Japanese “reserved” button
1F232..1F23A ; Extended_Pictographic# 6.0 [9] (🈲..🈺) Japanese “prohibited” button..Japanese “open for business” button
1F23C..1F23F ; Extended_Pictographic# NA [4] (🈼..🈿) <reserved-1F23C>..<reserved-1F23F>
1F249..1F24F ; Extended_Pictographic# NA [7] (🉉..🉏) <reserved-1F249>..<reserved-1F24F>
1F250..1F251 ; Extended_Pictographic# 6.0 [2] (🉐..🉑) Japanese “bargain” button..Japanese “acceptable” button
1F252..1F25F ; Extended_Pictographic# NA [14] (🉒..🉟) <reserved-1F252>..<reserved-1F25F>
1F260..1F265 ; Extended_Pictographic# 10.0 [6] (🉠..🉥) ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI
1F266..1F2FF ; Extended_Pictographic# NA[154] (🉦..🋿) <reserved-1F266>..<reserved-1F2FF>
1F300..1F320 ; Extended_Pictographic# 6.0 [33] (🌀..🌠) cyclone..shooting star
1F321..1F32C ; Extended_Pictographic# 7.0 [12] (🌡️..🌬️) thermometer..wind face
1F32D..1F32F ; Extended_Pictographic# 8.0 [3] (🌭..🌯) hot dog..burrito
1F330..1F335 ; Extended_Pictographic# 6.0 [6] (🌰..🌵) chestnut..cactus
1F336 ; Extended_Pictographic# 7.0 [1] (🌶️) hot pepper
1F337..1F37C ; Extended_Pictographic# 6.0 [70] (🌷..🍼) tulip..baby bottle
1F37D ; Extended_Pictographic# 7.0 [1] (🍽️) fork and knife with plate
1F37E..1F37F ; Extended_Pictographic# 8.0 [2] (🍾..🍿) bottle with popping cork..popcorn
1F380..1F393 ; Extended_Pictographic# 6.0 [20] (🎀..🎓) ribbon..graduation cap
1F394..1F39F ; Extended_Pictographic# 7.0 [12] (🎔..🎟️) HEART WITH TIP ON THE LEFT..admission tickets
1F3A0..1F3C4 ; Extended_Pictographic# 6.0 [37] (🎠..🏄) carousel horse..person surfing
1F3C5 ; Extended_Pictographic# 7.0 [1] (🏅) sports medal
1F3C6..1F3CA ; Extended_Pictographic# 6.0 [5] (🏆..🏊) trophy..person swimming
1F3CB..1F3CE ; Extended_Pictographic# 7.0 [4] (🏋️..🏎️) person lifting weights..racing car
1F3CF..1F3D3 ; Extended_Pictographic# 8.0 [5] (🏏..🏓) cricket game..ping pong
1F3D4..1F3DF ; Extended_Pictographic# 7.0 [12] (🏔️..🏟️) snow-capped mountain..stadium
1F3E0..1F3F0 ; Extended_Pictographic# 6.0 [17] (🏠..🏰) house..castle
1F3F1..1F3F7 ; Extended_Pictographic# 7.0 [7] (🏱..🏷️) WHITE PENNANT..label
1F3F8..1F3FA ; Extended_Pictographic# 8.0 [3] (🏸..🏺) badminton..amphora
1F400..1F43E ; Extended_Pictographic# 6.0 [63] (🐀..🐾) rat..paw prints
1F43F ; Extended_Pictographic# 7.0 [1] (🐿️) chipmunk
1F440 ; Extended_Pictographic# 6.0 [1] (👀) eyes
1F441 ; Extended_Pictographic# 7.0 [1] (👁️) eye
1F442..1F4F7 ; Extended_Pictographic# 6.0[182] (👂..📷) ear..camera
1F4F8 ; Extended_Pictographic# 7.0 [1] (📸) camera with flash
1F4F9..1F4FC ; Extended_Pictographic# 6.0 [4] (📹..📼) video camera..videocassette
1F4FD..1F4FE ; Extended_Pictographic# 7.0 [2] (📽️..📾) film projector..PORTABLE STEREO
1F4FF ; Extended_Pictographic# 8.0 [1] (📿) prayer beads
1F500..1F53D ; Extended_Pictographic# 6.0 [62] (🔀..🔽) shuffle tracks button..downwards button
1F546..1F54A ; Extended_Pictographic# 7.0 [5] (🕆..🕊️) WHITE LATIN CROSS..dove
1F54B..1F54F ; Extended_Pictographic# 8.0 [5] (🕋..🕏) kaaba..BOWL OF HYGIEIA
1F550..1F567 ; Extended_Pictographic# 6.0 [24] (🕐..🕧) one o’clock..twelve-thirty
1F568..1F579 ; Extended_Pictographic# 7.0 [18] (🕨..🕹️) RIGHT SPEAKER..joystick
1F57A ; Extended_Pictographic# 9.0 [1] (🕺) man dancing
1F57B..1F5A3 ; Extended_Pictographic# 7.0 [41] (🕻..🖣) LEFT HAND TELEPHONE RECEIVER..BLACK DOWN POINTING BACKHAND INDEX
1F5A4 ; Extended_Pictographic# 9.0 [1] (🖤) black heart
1F5A5..1F5FA ; Extended_Pictographic# 7.0 [86] (🖥️..🗺️) desktop computer..world map
1F5FB..1F5FF ; Extended_Pictographic# 6.0 [5] (🗻..🗿) mount fuji..moai
1F600 ; Extended_Pictographic# 6.1 [1] (😀) grinning face
1F601..1F610 ; Extended_Pictographic# 6.0 [16] (😁..😐) beaming face with smiling eyes..neutral face
1F611 ; Extended_Pictographic# 6.1 [1] (😑) expressionless face
1F612..1F614 ; Extended_Pictographic# 6.0 [3] (😒..😔) unamused face..pensive face
1F615 ; Extended_Pictographic# 6.1 [1] (😕) confused face
1F616 ; Extended_Pictographic# 6.0 [1] (😖) confounded face
1F617 ; Extended_Pictographic# 6.1 [1] (😗) kissing face
1F618 ; Extended_Pictographic# 6.0 [1] (😘) face blowing a kiss
1F619 ; Extended_Pictographic# 6.1 [1] (😙) kissing face with smiling eyes
1F61A ; Extended_Pictographic# 6.0 [1] (😚) kissing face with closed eyes
1F61B ; Extended_Pictographic# 6.1 [1] (😛) face with tongue
1F61C..1F61E ; Extended_Pictographic# 6.0 [3] (😜..😞) winking face with tongue..disappointed face
1F61F ; Extended_Pictographic# 6.1 [1] (😟) worried face
1F620..1F625 ; Extended_Pictographic# 6.0 [6] (😠..😥) angry face..sad but relieved face
1F626..1F627 ; Extended_Pictographic# 6.1 [2] (😦..😧) frowning face with open mouth..anguished face
1F628..1F62B ; Extended_Pictographic# 6.0 [4] (😨..😫) fearful face..tired face
1F62C ; Extended_Pictographic# 6.1 [1] (😬) grimacing face
1F62D ; Extended_Pictographic# 6.0 [1] (😭) loudly crying face
1F62E..1F62F ; Extended_Pictographic# 6.1 [2] (😮..😯) face with open mouth..hushed face
1F630..1F633 ; Extended_Pictographic# 6.0 [4] (😰..😳) anxious face with sweat..flushed face
1F634 ; Extended_Pictographic# 6.1 [1] (😴) sleeping face
1F635..1F640 ; Extended_Pictographic# 6.0 [12] (😵..🙀) dizzy face..weary cat
1F641..1F642 ; Extended_Pictographic# 7.0 [2] (🙁..🙂) slightly frowning face..slightly smiling face
1F643..1F644 ; Extended_Pictographic# 8.0 [2] (🙃..🙄) upside-down face..face with rolling eyes
1F645..1F64F ; Extended_Pictographic# 6.0 [11] (🙅..🙏) person gesturing NO..folded hands
1F680..1F6C5 ; Extended_Pictographic# 6.0 [70] (🚀..🛅) rocket..left luggage
1F6C6..1F6CF ; Extended_Pictographic# 7.0 [10] (🛆..🛏️) TRIANGLE WITH ROUNDED CORNERS..bed
1F6D0 ; Extended_Pictographic# 8.0 [1] (🛐) place of worship
1F6D1..1F6D2 ; Extended_Pictographic# 9.0 [2] (🛑..🛒) stop sign..shopping cart
1F6D3..1F6D4 ; Extended_Pictographic# 10.0 [2] (🛓..🛔) STUPA..PAGODA
1F6D5 ; Extended_Pictographic# 12.0 [1] (🛕) hindu temple
1F6D6..1F6DF ; Extended_Pictographic# NA [10] (🛖..🛟) <reserved-1F6D6>..<reserved-1F6DF>
1F6E0..1F6EC ; Extended_Pictographic# 7.0 [13] (🛠️..🛬) hammer and wrench..airplane arrival
1F6ED..1F6EF ; Extended_Pictographic# NA [3] (🛭..🛯) <reserved-1F6ED>..<reserved-1F6EF>
1F6F0..1F6F3 ; Extended_Pictographic# 7.0 [4] (🛰️..🛳️) satellite..passenger ship
1F6F4..1F6F6 ; Extended_Pictographic# 9.0 [3] (🛴..🛶) kick scooter..canoe
1F6F7..1F6F8 ; Extended_Pictographic# 10.0 [2] (🛷..🛸) sled..flying saucer
1F6F9 ; Extended_Pictographic# 11.0 [1] (🛹) skateboard
1F6FA ; Extended_Pictographic# 12.0 [1] (🛺) auto rickshaw
1F6FB..1F6FF ; Extended_Pictographic# NA [5] (🛻..🛿) <reserved-1F6FB>..<reserved-1F6FF>
1F774..1F77F ; Extended_Pictographic# NA [12] (🝴..🝿) <reserved-1F774>..<reserved-1F77F>
1F7D5..1F7D8 ; Extended_Pictographic# 11.0 [4] (🟕..🟘) CIRCLED TRIANGLE..NEGATIVE CIRCLED SQUARE
1F7D9..1F7DF ; Extended_Pictographic# NA [7] (🟙..🟟) <reserved-1F7D9>..<reserved-1F7DF>
1F7E0..1F7EB ; Extended_Pictographic# 12.0 [12] (🟠..🟫) orange circle..brown square
1F7EC..1F7FF ; Extended_Pictographic# NA [20] (🟬..🟿) <reserved-1F7EC>..<reserved-1F7FF>
1F80C..1F80F ; Extended_Pictographic# NA [4] (🠌..🠏) <reserved-1F80C>..<reserved-1F80F>
1F848..1F84F ; Extended_Pictographic# NA [8] (🡈..🡏) <reserved-1F848>..<reserved-1F84F>
1F85A..1F85F ; Extended_Pictographic# NA [6] (🡚..🡟) <reserved-1F85A>..<reserved-1F85F>
1F888..1F88F ; Extended_Pictographic# NA [8] (🢈..🢏) <reserved-1F888>..<reserved-1F88F>
1F8AE..1F8FF ; Extended_Pictographic# NA [82] (🢮..🣿) <reserved-1F8AE>..<reserved-1F8FF>
1F90C ; Extended_Pictographic# NA [1] (🤌) <reserved-1F90C>
1F90D..1F90F ; Extended_Pictographic# 12.0 [3] (🤍..🤏) white heart..pinching hand
1F910..1F918 ; Extended_Pictographic# 8.0 [9] (🤐..🤘) zipper-mouth face..sign of the horns
1F919..1F91E ; Extended_Pictographic# 9.0 [6] (🤙..🤞) call me hand..crossed fingers
1F91F ; Extended_Pictographic# 10.0 [1] (🤟) love-you gesture
1F920..1F927 ; Extended_Pictographic# 9.0 [8] (🤠..🤧) cowboy hat face..sneezing face
1F928..1F92F ; Extended_Pictographic# 10.0 [8] (🤨..🤯) face with raised eyebrow..exploding head
1F930 ; Extended_Pictographic# 9.0 [1] (🤰) pregnant woman
1F931..1F932 ; Extended_Pictographic# 10.0 [2] (🤱..🤲) breast-feeding..palms up together
1F933..1F93A ; Extended_Pictographic# 9.0 [8] (🤳..🤺) selfie..person fencing
1F93C..1F93E ; Extended_Pictographic# 9.0 [3] (🤼..🤾) people wrestling..person playing handball
1F93F ; Extended_Pictographic# 12.0 [1] (🤿) diving mask
1F940..1F945 ; Extended_Pictographic# 9.0 [6] (🥀..🥅) wilted flower..goal net
1F947..1F94B ; Extended_Pictographic# 9.0 [5] (🥇..🥋) 1st place medal..martial arts uniform
1F94C ; Extended_Pictographic# 10.0 [1] (🥌) curling stone
1F94D..1F94F ; Extended_Pictographic# 11.0 [3] (🥍..🥏) lacrosse..flying disc
1F950..1F95E ; Extended_Pictographic# 9.0 [15] (🥐..🥞) croissant..pancakes
1F95F..1F96B ; Extended_Pictographic# 10.0 [13] (🥟..🥫) dumpling..canned food
1F96C..1F970 ; Extended_Pictographic# 11.0 [5] (🥬..🥰) leafy green..smiling face with hearts
1F971 ; Extended_Pictographic# 12.0 [1] (🥱) yawning face
1F972 ; Extended_Pictographic# NA [1] (🥲) <reserved-1F972>
1F973..1F976 ; Extended_Pictographic# 11.0 [4] (🥳..🥶) partying face..cold face
1F977..1F979 ; Extended_Pictographic# NA [3] (🥷..🥹) <reserved-1F977>..<reserved-1F979>
1F97A ; Extended_Pictographic# 11.0 [1] (🥺) pleading face
1F97B ; Extended_Pictographic# 12.0 [1] (🥻) sari
1F97C..1F97F ; Extended_Pictographic# 11.0 [4] (🥼..🥿) lab coat..flat shoe
1F980..1F984 ; Extended_Pictographic# 8.0 [5] (🦀..🦄) crab..unicorn
1F985..1F991 ; Extended_Pictographic# 9.0 [13] (🦅..🦑) eagle..squid
1F992..1F997 ; Extended_Pictographic# 10.0 [6] (🦒..🦗) giraffe..cricket
1F998..1F9A2 ; Extended_Pictographic# 11.0 [11] (🦘..🦢) kangaroo..swan
1F9A3..1F9A4 ; Extended_Pictographic# NA [2] (🦣..🦤) <reserved-1F9A3>..<reserved-1F9A4>
1F9A5..1F9AA ; Extended_Pictographic# 12.0 [6] (🦥..🦪) sloth..oyster
1F9AB..1F9AD ; Extended_Pictographic# NA [3] (🦫..🦭) <reserved-1F9AB>..<reserved-1F9AD>
1F9AE..1F9AF ; Extended_Pictographic# 12.0 [2] (🦮..🦯) guide dog..probing cane
1F9B0..1F9B9 ; Extended_Pictographic# 11.0 [10] (🦰..🦹) red hair..supervillain
1F9BA..1F9BF ; Extended_Pictographic# 12.0 [6] (🦺..🦿) safety vest..mechanical leg
1F9C0 ; Extended_Pictographic# 8.0 [1] (🧀) cheese wedge
1F9C1..1F9C2 ; Extended_Pictographic# 11.0 [2] (🧁..🧂) cupcake..salt
1F9C3..1F9CA ; Extended_Pictographic# 12.0 [8] (🧃..🧊) beverage box..ice cube
1F9CB..1F9CC ; Extended_Pictographic# NA [2] (🧋..🧌) <reserved-1F9CB>..<reserved-1F9CC>
1F9CD..1F9CF ; Extended_Pictographic# 12.0 [3] (🧍..🧏) person standing..deaf person
1F9D0..1F9E6 ; Extended_Pictographic# 10.0 [23] (🧐..🧦) face with monocle..socks
1F9E7..1F9FF ; Extended_Pictographic# 11.0 [25] (🧧..🧿) red envelope..nazar amulet
1FA00..1FA53 ; Extended_Pictographic# 12.0 [84] (🨀..🩓) NEUTRAL CHESS KING..BLACK CHESS KNIGHT-BISHOP
1FA54..1FA5F ; Extended_Pictographic# NA [12] (🩔..🩟) <reserved-1FA54>..<reserved-1FA5F>
1FA60..1FA6D ; Extended_Pictographic# 11.0 [14] (🩠..🩭) XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER
1FA6E..1FA6F ; Extended_Pictographic# NA [2] (🩮..🩯) <reserved-1FA6E>..<reserved-1FA6F>
1FA70..1FA73 ; Extended_Pictographic# 12.0 [4] (🩰..🩳) ballet shoes..shorts
1FA74..1FA77 ; Extended_Pictographic# NA [4] (🩴..🩷) <reserved-1FA74>..<reserved-1FA77>
1FA78..1FA7A ; Extended_Pictographic# 12.0 [3] (🩸..🩺) drop of blood..stethoscope
1FA7B..1FA7F ; Extended_Pictographic# NA [5] (🩻..🩿) <reserved-1FA7B>..<reserved-1FA7F>
1FA80..1FA82 ; Extended_Pictographic# 12.0 [3] (🪀..🪂) yo-yo..parachute
1FA83..1FA8F ; Extended_Pictographic# NA [13] (🪃..🪏) <reserved-1FA83>..<reserved-1FA8F>
1FA90..1FA95 ; Extended_Pictographic# 12.0 [6] (🪐..🪕) ringed planet..banjo
1FA96..1FFFD ; Extended_Pictographic# NA[1384] (🪖..🿽) <reserved-1FA96>..<reserved-1FFFD>
# ================================================
# Total elements: 3793
# All omitted code points have Extended_Pictographic=No
# @missing: 0000..10FFFF ; Extended_Pictographic ; No
#EOF
00A9 ; Extended_Pictographic# E0.6 [1] (©️) copyright
00AE ; Extended_Pictographic# E0.6 [1] (®️) registered
203C ; Extended_Pictographic# E0.6 [1] (‼️) double exclamation mark
2049 ; Extended_Pictographic# E0.6 [1] (⁉️) exclamation question mark
2122 ; Extended_Pictographic# E0.6 [1] (™️) trade mark
2139 ; Extended_Pictographic# E0.6 [1] (ℹ️) information
2194..2199 ; Extended_Pictographic# E0.6 [6] (↔️..↙️) left-right arrow..down-left arrow
21A9..21AA ; Extended_Pictographic# E0.6 [2] (↩️..↪️) right arrow curving left..left arrow curving right
231A..231B ; Extended_Pictographic# E0.6 [2] (⌚..⌛) watch..hourglass done
2328 ; Extended_Pictographic# E1.0 [1] (⌨️) keyboard
2388 ; Extended_Pictographic# E0.0 [1] (⎈) HELM SYMBOL
23CF ; Extended_Pictographic# E1.0 [1] (⏏️) eject button
23E9..23EC ; Extended_Pictographic# E0.6 [4] (⏩..⏬) fast-forward button..fast down button
23ED..23EE ; Extended_Pictographic# E0.7 [2] (⏭️..⏮️) next track button..last track button
23EF ; Extended_Pictographic# E1.0 [1] (⏯️) play or pause button
23F0 ; Extended_Pictographic# E0.6 [1] (⏰) alarm clock
23F1..23F2 ; Extended_Pictographic# E1.0 [2] (⏱️..⏲️) stopwatch..timer clock
23F3 ; Extended_Pictographic# E0.6 [1] (⏳) hourglass not done
23F8..23FA ; Extended_Pictographic# E0.7 [3] (⏸️..⏺️) pause button..record button
24C2 ; Extended_Pictographic# E0.6 [1] (Ⓜ️) circled M
25AA..25AB ; Extended_Pictographic# E0.6 [2] (▪️..▫️) black small square..white small square
25B6 ; Extended_Pictographic# E0.6 [1] (▶️) play button
25C0 ; Extended_Pictographic# E0.6 [1] (◀️) reverse button
25FB..25FE ; Extended_Pictographic# E0.6 [4] (◻️..◾) white medium square..black medium-small square
2600..2601 ; Extended_Pictographic# E0.6 [2] (☀️..☁️) sun..cloud
2602..2603 ; Extended_Pictographic# E0.7 [2] (☂️..☃️) umbrella..snowman
2604 ; Extended_Pictographic# E1.0 [1] (☄️) comet
2605 ; Extended_Pictographic# E0.0 [1] (★) BLACK STAR
2607..260D ; Extended_Pictographic# E0.0 [7] (☇..☍) LIGHTNING..OPPOSITION
260E ; Extended_Pictographic# E0.6 [1] (☎️) telephone
260F..2610 ; Extended_Pictographic# E0.0 [2] (☏..☐) WHITE TELEPHONE..BALLOT BOX
2611 ; Extended_Pictographic# E0.6 [1] (☑️) check box with check
2612 ; Extended_Pictographic# E0.0 [1] (☒) BALLOT BOX WITH X
2614..2615 ; Extended_Pictographic# E0.6 [2] (☔..☕) umbrella with rain drops..hot beverage
2616..2617 ; Extended_Pictographic# E0.0 [2] (☖..☗) WHITE SHOGI PIECE..BLACK SHOGI PIECE
2618 ; Extended_Pictographic# E1.0 [1] (☘️) shamrock
2619..261C ; Extended_Pictographic# E0.0 [4] (☙..☜) REVERSED ROTATED FLORAL HEART BULLET..WHITE LEFT POINTING INDEX
261D ; Extended_Pictographic# E0.6 [1] (☝️) index pointing up
261E..261F ; Extended_Pictographic# E0.0 [2] (☞..☟) WHITE RIGHT POINTING INDEX..WHITE DOWN POINTING INDEX
2620 ; Extended_Pictographic# E1.0 [1] (☠️) skull and crossbones
2621 ; Extended_Pictographic# E0.0 [1] (☡) CAUTION SIGN
2622..2623 ; Extended_Pictographic# E1.0 [2] (☢️..☣️) radioactive..biohazard
2624..2625 ; Extended_Pictographic# E0.0 [2] (☤..☥) CADUCEUS..ANKH
2626 ; Extended_Pictographic# E1.0 [1] (☦️) orthodox cross
2627..2629 ; Extended_Pictographic# E0.0 [3] (☧..☩) CHI RHO..CROSS OF JERUSALEM
262A ; Extended_Pictographic# E0.7 [1] (☪️) star and crescent
262B..262D ; Extended_Pictographic# E0.0 [3] (☫..☭) FARSI SYMBOL..HAMMER AND SICKLE
262E ; Extended_Pictographic# E1.0 [1] (☮️) peace symbol
262F ; Extended_Pictographic# E0.7 [1] (☯️) yin yang
2630..2637 ; Extended_Pictographic# E0.0 [8] (☰..☷) TRIGRAM FOR HEAVEN..TRIGRAM FOR EARTH
2638..2639 ; Extended_Pictographic# E0.7 [2] (☸️..☹️) wheel of dharma..frowning face
263A ; Extended_Pictographic# E0.6 [1] (☺️) smiling face
263B..263F ; Extended_Pictographic# E0.0 [5] (☻..☿) BLACK SMILING FACE..MERCURY
2640 ; Extended_Pictographic# E4.0 [1] (♀️) female sign
2641 ; Extended_Pictographic# E0.0 [1] (♁) EARTH
2642 ; Extended_Pictographic# E4.0 [1] (♂️) male sign
2643..2647 ; Extended_Pictographic# E0.0 [5] (♃..♇) JUPITER..PLUTO
2648..2653 ; Extended_Pictographic# E0.6 [12] (♈..♓) Aries..Pisces
2654..265E ; Extended_Pictographic# E0.0 [11] (♔..♞) WHITE CHESS KING..BLACK CHESS KNIGHT
265F ; Extended_Pictographic# E11.0 [1] (♟️) chess pawn
2660 ; Extended_Pictographic# E0.6 [1] (♠️) spade suit
2661..2662 ; Extended_Pictographic# E0.0 [2] (♡..♢) WHITE HEART SUIT..WHITE DIAMOND SUIT
2663 ; Extended_Pictographic# E0.6 [1] (♣️) club suit
2664 ; Extended_Pictographic# E0.0 [1] (♤) WHITE SPADE SUIT
2665..2666 ; Extended_Pictographic# E0.6 [2] (♥️..♦️) heart suit..diamond suit
2667 ; Extended_Pictographic# E0.0 [1] (♧) WHITE CLUB SUIT
2668 ; Extended_Pictographic# E0.6 [1] (♨️) hot springs
2669..267A ; Extended_Pictographic# E0.0 [18] (♩..♺) QUARTER NOTE..RECYCLING SYMBOL FOR GENERIC MATERIALS
267B ; Extended_Pictographic# E0.6 [1] (♻️) recycling symbol
267C..267D ; Extended_Pictographic# E0.0 [2] (♼..♽) RECYCLED PAPER SYMBOL..PARTIALLY-RECYCLED PAPER SYMBOL
267E ; Extended_Pictographic# E11.0 [1] (♾️) infinity
267F ; Extended_Pictographic# E0.6 [1] (♿) wheelchair symbol
2680..2685 ; Extended_Pictographic# E0.0 [6] (⚀..⚅) DIE FACE-1..DIE FACE-6
2690..2691 ; Extended_Pictographic# E0.0 [2] (⚐..⚑) WHITE FLAG..BLACK FLAG
2692 ; Extended_Pictographic# E1.0 [1] (⚒️) hammer and pick
2693 ; Extended_Pictographic# E0.6 [1] (⚓) anchor
2694 ; Extended_Pictographic# E1.0 [1] (⚔️) crossed swords
2695 ; Extended_Pictographic# E4.0 [1] (⚕️) medical symbol
2696..2697 ; Extended_Pictographic# E1.0 [2] (⚖️..⚗️) balance scale..alembic
2698 ; Extended_Pictographic# E0.0 [1] (⚘) FLOWER
2699 ; Extended_Pictographic# E1.0 [1] (⚙️) gear
269A ; Extended_Pictographic# E0.0 [1] (⚚) STAFF OF HERMES
269B..269C ; Extended_Pictographic# E1.0 [2] (⚛️..⚜️) atom symbol..fleur-de-lis
269D..269F ; Extended_Pictographic# E0.0 [3] (⚝..⚟) OUTLINED WHITE STAR..THREE LINES CONVERGING LEFT
26A0..26A1 ; Extended_Pictographic# E0.6 [2] (⚠️..⚡) warning..high voltage
26A2..26A6 ; Extended_Pictographic# E0.0 [5] (⚢..⚦) DOUBLED FEMALE SIGN..MALE WITH STROKE SIGN
26A7 ; Extended_Pictographic# E13.0 [1] (⚧️) transgender symbol
26A8..26A9 ; Extended_Pictographic# E0.0 [2] (⚨..⚩) VERTICAL MALE WITH STROKE SIGN..HORIZONTAL MALE WITH STROKE SIGN
26AA..26AB ; Extended_Pictographic# E0.6 [2] (⚪..⚫) white circle..black circle
26AC..26AF ; Extended_Pictographic# E0.0 [4] (⚬..⚯) MEDIUM SMALL WHITE CIRCLE..UNMARRIED PARTNERSHIP SYMBOL
26B0..26B1 ; Extended_Pictographic# E1.0 [2] (⚰️..⚱️) coffin..funeral urn
26B2..26BC ; Extended_Pictographic# E0.0 [11] (⚲..⚼) NEUTER..SESQUIQUADRATE
26BD..26BE ; Extended_Pictographic# E0.6 [2] (⚽..⚾) soccer ball..baseball
26BF..26C3 ; Extended_Pictographic# E0.0 [5] (⚿..⛃) SQUARED KEY..BLACK DRAUGHTS KING
26C4..26C5 ; Extended_Pictographic# E0.6 [2] (⛄..⛅) snowman without snow..sun behind cloud
26C6..26C7 ; Extended_Pictographic# E0.0 [2] (⛆..⛇) RAIN..BLACK SNOWMAN
26C8 ; Extended_Pictographic# E0.7 [1] (⛈️) cloud with lightning and rain
26C9..26CD ; Extended_Pictographic# E0.0 [5] (⛉..⛍) TURNED WHITE SHOGI PIECE..DISABLED CAR
26CE ; Extended_Pictographic# E0.6 [1] (⛎) Ophiuchus
26CF ; Extended_Pictographic# E0.7 [1] (⛏️) pick
26D0 ; Extended_Pictographic# E0.0 [1] (⛐) CAR SLIDING
26D1 ; Extended_Pictographic# E0.7 [1] (⛑️) rescue worker’s helmet
26D2 ; Extended_Pictographic# E0.0 [1] (⛒) CIRCLED CROSSING LANES
26D3 ; Extended_Pictographic# E0.7 [1] (⛓️) chains
26D4 ; Extended_Pictographic# E0.6 [1] (⛔) no entry
26D5..26E8 ; Extended_Pictographic# E0.0 [20] (⛕..⛨) ALTERNATE ONE-WAY LEFT WAY TRAFFIC..BLACK CROSS ON SHIELD
26E9 ; Extended_Pictographic# E0.7 [1] (⛩️) shinto shrine
26EA ; Extended_Pictographic# E0.6 [1] (⛪) church
26EB..26EF ; Extended_Pictographic# E0.0 [5] (⛫..⛯) CASTLE..MAP SYMBOL FOR LIGHTHOUSE
26F0..26F1 ; Extended_Pictographic# E0.7 [2] (⛰️..⛱️) mountain..umbrella on ground
26F2..26F3 ; Extended_Pictographic# E0.6 [2] (⛲..⛳) fountain..flag in hole
26F4 ; Extended_Pictographic# E0.7 [1] (⛴️) ferry
26F5 ; Extended_Pictographic# E0.6 [1] (⛵) sailboat
26F6 ; Extended_Pictographic# E0.0 [1] (⛶) SQUARE FOUR CORNERS
26F7..26F9 ; Extended_Pictographic# E0.7 [3] (⛷️..⛹️) skier..person bouncing ball
26FA ; Extended_Pictographic# E0.6 [1] (⛺) tent
26FB..26FC ; Extended_Pictographic# E0.0 [2] (⛻..⛼) JAPANESE BANK SYMBOL..HEADSTONE GRAVEYARD SYMBOL
26FD ; Extended_Pictographic# E0.6 [1] (⛽) fuel pump
26FE..2701 ; Extended_Pictographic# E0.0 [4] (⛾..✁) CUP ON BLACK SQUARE..UPPER BLADE SCISSORS
2702 ; Extended_Pictographic# E0.6 [1] (✂️) scissors
2703..2704 ; Extended_Pictographic# E0.0 [2] (✃..✄) LOWER BLADE SCISSORS..WHITE SCISSORS
2705 ; Extended_Pictographic# E0.6 [1] (✅) check mark button
2708..270C ; Extended_Pictographic# E0.6 [5] (✈️..✌️) airplane..victory hand
270D ; Extended_Pictographic# E0.7 [1] (✍️) writing hand
270E ; Extended_Pictographic# E0.0 [1] (✎) LOWER RIGHT PENCIL
270F ; Extended_Pictographic# E0.6 [1] (✏️) pencil
2710..2711 ; Extended_Pictographic# E0.0 [2] (✐..✑) UPPER RIGHT PENCIL..WHITE NIB
2712 ; Extended_Pictographic# E0.6 [1] (✒️) black nib
2714 ; Extended_Pictographic# E0.6 [1] (✔️) check mark
2716 ; Extended_Pictographic# E0.6 [1] (✖️) multiply
271D ; Extended_Pictographic# E0.7 [1] (✝️) latin cross
2721 ; Extended_Pictographic# E0.7 [1] (✡️) star of David
2728 ; Extended_Pictographic# E0.6 [1] (✨) sparkles
2733..2734 ; Extended_Pictographic# E0.6 [2] (✳️..✴️) eight-spoked asterisk..eight-pointed star
2744 ; Extended_Pictographic# E0.6 [1] (❄️) snowflake
2747 ; Extended_Pictographic# E0.6 [1] (❇️) sparkle
274C ; Extended_Pictographic# E0.6 [1] (❌) cross mark
274E ; Extended_Pictographic# E0.6 [1] (❎) cross mark button
2753..2755 ; Extended_Pictographic# E0.6 [3] (❓..❕) question mark..white exclamation mark
2757 ; Extended_Pictographic# E0.6 [1] (❗) exclamation mark
2763 ; Extended_Pictographic# E1.0 [1] (❣️) heart exclamation
2764 ; Extended_Pictographic# E0.6 [1] (❤️) red heart
2765..2767 ; Extended_Pictographic# E0.0 [3] (❥..❧) ROTATED HEAVY BLACK HEART BULLET..ROTATED FLORAL HEART BULLET
2795..2797 ; Extended_Pictographic# E0.6 [3] (➕..➗) plus..divide
27A1 ; Extended_Pictographic# E0.6 [1] (➡️) right arrow
27B0 ; Extended_Pictographic# E0.6 [1] (➰) curly loop
27BF ; Extended_Pictographic# E1.0 [1] (➿) double curly loop
2934..2935 ; Extended_Pictographic# E0.6 [2] (⤴️..⤵️) right arrow curving up..right arrow curving down
2B05..2B07 ; Extended_Pictographic# E0.6 [3] (⬅️..⬇️) left arrow..down arrow
2B1B..2B1C ; Extended_Pictographic# E0.6 [2] (⬛..⬜) black large square..white large square
2B50 ; Extended_Pictographic# E0.6 [1] (⭐) star
2B55 ; Extended_Pictographic# E0.6 [1] (⭕) hollow red circle
3030 ; Extended_Pictographic# E0.6 [1] (〰️) wavy dash
303D ; Extended_Pictographic# E0.6 [1] (〽️) part alternation mark
3297 ; Extended_Pictographic# E0.6 [1] (㊗️) Japanese “congratulations” button
3299 ; Extended_Pictographic# E0.6 [1] (㊙️) Japanese “secret” button
1F000..1F003 ; Extended_Pictographic# E0.0 [4] (🀀..🀃) MAHJONG TILE EAST WIND..MAHJONG TILE NORTH WIND
1F004 ; Extended_Pictographic# E0.6 [1] (🀄) mahjong red dragon
1F005..1F0CE ; Extended_Pictographic# E0.0 [202] (🀅..🃎) MAHJONG TILE GREEN DRAGON..PLAYING CARD KING OF DIAMONDS
1F0CF ; Extended_Pictographic# E0.6 [1] (🃏) joker
1F0D0..1F0FF ; Extended_Pictographic# E0.0 [48] (🃐..🃿) <reserved-1F0D0>..<reserved-1F0FF>
1F10D..1F10F ; Extended_Pictographic# E0.0 [3] (🄍..🄏) CIRCLED ZERO WITH SLASH..CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH
1F12F ; Extended_Pictographic# E0.0 [1] (🄯) COPYLEFT SYMBOL
1F16C..1F16F ; Extended_Pictographic# E0.0 [4] (🅬..🅯) RAISED MR SIGN..CIRCLED HUMAN FIGURE
1F170..1F171 ; Extended_Pictographic# E0.6 [2] (🅰️..🅱️) A button (blood type)..B button (blood type)
1F17E..1F17F ; Extended_Pictographic# E0.6 [2] (🅾️..🅿️) O button (blood type)..P button
1F18E ; Extended_Pictographic# E0.6 [1] (🆎) AB button (blood type)
1F191..1F19A ; Extended_Pictographic# E0.6 [10] (🆑..🆚) CL button..VS button
1F1AD..1F1E5 ; Extended_Pictographic# E0.0 [57] (🆭..🇥) MASK WORK SYMBOL..<reserved-1F1E5>
1F201..1F202 ; Extended_Pictographic# E0.6 [2] (🈁..🈂️) Japanese “here” button..Japanese “service charge” button
1F203..1F20F ; Extended_Pictographic# E0.0 [13] (🈃..🈏) <reserved-1F203>..<reserved-1F20F>
1F21A ; Extended_Pictographic# E0.6 [1] (🈚) Japanese “free of charge” button
1F22F ; Extended_Pictographic# E0.6 [1] (🈯) Japanese “reserved” button
1F232..1F23A ; Extended_Pictographic# E0.6 [9] (🈲..🈺) Japanese “prohibited” button..Japanese “open for business” button
1F23C..1F23F ; Extended_Pictographic# E0.0 [4] (🈼..🈿) <reserved-1F23C>..<reserved-1F23F>
1F249..1F24F ; Extended_Pictographic# E0.0 [7] (🉉..🉏) <reserved-1F249>..<reserved-1F24F>
1F250..1F251 ; Extended_Pictographic# E0.6 [2] (🉐..🉑) Japanese “bargain” button..Japanese “acceptable” button
1F252..1F2FF ; Extended_Pictographic# E0.0 [174] (🉒..🋿) <reserved-1F252>..<reserved-1F2FF>
1F300..1F30C ; Extended_Pictographic# E0.6 [13] (🌀..🌌) cyclone..milky way
1F30D..1F30E ; Extended_Pictographic# E0.7 [2] (🌍..🌎) globe showing Europe-Africa..globe showing Americas
1F30F ; Extended_Pictographic# E0.6 [1] (🌏) globe showing Asia-Australia
1F310 ; Extended_Pictographic# E1.0 [1] (🌐) globe with meridians
1F311 ; Extended_Pictographic# E0.6 [1] (🌑) new moon
1F312 ; Extended_Pictographic# E1.0 [1] (🌒) waxing crescent moon
1F313..1F315 ; Extended_Pictographic# E0.6 [3] (🌓..🌕) first quarter moon..full moon
1F316..1F318 ; Extended_Pictographic# E1.0 [3] (🌖..🌘) waning gibbous moon..waning crescent moon
1F319 ; Extended_Pictographic# E0.6 [1] (🌙) crescent moon
1F31A ; Extended_Pictographic# E1.0 [1] (🌚) new moon face
1F31B ; Extended_Pictographic# E0.6 [1] (🌛) first quarter moon face
1F31C ; Extended_Pictographic# E0.7 [1] (🌜) last quarter moon face
1F31D..1F31E ; Extended_Pictographic# E1.0 [2] (🌝..🌞) full moon face..sun with face
1F31F..1F320 ; Extended_Pictographic# E0.6 [2] (🌟..🌠) glowing star..shooting star
1F321 ; Extended_Pictographic# E0.7 [1] (🌡️) thermometer
1F322..1F323 ; Extended_Pictographic# E0.0 [2] (🌢..🌣) BLACK DROPLET..WHITE SUN
1F324..1F32C ; Extended_Pictographic# E0.7 [9] (🌤️..🌬️) sun behind small cloud..wind face
1F32D..1F32F ; Extended_Pictographic# E1.0 [3] (🌭..🌯) hot dog..burrito
1F330..1F331 ; Extended_Pictographic# E0.6 [2] (🌰..🌱) chestnut..seedling
1F332..1F333 ; Extended_Pictographic# E1.0 [2] (🌲..🌳) evergreen tree..deciduous tree
1F334..1F335 ; Extended_Pictographic# E0.6 [2] (🌴..🌵) palm tree..cactus
1F336 ; Extended_Pictographic# E0.7 [1] (🌶️) hot pepper
1F337..1F34A ; Extended_Pictographic# E0.6 [20] (🌷..🍊) tulip..tangerine
1F34B ; Extended_Pictographic# E1.0 [1] (🍋) lemon
1F34C..1F34F ; Extended_Pictographic# E0.6 [4] (🍌..🍏) banana..green apple
1F350 ; Extended_Pictographic# E1.0 [1] (🍐) pear
1F351..1F37B ; Extended_Pictographic# E0.6 [43] (🍑..🍻) peach..clinking beer mugs
1F37C ; Extended_Pictographic# E1.0 [1] (🍼) baby bottle
1F37D ; Extended_Pictographic# E0.7 [1] (🍽️) fork and knife with plate
1F37E..1F37F ; Extended_Pictographic# E1.0 [2] (🍾..🍿) bottle with popping cork..popcorn
1F380..1F393 ; Extended_Pictographic# E0.6 [20] (🎀..🎓) ribbon..graduation cap
1F394..1F395 ; Extended_Pictographic# E0.0 [2] (🎔..🎕) HEART WITH TIP ON THE LEFT..BOUQUET OF FLOWERS
1F396..1F397 ; Extended_Pictographic# E0.7 [2] (🎖️..🎗️) military medal..reminder ribbon
1F398 ; Extended_Pictographic# E0.0 [1] (🎘) MUSICAL KEYBOARD WITH JACKS
1F399..1F39B ; Extended_Pictographic# E0.7 [3] (🎙️..🎛️) studio microphone..control knobs
1F39C..1F39D ; Extended_Pictographic# E0.0 [2] (🎜..🎝) BEAMED ASCENDING MUSICAL NOTES..BEAMED DESCENDING MUSICAL NOTES
1F39E..1F39F ; Extended_Pictographic# E0.7 [2] (🎞️..🎟️) film frames..admission tickets
1F3A0..1F3C4 ; Extended_Pictographic# E0.6 [37] (🎠..🏄) carousel horse..person surfing
1F3C5 ; Extended_Pictographic# E1.0 [1] (🏅) sports medal
1F3C6 ; Extended_Pictographic# E0.6 [1] (🏆) trophy
1F3C7 ; Extended_Pictographic# E1.0 [1] (🏇) horse racing
1F3C8 ; Extended_Pictographic# E0.6 [1] (🏈) american football
1F3C9 ; Extended_Pictographic# E1.0 [1] (🏉) rugby football
1F3CA ; Extended_Pictographic# E0.6 [1] (🏊) person swimming
1F3CB..1F3CE ; Extended_Pictographic# E0.7 [4] (🏋️..🏎️) person lifting weights..racing car
1F3CF..1F3D3 ; Extended_Pictographic# E1.0 [5] (🏏..🏓) cricket game..ping pong
1F3D4..1F3DF ; Extended_Pictographic# E0.7 [12] (🏔️..🏟️) snow-capped mountain..stadium
1F3E0..1F3E3 ; Extended_Pictographic# E0.6 [4] (🏠..🏣) house..Japanese post office
1F3E4 ; Extended_Pictographic# E1.0 [1] (🏤) post office
1F3E5..1F3F0 ; Extended_Pictographic# E0.6 [12] (🏥..🏰) hospital..castle
1F3F1..1F3F2 ; Extended_Pictographic# E0.0 [2] (🏱..🏲) WHITE PENNANT..BLACK PENNANT
1F3F3 ; Extended_Pictographic# E0.7 [1] (🏳️) white flag
1F3F4 ; Extended_Pictographic# E1.0 [1] (🏴) black flag
1F3F5 ; Extended_Pictographic# E0.7 [1] (🏵️) rosette
1F3F6 ; Extended_Pictographic# E0.0 [1] (🏶) BLACK ROSETTE
1F3F7 ; Extended_Pictographic# E0.7 [1] (🏷️) label
1F3F8..1F3FA ; Extended_Pictographic# E1.0 [3] (🏸..🏺) badminton..amphora
1F400..1F407 ; Extended_Pictographic# E1.0 [8] (🐀..🐇) rat..rabbit
1F408 ; Extended_Pictographic# E0.7 [1] (🐈) cat
1F409..1F40B ; Extended_Pictographic# E1.0 [3] (🐉..🐋) dragon..whale
1F40C..1F40E ; Extended_Pictographic# E0.6 [3] (🐌..🐎) snail..horse
1F40F..1F410 ; Extended_Pictographic# E1.0 [2] (🐏..🐐) ram..goat
1F411..1F412 ; Extended_Pictographic# E0.6 [2] (🐑..🐒) ewe..monkey
1F413 ; Extended_Pictographic# E1.0 [1] (🐓) rooster
1F414 ; Extended_Pictographic# E0.6 [1] (🐔) chicken
1F415 ; Extended_Pictographic# E0.7 [1] (🐕) dog
1F416 ; Extended_Pictographic# E1.0 [1] (🐖) pig
1F417..1F429 ; Extended_Pictographic# E0.6 [19] (🐗..🐩) boar..poodle
1F42A ; Extended_Pictographic# E1.0 [1] (🐪) camel
1F42B..1F43E ; Extended_Pictographic# E0.6 [20] (🐫..🐾) two-hump camel..paw prints
1F43F ; Extended_Pictographic# E0.7 [1] (🐿️) chipmunk
1F440 ; Extended_Pictographic# E0.6 [1] (👀) eyes
1F441 ; Extended_Pictographic# E0.7 [1] (👁️) eye
1F442..1F464 ; Extended_Pictographic# E0.6 [35] (👂..👤) ear..bust in silhouette
1F465 ; Extended_Pictographic# E1.0 [1] (👥) busts in silhouette
1F466..1F46B ; Extended_Pictographic# E0.6 [6] (👦..👫) boy..woman and man holding hands
1F46C..1F46D ; Extended_Pictographic# E1.0 [2] (👬..👭) men holding hands..women holding hands
1F46E..1F4AC ; Extended_Pictographic# E0.6 [63] (👮..💬) police officer..speech balloon
1F4AD ; Extended_Pictographic# E1.0 [1] (💭) thought balloon
1F4AE..1F4B5 ; Extended_Pictographic# E0.6 [8] (💮..💵) white flower..dollar banknote
1F4B6..1F4B7 ; Extended_Pictographic# E1.0 [2] (💶..💷) euro banknote..pound banknote
1F4B8..1F4EB ; Extended_Pictographic# E0.6 [52] (💸..📫) money with wings..closed mailbox with raised flag
1F4EC..1F4ED ; Extended_Pictographic# E0.7 [2] (📬..📭) open mailbox with raised flag..open mailbox with lowered flag
1F4EE ; Extended_Pictographic# E0.6 [1] (📮) postbox
1F4EF ; Extended_Pictographic# E1.0 [1] (📯) postal horn
1F4F0..1F4F4 ; Extended_Pictographic# E0.6 [5] (📰..📴) newspaper..mobile phone off
1F4F5 ; Extended_Pictographic# E1.0 [1] (📵) no mobile phones
1F4F6..1F4F7 ; Extended_Pictographic# E0.6 [2] (📶..📷) antenna bars..camera
1F4F8 ; Extended_Pictographic# E1.0 [1] (📸) camera with flash
1F4F9..1F4FC ; Extended_Pictographic# E0.6 [4] (📹..📼) video camera..videocassette
1F4FD ; Extended_Pictographic# E0.7 [1] (📽️) film projector
1F4FE ; Extended_Pictographic# E0.0 [1] (📾) PORTABLE STEREO
1F4FF..1F502 ; Extended_Pictographic# E1.0 [4] (📿..🔂) prayer beads..repeat single button
1F503 ; Extended_Pictographic# E0.6 [1] (🔃) clockwise vertical arrows
1F504..1F507 ; Extended_Pictographic# E1.0 [4] (🔄..🔇) counterclockwise arrows button..muted speaker
1F508 ; Extended_Pictographic# E0.7 [1] (🔈) speaker low volume
1F509 ; Extended_Pictographic# E1.0 [1] (🔉) speaker medium volume
1F50A..1F514 ; Extended_Pictographic# E0.6 [11] (🔊..🔔) speaker high volume..bell
1F515 ; Extended_Pictographic# E1.0 [1] (🔕) bell with slash
1F516..1F52B ; Extended_Pictographic# E0.6 [22] (🔖..🔫) bookmark..pistol
1F52C..1F52D ; Extended_Pictographic# E1.0 [2] (🔬..🔭) microscope..telescope
1F52E..1F53D ; Extended_Pictographic# E0.6 [16] (🔮..🔽) crystal ball..downwards button
1F546..1F548 ; Extended_Pictographic# E0.0 [3] (🕆..🕈) WHITE LATIN CROSS..CELTIC CROSS
1F549..1F54A ; Extended_Pictographic# E0.7 [2] (🕉️..🕊️) om..dove
1F54B..1F54E ; Extended_Pictographic# E1.0 [4] (🕋..🕎) kaaba..menorah
1F54F ; Extended_Pictographic# E0.0 [1] (🕏) BOWL OF HYGIEIA
1F550..1F55B ; Extended_Pictographic# E0.6 [12] (🕐..🕛) one o’clock..twelve o’clock
1F55C..1F567 ; Extended_Pictographic# E0.7 [12] (🕜..🕧) one-thirty..twelve-thirty
1F568..1F56E ; Extended_Pictographic# E0.0 [7] (🕨..🕮) RIGHT SPEAKER..BOOK
1F56F..1F570 ; Extended_Pictographic# E0.7 [2] (🕯️..🕰️) candle..mantelpiece clock
1F571..1F572 ; Extended_Pictographic# E0.0 [2] (🕱..🕲) BLACK SKULL AND CROSSBONES..NO PIRACY
1F573..1F579 ; Extended_Pictographic# E0.7 [7] (🕳️..🕹️) hole..joystick
1F57A ; Extended_Pictographic# E3.0 [1] (🕺) man dancing
1F57B..1F586 ; Extended_Pictographic# E0.0 [12] (🕻..🖆) LEFT HAND TELEPHONE RECEIVER..PEN OVER STAMPED ENVELOPE
1F587 ; Extended_Pictographic# E0.7 [1] (🖇️) linked paperclips
1F588..1F589 ; Extended_Pictographic# E0.0 [2] (🖈..🖉) BLACK PUSHPIN..LOWER LEFT PENCIL
1F58A..1F58D ; Extended_Pictographic# E0.7 [4] (🖊️..🖍️) pen..crayon
1F58E..1F58F ; Extended_Pictographic# E0.0 [2] (🖎..🖏) LEFT WRITING HAND..TURNED OK HAND SIGN
1F590 ; Extended_Pictographic# E0.7 [1] (🖐️) hand with fingers splayed
1F591..1F594 ; Extended_Pictographic# E0.0 [4] (🖑..🖔) REVERSED RAISED HAND WITH FINGERS SPLAYED..REVERSED VICTORY HAND
1F595..1F596 ; Extended_Pictographic# E1.0 [2] (🖕..🖖) middle finger..vulcan salute
1F597..1F5A3 ; Extended_Pictographic# E0.0 [13] (🖗..🖣) WHITE DOWN POINTING LEFT HAND INDEX..BLACK DOWN POINTING BACKHAND INDEX
1F5A4 ; Extended_Pictographic# E3.0 [1] (🖤) black heart
1F5A5 ; Extended_Pictographic# E0.7 [1] (🖥️) desktop computer
1F5A6..1F5A7 ; Extended_Pictographic# E0.0 [2] (🖦..🖧) KEYBOARD AND MOUSE..THREE NETWORKED COMPUTERS
1F5A8 ; Extended_Pictographic# E0.7 [1] (🖨️) printer
1F5A9..1F5B0 ; Extended_Pictographic# E0.0 [8] (🖩..🖰) POCKET CALCULATOR..TWO BUTTON MOUSE
1F5B1..1F5B2 ; Extended_Pictographic# E0.7 [2] (🖱️..🖲️) computer mouse..trackball
1F5B3..1F5BB ; Extended_Pictographic# E0.0 [9] (🖳..🖻) OLD PERSONAL COMPUTER..DOCUMENT WITH PICTURE
1F5BC ; Extended_Pictographic# E0.7 [1] (🖼️) framed picture
1F5BD..1F5C1 ; Extended_Pictographic# E0.0 [5] (🖽..🗁) FRAME WITH TILES..OPEN FOLDER
1F5C2..1F5C4 ; Extended_Pictographic# E0.7 [3] (🗂️..🗄️) card index dividers..file cabinet
1F5C5..1F5D0 ; Extended_Pictographic# E0.0 [12] (🗅..🗐) EMPTY NOTE..PAGES
1F5D1..1F5D3 ; Extended_Pictographic# E0.7 [3] (🗑️..🗓️) wastebasket..spiral calendar
1F5D4..1F5DB ; Extended_Pictographic# E0.0 [8] (🗔..🗛) DESKTOP WINDOW..DECREASE FONT SIZE SYMBOL
1F5DC..1F5DE ; Extended_Pictographic# E0.7 [3] (🗜️..🗞️) clamp..rolled-up newspaper
1F5DF..1F5E0 ; Extended_Pictographic# E0.0 [2] (🗟..🗠) PAGE WITH CIRCLED TEXT..STOCK CHART
1F5E1 ; Extended_Pictographic# E0.7 [1] (🗡️) dagger
1F5E2 ; Extended_Pictographic# E0.0 [1] (🗢) LIPS
1F5E3 ; Extended_Pictographic# E0.7 [1] (🗣️) speaking head
1F5E4..1F5E7 ; Extended_Pictographic# E0.0 [4] (🗤..🗧) THREE RAYS ABOVE..THREE RAYS RIGHT
1F5E8 ; Extended_Pictographic# E2.0 [1] (🗨️) left speech bubble
1F5E9..1F5EE ; Extended_Pictographic# E0.0 [6] (🗩..🗮) RIGHT SPEECH BUBBLE..LEFT ANGER BUBBLE
1F5EF ; Extended_Pictographic# E0.7 [1] (🗯️) right anger bubble
1F5F0..1F5F2 ; Extended_Pictographic# E0.0 [3] (🗰..🗲) MOOD BUBBLE..LIGHTNING MOOD
1F5F3 ; Extended_Pictographic# E0.7 [1] (🗳️) ballot box with ballot
1F5F4..1F5F9 ; Extended_Pictographic# E0.0 [6] (🗴..🗹) BALLOT SCRIPT X..BALLOT BOX WITH BOLD CHECK
1F5FA ; Extended_Pictographic# E0.7 [1] (🗺️) world map
1F5FB..1F5FF ; Extended_Pictographic# E0.6 [5] (🗻..🗿) mount fuji..moai
1F600 ; Extended_Pictographic# E1.0 [1] (😀) grinning face
1F601..1F606 ; Extended_Pictographic# E0.6 [6] (😁..😆) beaming face with smiling eyes..grinning squinting face
1F607..1F608 ; Extended_Pictographic# E1.0 [2] (😇..😈) smiling face with halo..smiling face with horns
1F609..1F60D ; Extended_Pictographic# E0.6 [5] (😉..😍) winking face..smiling face with heart-eyes
1F60E ; Extended_Pictographic# E1.0 [1] (😎) smiling face with sunglasses
1F60F ; Extended_Pictographic# E0.6 [1] (😏) smirking face
1F610 ; Extended_Pictographic# E0.7 [1] (😐) neutral face
1F611 ; Extended_Pictographic# E1.0 [1] (😑) expressionless face
1F612..1F614 ; Extended_Pictographic# E0.6 [3] (😒..😔) unamused face..pensive face
1F615 ; Extended_Pictographic# E1.0 [1] (😕) confused face
1F616 ; Extended_Pictographic# E0.6 [1] (😖) confounded face
1F617 ; Extended_Pictographic# E1.0 [1] (😗) kissing face
1F618 ; Extended_Pictographic# E0.6 [1] (😘) face blowing a kiss
1F619 ; Extended_Pictographic# E1.0 [1] (😙) kissing face with smiling eyes
1F61A ; Extended_Pictographic# E0.6 [1] (😚) kissing face with closed eyes
1F61B ; Extended_Pictographic# E1.0 [1] (😛) face with tongue
1F61C..1F61E ; Extended_Pictographic# E0.6 [3] (😜..😞) winking face with tongue..disappointed face
1F61F ; Extended_Pictographic# E1.0 [1] (😟) worried face
1F620..1F625 ; Extended_Pictographic# E0.6 [6] (😠..😥) angry face..sad but relieved face
1F626..1F627 ; Extended_Pictographic# E1.0 [2] (😦..😧) frowning face with open mouth..anguished face
1F628..1F62B ; Extended_Pictographic# E0.6 [4] (😨..😫) fearful face..tired face
1F62C ; Extended_Pictographic# E1.0 [1] (😬) grimacing face
1F62D ; Extended_Pictographic# E0.6 [1] (😭) loudly crying face
1F62E..1F62F ; Extended_Pictographic# E1.0 [2] (😮..😯) face with open mouth..hushed face
1F630..1F633 ; Extended_Pictographic# E0.6 [4] (😰..😳) anxious face with sweat..flushed face
1F634 ; Extended_Pictographic# E1.0 [1] (😴) sleeping face
1F635 ; Extended_Pictographic# E0.6 [1] (😵) dizzy face
1F636 ; Extended_Pictographic# E1.0 [1] (😶) face without mouth
1F637..1F640 ; Extended_Pictographic# E0.6 [10] (😷..🙀) face with medical mask..weary cat
1F641..1F644 ; Extended_Pictographic# E1.0 [4] (🙁..🙄) slightly frowning face..face with rolling eyes
1F645..1F64F ; Extended_Pictographic# E0.6 [11] (🙅..🙏) person gesturing NO..folded hands
1F680 ; Extended_Pictographic# E0.6 [1] (🚀) rocket
1F681..1F682 ; Extended_Pictographic# E1.0 [2] (🚁..🚂) helicopter..locomotive
1F683..1F685 ; Extended_Pictographic# E0.6 [3] (🚃..🚅) railway car..bullet train
1F686 ; Extended_Pictographic# E1.0 [1] (🚆) train
1F687 ; Extended_Pictographic# E0.6 [1] (🚇) metro
1F688 ; Extended_Pictographic# E1.0 [1] (🚈) light rail
1F689 ; Extended_Pictographic# E0.6 [1] (🚉) station
1F68A..1F68B ; Extended_Pictographic# E1.0 [2] (🚊..🚋) tram..tram car
1F68C ; Extended_Pictographic# E0.6 [1] (🚌) bus
1F68D ; Extended_Pictographic# E0.7 [1] (🚍) oncoming bus
1F68E ; Extended_Pictographic# E1.0 [1] (🚎) trolleybus
1F68F ; Extended_Pictographic# E0.6 [1] (🚏) bus stop
1F690 ; Extended_Pictographic# E1.0 [1] (🚐) minibus
1F691..1F693 ; Extended_Pictographic# E0.6 [3] (🚑..🚓) ambulance..police car
1F694 ; Extended_Pictographic# E0.7 [1] (🚔) oncoming police car
1F695 ; Extended_Pictographic# E0.6 [1] (🚕) taxi
1F696 ; Extended_Pictographic# E1.0 [1] (🚖) oncoming taxi
1F697 ; Extended_Pictographic# E0.6 [1] (🚗) automobile
1F698 ; Extended_Pictographic# E0.7 [1] (🚘) oncoming automobile
1F699..1F69A ; Extended_Pictographic# E0.6 [2] (🚙..🚚) sport utility vehicle..delivery truck
1F69B..1F6A1 ; Extended_Pictographic# E1.0 [7] (🚛..🚡) articulated lorry..aerial tramway
1F6A2 ; Extended_Pictographic# E0.6 [1] (🚢) ship
1F6A3 ; Extended_Pictographic# E1.0 [1] (🚣) person rowing boat
1F6A4..1F6A5 ; Extended_Pictographic# E0.6 [2] (🚤..🚥) speedboat..horizontal traffic light
1F6A6 ; Extended_Pictographic# E1.0 [1] (🚦) vertical traffic light
1F6A7..1F6AD ; Extended_Pictographic# E0.6 [7] (🚧..🚭) construction..no smoking
1F6AE..1F6B1 ; Extended_Pictographic# E1.0 [4] (🚮..🚱) litter in bin sign..non-potable water
1F6B2 ; Extended_Pictographic# E0.6 [1] (🚲) bicycle
1F6B3..1F6B5 ; Extended_Pictographic# E1.0 [3] (🚳..🚵) no bicycles..person mountain biking
1F6B6 ; Extended_Pictographic# E0.6 [1] (🚶) person walking
1F6B7..1F6B8 ; Extended_Pictographic# E1.0 [2] (🚷..🚸) no pedestrians..children crossing
1F6B9..1F6BE ; Extended_Pictographic# E0.6 [6] (🚹..🚾) men’s room..water closet
1F6BF ; Extended_Pictographic# E1.0 [1] (🚿) shower
1F6C0 ; Extended_Pictographic# E0.6 [1] (🛀) person taking bath
1F6C1..1F6C5 ; Extended_Pictographic# E1.0 [5] (🛁..🛅) bathtub..left luggage
1F6C6..1F6CA ; Extended_Pictographic# E0.0 [5] (🛆..🛊) TRIANGLE WITH ROUNDED CORNERS..GIRLS SYMBOL
1F6CB ; Extended_Pictographic# E0.7 [1] (🛋️) couch and lamp
1F6CC ; Extended_Pictographic# E1.0 [1] (🛌) person in bed
1F6CD..1F6CF ; Extended_Pictographic# E0.7 [3] (🛍️..🛏️) shopping bags..bed
1F6D0 ; Extended_Pictographic# E1.0 [1] (🛐) place of worship
1F6D1..1F6D2 ; Extended_Pictographic# E3.0 [2] (🛑..🛒) stop sign..shopping cart
1F6D3..1F6D4 ; Extended_Pictographic# E0.0 [2] (🛓..🛔) STUPA..PAGODA
1F6D5 ; Extended_Pictographic# E12.0 [1] (🛕) hindu temple
1F6D6..1F6D7 ; Extended_Pictographic# E13.0 [2] (🛖..🛗) hut..elevator
1F6D8..1F6DF ; Extended_Pictographic# E0.0 [8] (🛘..🛟) <reserved-1F6D8>..<reserved-1F6DF>
1F6E0..1F6E5 ; Extended_Pictographic# E0.7 [6] (🛠️..🛥️) hammer and wrench..motor boat
1F6E6..1F6E8 ; Extended_Pictographic# E0.0 [3] (🛦..🛨) UP-POINTING MILITARY AIRPLANE..UP-POINTING SMALL AIRPLANE
1F6E9 ; Extended_Pictographic# E0.7 [1] (🛩️) small airplane
1F6EA ; Extended_Pictographic# E0.0 [1] (🛪) NORTHEAST-POINTING AIRPLANE
1F6EB..1F6EC ; Extended_Pictographic# E1.0 [2] (🛫..🛬) airplane departure..airplane arrival
1F6ED..1F6EF ; Extended_Pictographic# E0.0 [3] (🛭..🛯) <reserved-1F6ED>..<reserved-1F6EF>
1F6F0 ; Extended_Pictographic# E0.7 [1] (🛰️) satellite
1F6F1..1F6F2 ; Extended_Pictographic# E0.0 [2] (🛱..🛲) ONCOMING FIRE ENGINE..DIESEL LOCOMOTIVE
1F6F3 ; Extended_Pictographic# E0.7 [1] (🛳️) passenger ship
1F6F4..1F6F6 ; Extended_Pictographic# E3.0 [3] (🛴..🛶) kick scooter..canoe
1F6F7..1F6F8 ; Extended_Pictographic# E5.0 [2] (🛷..🛸) sled..flying saucer
1F6F9 ; Extended_Pictographic# E11.0 [1] (🛹) skateboard
1F6FA ; Extended_Pictographic# E12.0 [1] (🛺) auto rickshaw
1F6FB..1F6FC ; Extended_Pictographic# E13.0 [2] (🛻..🛼) pickup truck..roller skate
1F6FD..1F6FF ; Extended_Pictographic# E0.0 [3] (🛽..🛿) <reserved-1F6FD>..<reserved-1F6FF>
1F774..1F77F ; Extended_Pictographic# E0.0 [12] (🝴..🝿) <reserved-1F774>..<reserved-1F77F>
1F7D5..1F7DF ; Extended_Pictographic# E0.0 [11] (🟕..🟟) CIRCLED TRIANGLE..<reserved-1F7DF>
1F7E0..1F7EB ; Extended_Pictographic# E12.0 [12] (🟠..🟫) orange circle..brown square
1F7EC..1F7FF ; Extended_Pictographic# E0.0 [20] (🟬..🟿) <reserved-1F7EC>..<reserved-1F7FF>
1F80C..1F80F ; Extended_Pictographic# E0.0 [4] (🠌..🠏) <reserved-1F80C>..<reserved-1F80F>
1F848..1F84F ; Extended_Pictographic# E0.0 [8] (🡈..🡏) <reserved-1F848>..<reserved-1F84F>
1F85A..1F85F ; Extended_Pictographic# E0.0 [6] (🡚..🡟) <reserved-1F85A>..<reserved-1F85F>
1F888..1F88F ; Extended_Pictographic# E0.0 [8] (🢈..🢏) <reserved-1F888>..<reserved-1F88F>
1F8AE..1F8FF ; Extended_Pictographic# E0.0 [82] (🢮..🣿) <reserved-1F8AE>..<reserved-1F8FF>
1F90C ; Extended_Pictographic# E13.0 [1] (🤌) pinched fingers
1F90D..1F90F ; Extended_Pictographic# E12.0 [3] (🤍..🤏) white heart..pinching hand
1F910..1F918 ; Extended_Pictographic# E1.0 [9] (🤐..🤘) zipper-mouth face..sign of the horns
1F919..1F91E ; Extended_Pictographic# E3.0 [6] (🤙..🤞) call me hand..crossed fingers
1F91F ; Extended_Pictographic# E5.0 [1] (🤟) love-you gesture
1F920..1F927 ; Extended_Pictographic# E3.0 [8] (🤠..🤧) cowboy hat face..sneezing face
1F928..1F92F ; Extended_Pictographic# E5.0 [8] (🤨..🤯) face with raised eyebrow..exploding head
1F930 ; Extended_Pictographic# E3.0 [1] (🤰) pregnant woman
1F931..1F932 ; Extended_Pictographic# E5.0 [2] (🤱..🤲) breast-feeding..palms up together
1F933..1F93A ; Extended_Pictographic# E3.0 [8] (🤳..🤺) selfie..person fencing
1F93C..1F93E ; Extended_Pictographic# E3.0 [3] (🤼..🤾) people wrestling..person playing handball
1F93F ; Extended_Pictographic# E12.0 [1] (🤿) diving mask
1F940..1F945 ; Extended_Pictographic# E3.0 [6] (🥀..🥅) wilted flower..goal net
1F947..1F94B ; Extended_Pictographic# E3.0 [5] (🥇..🥋) 1st place medal..martial arts uniform
1F94C ; Extended_Pictographic# E5.0 [1] (🥌) curling stone
1F94D..1F94F ; Extended_Pictographic# E11.0 [3] (🥍..🥏) lacrosse..flying disc
1F950..1F95E ; Extended_Pictographic# E3.0 [15] (🥐..🥞) croissant..pancakes
1F95F..1F96B ; Extended_Pictographic# E5.0 [13] (🥟..🥫) dumpling..canned food
1F96C..1F970 ; Extended_Pictographic# E11.0 [5] (🥬..🥰) leafy green..smiling face with hearts
1F971 ; Extended_Pictographic# E12.0 [1] (🥱) yawning face
1F972 ; Extended_Pictographic# E13.0 [1] (🥲) smiling face with tear
1F973..1F976 ; Extended_Pictographic# E11.0 [4] (🥳..🥶) partying face..cold face
1F977..1F978 ; Extended_Pictographic# E13.0 [2] (🥷..🥸) ninja..disguised face
1F979 ; Extended_Pictographic# E0.0 [1] (🥹) <reserved-1F979>
1F97A ; Extended_Pictographic# E11.0 [1] (🥺) pleading face
1F97B ; Extended_Pictographic# E12.0 [1] (🥻) sari
1F97C..1F97F ; Extended_Pictographic# E11.0 [4] (🥼..🥿) lab coat..flat shoe
1F980..1F984 ; Extended_Pictographic# E1.0 [5] (🦀..🦄) crab..unicorn
1F985..1F991 ; Extended_Pictographic# E3.0 [13] (🦅..🦑) eagle..squid
1F992..1F997 ; Extended_Pictographic# E5.0 [6] (🦒..🦗) giraffe..cricket
1F998..1F9A2 ; Extended_Pictographic# E11.0 [11] (🦘..🦢) kangaroo..swan
1F9A3..1F9A4 ; Extended_Pictographic# E13.0 [2] (🦣..🦤) mammoth..dodo
1F9A5..1F9AA ; Extended_Pictographic# E12.0 [6] (🦥..🦪) sloth..oyster
1F9AB..1F9AD ; Extended_Pictographic# E13.0 [3] (🦫..🦭) beaver..seal
1F9AE..1F9AF ; Extended_Pictographic# E12.0 [2] (🦮..🦯) guide dog..white cane
1F9B0..1F9B9 ; Extended_Pictographic# E11.0 [10] (🦰..🦹) red hair..supervillain
1F9BA..1F9BF ; Extended_Pictographic# E12.0 [6] (🦺..🦿) safety vest..mechanical leg
1F9C0 ; Extended_Pictographic# E1.0 [1] (🧀) cheese wedge
1F9C1..1F9C2 ; Extended_Pictographic# E11.0 [2] (🧁..🧂) cupcake..salt
1F9C3..1F9CA ; Extended_Pictographic# E12.0 [8] (🧃..🧊) beverage box..ice
1F9CB ; Extended_Pictographic# E13.0 [1] (🧋) bubble tea
1F9CC ; Extended_Pictographic# E0.0 [1] (🧌) <reserved-1F9CC>
1F9CD..1F9CF ; Extended_Pictographic# E12.0 [3] (🧍..🧏) person standing..deaf person
1F9D0..1F9E6 ; Extended_Pictographic# E5.0 [23] (🧐..🧦) face with monocle..socks
1F9E7..1F9FF ; Extended_Pictographic# E11.0 [25] (🧧..🧿) red envelope..nazar amulet
1FA00..1FA6F ; Extended_Pictographic# E0.0 [112] (🨀..🩯) NEUTRAL CHESS KING..<reserved-1FA6F>
1FA70..1FA73 ; Extended_Pictographic# E12.0 [4] (🩰..🩳) ballet shoes..shorts
1FA74 ; Extended_Pictographic# E13.0 [1] (🩴) thong sandal
1FA75..1FA77 ; Extended_Pictographic# E0.0 [3] (🩵..🩷) <reserved-1FA75>..<reserved-1FA77>
1FA78..1FA7A ; Extended_Pictographic# E12.0 [3] (🩸..🩺) drop of blood..stethoscope
1FA7B..1FA7F ; Extended_Pictographic# E0.0 [5] (🩻..🩿) <reserved-1FA7B>..<reserved-1FA7F>
1FA80..1FA82 ; Extended_Pictographic# E12.0 [3] (🪀..🪂) yo-yo..parachute
1FA83..1FA86 ; Extended_Pictographic# E13.0 [4] (🪃..🪆) boomerang..nesting dolls
1FA87..1FA8F ; Extended_Pictographic# E0.0 [9] (🪇..🪏) <reserved-1FA87>..<reserved-1FA8F>
1FA90..1FA95 ; Extended_Pictographic# E12.0 [6] (🪐..🪕) ringed planet..banjo
1FA96..1FAA8 ; Extended_Pictographic# E13.0 [19] (🪖..🪨) military helmet..rock
1FAA9..1FAAF ; Extended_Pictographic# E0.0 [7] (🪩..🪯) <reserved-1FAA9>..<reserved-1FAAF>
1FAB0..1FAB6 ; Extended_Pictographic# E13.0 [7] (🪰..🪶) fly..feather
1FAB7..1FABF ; Extended_Pictographic# E0.0 [9] (🪷..🪿) <reserved-1FAB7>..<reserved-1FABF>
1FAC0..1FAC2 ; Extended_Pictographic# E13.0 [3] (🫀..🫂) anatomical heart..people hugging
1FAC3..1FACF ; Extended_Pictographic# E0.0 [13] (🫃..🫏) <reserved-1FAC3>..<reserved-1FACF>
1FAD0..1FAD6 ; Extended_Pictographic# E13.0 [7] (🫐..🫖) blueberries..teapot
1FAD7..1FAFF ; Extended_Pictographic# E0.0 [41] (🫗..🫿) <reserved-1FAD7>..<reserved-1FAFF>
1FC00..1FFFD ; Extended_Pictographic# E0.0[1022] (🰀..🿽) <reserved-1FC00>..<reserved-1FFFD>
# Total elements: 3537
# EOF
File diff suppressed because it is too large Load Diff
+53 -22
View File
@@ -1,5 +1,5 @@
# PropList-12.1.0.txt
# Date: 2019-03-10, 10:53:16 GMT
# PropList-13.0.0.txt
# Date: 2019-11-27, 03:13:28 GMT
# © 2019 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
@@ -61,8 +61,9 @@ FE31..FE32 ; Dash # Pd [2] PRESENTATION FORM FOR VERTICAL EM DASH..PRESENTA
FE58 ; Dash # Pd SMALL EM DASH
FE63 ; Dash # Pd SMALL HYPHEN-MINUS
FF0D ; Dash # Pd FULLWIDTH HYPHEN-MINUS
10EAD ; Dash # Pd YEZIDI HYPHENATION MARK
# Total code points: 28
# Total code points: 29
# ================================================
@@ -197,11 +198,13 @@ FF64 ; Terminal_Punctuation # Po HALFWIDTH IDEOGRAPHIC COMMA
11238..1123C ; Terminal_Punctuation # Po [5] KHOJKI DANDA..KHOJKI DOUBLE SECTION MARK
112A9 ; Terminal_Punctuation # Po MULTANI SECTION MARK
1144B..1144D ; Terminal_Punctuation # Po [3] NEWA DANDA..NEWA COMMA
1145B ; Terminal_Punctuation # Po NEWA PLACEHOLDER MARK
1145A..1145B ; Terminal_Punctuation # Po [2] NEWA DOUBLE COMMA..NEWA PLACEHOLDER MARK
115C2..115C5 ; Terminal_Punctuation # Po [4] SIDDHAM DANDA..SIDDHAM SEPARATOR BAR
115C9..115D7 ; Terminal_Punctuation # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
11641..11642 ; Terminal_Punctuation # Po [2] MODI DANDA..MODI DOUBLE DANDA
1173C..1173E ; Terminal_Punctuation # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
11944 ; Terminal_Punctuation # Po DIVES AKURU DOUBLE DANDA
11946 ; Terminal_Punctuation # Po DIVES AKURU END OF TEXT MARK
11A42..11A43 ; Terminal_Punctuation # Po [2] ZANABAZAR SQUARE MARK SHAD..ZANABAZAR SQUARE MARK DOUBLE SHAD
11A9B..11A9C ; Terminal_Punctuation # Po [2] SOYOMBO MARK SHAD..SOYOMBO MARK DOUBLE SHAD
11AA1..11AA2 ; Terminal_Punctuation # Po [2] SOYOMBO TERMINAL MARK-1..SOYOMBO TERMINAL MARK-2
@@ -217,7 +220,7 @@ FF64 ; Terminal_Punctuation # Po HALFWIDTH IDEOGRAPHIC COMMA
1BC9F ; Terminal_Punctuation # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
1DA87..1DA8A ; Terminal_Punctuation # Po [4] SIGNWRITING COMMA..SIGNWRITING COLON
# Total code points: 264
# Total code points: 267
# ================================================
@@ -525,6 +528,7 @@ FF41..FF46 ; Hex_Digit # L& [6] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH L
0D4A..0D4C ; Other_Alphabetic # Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU
0D57 ; Other_Alphabetic # Mc MALAYALAM AU LENGTH MARK
0D62..0D63 ; Other_Alphabetic # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL
0D81 ; Other_Alphabetic # Mn SINHALA SIGN CANDRABINDU
0D82..0D83 ; Other_Alphabetic # Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA
0DCF..0DD1 ; Other_Alphabetic # Mc [3] SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA
0DD2..0DD4 ; Other_Alphabetic # Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA
@@ -595,6 +599,7 @@ FF41..FF46 ; Hex_Digit # L& [6] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH L
1A65..1A6C ; Other_Alphabetic # Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW
1A6D..1A72 ; Other_Alphabetic # Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI
1A73..1A74 ; Other_Alphabetic # Mn [2] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN MAI KANG
1ABF..1AC0 ; Other_Alphabetic # Mn [2] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER TURNED W BELOW
1B00..1B03 ; Other_Alphabetic # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG
1B04 ; Other_Alphabetic # Mc BALINESE SIGN BISAH
1B35 ; Other_Alphabetic # Mc BALINESE VOWEL SIGN TEDUNG
@@ -676,6 +681,7 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
10A05..10A06 ; Other_Alphabetic # Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O
10A0C..10A0F ; Other_Alphabetic # Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA
10D24..10D27 ; Other_Alphabetic # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
10EAB..10EAC ; Other_Alphabetic # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
11000 ; Other_Alphabetic # Mc BRAHMI SIGN CANDRABINDU
11001 ; Other_Alphabetic # Mn BRAHMI SIGN ANUSVARA
11002 ; Other_Alphabetic # Mc BRAHMI SIGN VISARGA
@@ -694,6 +700,8 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
111B3..111B5 ; Other_Alphabetic # Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II
111B6..111BE ; Other_Alphabetic # Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O
111BF ; Other_Alphabetic # Mc SHARADA VOWEL SIGN AU
111CE ; Other_Alphabetic # Mc SHARADA VOWEL SIGN PRISHTHAMATRA E
111CF ; Other_Alphabetic # Mn SHARADA SIGN INVERTED CANDRABINDU
1122C..1122E ; Other_Alphabetic # Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II
1122F..11231 ; Other_Alphabetic # Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI
11232..11233 ; Other_Alphabetic # Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU
@@ -749,6 +757,11 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
1182C..1182E ; Other_Alphabetic # Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II
1182F..11837 ; Other_Alphabetic # Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA
11838 ; Other_Alphabetic # Mc DOGRA SIGN VISARGA
11930..11935 ; Other_Alphabetic # Mc [6] DIVES AKURU VOWEL SIGN AA..DIVES AKURU VOWEL SIGN E
11937..11938 ; Other_Alphabetic # Mc [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O
1193B..1193C ; Other_Alphabetic # Mn [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU
11940 ; Other_Alphabetic # Mc DIVES AKURU MEDIAL YA
11942 ; Other_Alphabetic # Mc DIVES AKURU MEDIAL RA
119D1..119D3 ; Other_Alphabetic # Mc [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II
119D4..119D7 ; Other_Alphabetic # Mn [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR
119DA..119DB ; Other_Alphabetic # Mn [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI
@@ -790,6 +803,7 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
16F4F ; Other_Alphabetic # Mn MIAO SIGN CONSONANT MODIFIER BAR
16F51..16F87 ; Other_Alphabetic # Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI
16F8F..16F92 ; Other_Alphabetic # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
16FF0..16FF1 ; Other_Alphabetic # Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY
1BC9E ; Other_Alphabetic # Mn DUPLOYAN DOUBLE MARK
1E000..1E006 ; Other_Alphabetic # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE
1E008..1E018 ; Other_Alphabetic # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU
@@ -801,7 +815,7 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
1F150..1F169 ; Other_Alphabetic # So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z
1F170..1F189 ; Other_Alphabetic # So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z
# Total code points: 1377
# Total code points: 1398
# ================================================
@@ -809,21 +823,24 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
3007 ; Ideographic # Nl IDEOGRAPHIC NUMBER ZERO
3021..3029 ; Ideographic # Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE
3038..303A ; Ideographic # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY
3400..4DB5 ; Ideographic # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5
4E00..9FEF ; Ideographic # Lo [20976] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FEF
3400..4DBF ; Ideographic # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF
4E00..9FFC ; Ideographic # Lo [20989] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFC
F900..FA6D ; Ideographic # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D
FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
16FE4 ; Ideographic # Mn KHITAN SMALL SCRIPT FILLER
17000..187F7 ; Ideographic # Lo [6136] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F7
18800..18AF2 ; Ideographic # Lo [755] TANGUT COMPONENT-001..TANGUT COMPONENT-755
18800..18CD5 ; Ideographic # Lo [1238] TANGUT COMPONENT-001..KHITAN SMALL SCRIPT CHARACTER-18CD5
18D00..18D08 ; Ideographic # Lo [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08
1B170..1B2FB ; Ideographic # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB
20000..2A6D6 ; Ideographic # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6
20000..2A6DD ; Ideographic # Lo [42718] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DD
2A700..2B734 ; Ideographic # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
2B740..2B81D ; Ideographic # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
2B820..2CEA1 ; Ideographic # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
2CEB0..2EBE0 ; Ideographic # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
2F800..2FA1D ; Ideographic # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
30000..3134A ; Ideographic # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
# Total code points: 96190
# Total code points: 101652
# ================================================
@@ -882,6 +899,7 @@ FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COM
0AFD..0AFF ; Diacritic # Mn [3] GUJARATI SIGN THREE-DOT NUKTA ABOVE..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE
0B3C ; Diacritic # Mn ORIYA SIGN NUKTA
0B4D ; Diacritic # Mn ORIYA SIGN VIRAMA
0B55 ; Diacritic # Mn ORIYA SIGN OVERLINE
0BCD ; Diacritic # Mn TAMIL SIGN VIRAMA
0C4D ; Diacritic # Mn TELUGU SIGN VIRAMA
0CBC ; Diacritic # Mn KANNADA SIGN NUKTA
@@ -978,6 +996,8 @@ AAC2 ; Diacritic # Lo TAI VIET TONE MAI SONG
AAF6 ; Diacritic # Mn MEETEI MAYEK VIRAMA
AB5B ; Diacritic # Sk MODIFIER BREVE WITH INVERTED BREVE
AB5C..AB5F ; Diacritic # Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK
AB69 ; Diacritic # Lm MODIFIER LETTER SMALL TURNED W
AB6A..AB6B ; Diacritic # Sk [2] MODIFIER LETTER LEFT TACK..MODIFIER LETTER RIGHT TACK
ABEC ; Diacritic # Mc MEETEI MAYEK LUM IYEK
ABED ; Diacritic # Mn MEETEI MAYEK APUN IYEK
FB1E ; Diacritic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
@@ -1013,6 +1033,9 @@ FFE3 ; Diacritic # Sk FULLWIDTH MACRON
116B7 ; Diacritic # Mn TAKRI SIGN NUKTA
1172B ; Diacritic # Mn AHOM SIGN KILLER
11839..1183A ; Diacritic # Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA
1193D ; Diacritic # Mc DIVES AKURU SIGN HALANTA
1193E ; Diacritic # Mn DIVES AKURU VIRAMA
11943 ; Diacritic # Mn DIVES AKURU SIGN NUKTA
119E0 ; Diacritic # Mn NANDINAGARI SIGN VIRAMA
11A34 ; Diacritic # Mn ZANABAZAR SQUARE SIGN VIRAMA
11A47 ; Diacritic # Mn ZANABAZAR SQUARE SUBJOINER
@@ -1025,6 +1048,7 @@ FFE3 ; Diacritic # Sk FULLWIDTH MACRON
16B30..16B36 ; Diacritic # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
16F8F..16F92 ; Diacritic # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
16F93..16F9F ; Diacritic # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8
16FF0..16FF1 ; Diacritic # Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY
1D167..1D169 ; Diacritic # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3
1D16D..1D172 ; Diacritic # Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5
1D17B..1D182 ; Diacritic # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE
@@ -1036,7 +1060,7 @@ FFE3 ; Diacritic # Sk FULLWIDTH MACRON
1E944..1E946 ; Diacritic # Mn [3] ADLAM ALIF LENGTHENER..ADLAM GEMINATION MARK
1E948..1E94A ; Diacritic # Mn [3] ADLAM CONSONANT MODIFIER..ADLAM NUKTA
# Total code points: 873
# Total code points: 882
# ================================================
@@ -1044,6 +1068,7 @@ FFE3 ; Diacritic # Sk FULLWIDTH MACRON
02D0..02D1 ; Extender # Lm [2] MODIFIER LETTER TRIANGULAR COLON..MODIFIER LETTER HALF TRIANGULAR COLON
0640 ; Extender # Lm ARABIC TATWEEL
07FA ; Extender # Lm NKO LAJANYALAN
0B55 ; Extender # Mn ORIYA SIGN OVERLINE
0E46 ; Extender # Lm THAI CHARACTER MAIYAMOK
0EC6 ; Extender # Lm LAO KO LA
180A ; Extender # Po MONGOLIAN NIRUGU
@@ -1072,7 +1097,7 @@ FF70 ; Extender # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND
1E13C..1E13D ; Extender # Lm [2] NYIAKENG PUACHUE HMONG SIGN XW XW..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER
1E944..1E946 ; Extender # Mn [3] ADLAM ALIF LENGTHENER..ADLAM GEMINATION MARK
# Total code points: 47
# Total code points: 48
# ================================================
@@ -1155,11 +1180,12 @@ FF9E..FF9F ; Other_Grapheme_Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND
114B0 ; Other_Grapheme_Extend # Mc TIRHUTA VOWEL SIGN AA
114BD ; Other_Grapheme_Extend # Mc TIRHUTA VOWEL SIGN SHORT O
115AF ; Other_Grapheme_Extend # Mc SIDDHAM VOWEL SIGN AA
11930 ; Other_Grapheme_Extend # Mc DIVES AKURU VOWEL SIGN AA
1D165 ; Other_Grapheme_Extend # Mc MUSICAL SYMBOL COMBINING STEM
1D16E..1D172 ; Other_Grapheme_Extend # Mc [5] MUSICAL SYMBOL COMBINING FLAG-1..MUSICAL SYMBOL COMBINING FLAG-5
E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG
# Total code points: 126
# Total code points: 127
# ================================================
@@ -1184,8 +1210,8 @@ E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG
# ================================================
3400..4DB5 ; Unified_Ideograph # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5
4E00..9FEF ; Unified_Ideograph # Lo [20976] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FEF
3400..4DBF ; Unified_Ideograph # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF
4E00..9FFC ; Unified_Ideograph # Lo [20989] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFC
FA0E..FA0F ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA0E..CJK COMPATIBILITY IDEOGRAPH-FA0F
FA11 ; Unified_Ideograph # Lo CJK COMPATIBILITY IDEOGRAPH-FA11
FA13..FA14 ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA13..CJK COMPATIBILITY IDEOGRAPH-FA14
@@ -1193,13 +1219,14 @@ FA1F ; Unified_Ideograph # Lo CJK COMPATIBILITY IDEOGRAPH-FA1F
FA21 ; Unified_Ideograph # Lo CJK COMPATIBILITY IDEOGRAPH-FA21
FA23..FA24 ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA23..CJK COMPATIBILITY IDEOGRAPH-FA24
FA27..FA29 ; Unified_Ideograph # Lo [3] CJK COMPATIBILITY IDEOGRAPH-FA27..CJK COMPATIBILITY IDEOGRAPH-FA29
20000..2A6D6 ; Unified_Ideograph # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6
20000..2A6DD ; Unified_Ideograph # Lo [42718] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DD
2A700..2B734 ; Unified_Ideograph # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
2B740..2B81D ; Unified_Ideograph # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
2B820..2CEA1 ; Unified_Ideograph # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
2CEB0..2EBE0 ; Unified_Ideograph # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
30000..3134A ; Unified_Ideograph # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
# Total code points: 87887
# Total code points: 92856
# ================================================
@@ -1362,6 +1389,8 @@ FF61 ; Sentence_Terminal # Po HALFWIDTH IDEOGRAPHIC FULL STOP
115C9..115D7 ; Sentence_Terminal # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
11641..11642 ; Sentence_Terminal # Po [2] MODI DANDA..MODI DOUBLE DANDA
1173C..1173E ; Sentence_Terminal # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
11944 ; Sentence_Terminal # Po DIVES AKURU DOUBLE DANDA
11946 ; Sentence_Terminal # Po DIVES AKURU END OF TEXT MARK
11A42..11A43 ; Sentence_Terminal # Po [2] ZANABAZAR SQUARE MARK SHAD..ZANABAZAR SQUARE MARK DOUBLE SHAD
11A9B..11A9C ; Sentence_Terminal # Po [2] SOYOMBO MARK SHAD..SOYOMBO MARK DOUBLE SHAD
11C41..11C42 ; Sentence_Terminal # Po [2] BHAIKSUKI DANDA..BHAIKSUKI DOUBLE DANDA
@@ -1374,7 +1403,7 @@ FF61 ; Sentence_Terminal # Po HALFWIDTH IDEOGRAPHIC FULL STOP
1BC9F ; Sentence_Terminal # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
1DA88 ; Sentence_Terminal # Po SIGNWRITING FULL STOP
# Total code points: 141
# Total code points: 143
# ================================================
@@ -1574,8 +1603,8 @@ E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION S
2B4D..2B73 ; Pattern_Syntax # So [39] DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW..DOWNWARDS TRIANGLE-HEADED ARROW TO BAR
2B74..2B75 ; Pattern_Syntax # Cn [2] <reserved-2B74>..<reserved-2B75>
2B76..2B95 ; Pattern_Syntax # So [32] NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW
2B96..2B97 ; Pattern_Syntax # Cn [2] <reserved-2B96>..<reserved-2B97>
2B98..2BFF ; Pattern_Syntax # So [104] THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD..HELLSCHREIBER PAUSE SYMBOL
2B96 ; Pattern_Syntax # Cn <reserved-2B96>
2B97..2BFF ; Pattern_Syntax # So [105] SYMBOL FOR TYPE A ELECTRONICS..HELLSCHREIBER PAUSE SYMBOL
2E00..2E01 ; Pattern_Syntax # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER
2E02 ; Pattern_Syntax # Pi LEFT SUBSTITUTION BRACKET
2E03 ; Pattern_Syntax # Pf RIGHT SUBSTITUTION BRACKET
@@ -1614,7 +1643,9 @@ E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION S
2E41 ; Pattern_Syntax # Po REVERSED COMMA
2E42 ; Pattern_Syntax # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK
2E43..2E4F ; Pattern_Syntax # Po [13] DASH WITH LEFT UPTURN..CORNISH VERSE DIVIDER
2E50..2E7F ; Pattern_Syntax # Cn [48] <reserved-2E50>..<reserved-2E7F>
2E50..2E51 ; Pattern_Syntax # So [2] CROSS PATTY WITH RIGHT CROSSBAR..CROSS PATTY WITH LEFT CROSSBAR
2E52 ; Pattern_Syntax # Po TIRONIAN SIGN CAPITAL ET
2E53..2E7F ; Pattern_Syntax # Cn [45] <reserved-2E53>..<reserved-2E7F>
3001..3003 ; Pattern_Syntax # Po [3] IDEOGRAPHIC COMMA..DITTO MARK
3008 ; Pattern_Syntax # Ps LEFT ANGLE BRACKET
3009 ; Pattern_Syntax # Pe RIGHT ANGLE BRACKET
+4 -2
View File
@@ -1,5 +1,5 @@
# SpecialCasing-12.1.0.txt
# Date: 2019-03-10, 10:53:28 GMT
# SpecialCasing-13.0.0.txt
# Date: 2019-09-08, 23:31:24 GMT
# © 2019 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
@@ -194,3 +194,5 @@ FB17; FB17; 0544 056D; 0544 053D; # ARMENIAN SMALL LIGATURE MEN XEH
1FB7; 1FB7; 0391 0342 0345; 0391 0342 0399; # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI
1FC7; 1FC7; 0397 0342 0345; 0397 0342 0399; # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI
1FF7; 1FF7; 03A9 0342 0345; 03A9 0342 0399; # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI
# EOF
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -138,7 +138,7 @@ defmodule String.Casing do
codes =
special_path
|> File.read!()
|> String.split("\n", trim: true)
|> String.split(["\r\n", "\n"], trim: true)
|> Enum.reduce(codes, fn
"", acc ->
acc
@@ -325,7 +325,7 @@ defmodule String.Break do
whitespace =
prop_path
|> File.read!()
|> String.split("\n")
|> String.split(["\r\n", "\n"])
|> Enum.reduce([], fn line, acc ->
case :binary.split(line, ";") do
[<<first::4-bytes, "..", last::4-bytes, _::binary>>, <<" White_Space", _::binary>>] ->
+3 -3
View File
@@ -47,7 +47,7 @@ defmodule String.Tokenizer do
{start, continue, patterns} =
prop_path
|> File.read!()
|> String.split("\n", trim: true)
|> String.split(["\r\n", "\n"], trim: true)
|> Enum.reduce({start, continue, []}, fn line, acc ->
[codepoints | category] = :binary.split(line, ";")
@@ -129,8 +129,8 @@ defmodule String.Tokenizer do
defp unicode_start?(_), do: false
unless {13312, 19893} in range do
raise "CHECK: CJK Ideograph not in range"
unless {13312, 19903} in range do
raise "CHECK: CJK Ideograph not in range. Make sure all properties are listed."
end
for {first, last} <- rangify.(unicode_continue) do
+12 -9
View File
@@ -1,17 +1,20 @@
# How to update the Unicode files
#
# 1. Update PropList.txt by copying original as is
# 2. Update SpecialCasing.txt by copying original and removing conditional mappings
# 3. Update GraphemeBreakProperty.txt by copying original as is
# 4. Copy Extended_Pictographic from emoji-data at the end of GraphemeBreakProperty.txt
# 5. Update GraphemeBreakTest.txt by copying original as is
# 6. Update String.Unicode.version/0 and on String module docs
# 7. make unicode
# 8. elixir lib/elixir/unicode/graphemes_test.exs
# Unicode files can be found in https://www.unicode.org/Public/
#
# 1. Replace UnicodeData.txt by copying original
# 2. Replace PropList.txt by copying original
# 3. Replace SpecialCasing.txt by copying original and removing conditional mappings
# 4. Replace GraphemeBreakTest.txt by copying original auxiliary/GraphemeBreakTest.txt
# 5. Replace GraphemeBreakProperty.txt by copying original auxiliary/GraphemeBreakProperty.txt
# 6. Append Extended_Pictographic from emoji/emoji-data.txt to the end of GraphemeBreakProperty.txt
# 7. Update String.Unicode.version/0 and on String module docs
# 8. make unicode
# 9. elixir lib/elixir/unicode/graphemes_test.exs
defmodule String.Unicode do
@moduledoc false
def version, do: {12, 1, 0}
def version, do: {13, 0, 0}
cluster_path = Path.join(__DIR__, "GraphemeBreakProperty.txt")
regex = ~r/(?:^([0-9A-F]+)(?:\.\.([0-9A-F]+))?)\s+;\s(\w+)/m
+29 -1
View File
@@ -274,7 +274,9 @@ defmodule ExUnit do
* `:seed` - an integer seed value to randomize the test suite. This seed
is also mixed with the test module and name to create a new unique seed
on every test, which is automatically fed into the `:rand` module. This
provides randomness between tests, but predictable and reproducible results;
provides randomness between tests, but predictable and reproducible
results. A `:seed` of `0` will disable randomization and the tests in each
file will always run in the order that they were defined in;
* `:slowest` - prints timing information for the N slowest tests. Running
ExUnit with slow test reporting automatically runs in `trace` mode. It
@@ -350,10 +352,36 @@ defmodule ExUnit do
"""
@spec run() :: suite_result()
def run do
_ = ExUnit.Server.modules_loaded()
options = persist_defaults(configuration())
ExUnit.Runner.run(options, nil)
end
@doc """
Starts tests asynchronously while test cases are still loading.
It returns a task that must be given to `await_run/0` when a result
is desired.
"""
@doc since: "1.12.0"
@spec async_run() :: Task.t()
def async_run() do
Task.async(fn ->
options = persist_defaults(configuration())
ExUnit.Runner.run(options, nil)
end)
end
@doc """
Awaits for a test suite that has been started with `async_run/0`.
"""
@doc since: "1.12.0"
@spec await_run(Task.t()) :: suite_result()
def await_run(task) do
ExUnit.Server.modules_loaded()
Task.await(task, :infinity)
end
@doc """
Sets a callback to be executed after the completion of a test suite.
+1 -1
View File
@@ -231,7 +231,7 @@ defmodule ExUnit.Formatter do
{header, wrapped_reason, wrapped_stack} ->
struct = Exception.normalize(:error, wrapped_reason, wrapped_stack)
{formatted_reason, _} =
{formatted_reason, wrapped_stack} =
format_exception(test, struct, wrapped_stack, width, formatter, @counter_padding)
formatted_stack = format_stacktrace(wrapped_stack, test.module, test.name, formatter)
+4
View File
@@ -58,6 +58,10 @@ defmodule ExUnit.Server do
{:reply, state.sync_modules, %{state | sync_modules: [], loaded: System.monotonic_time()}}
end
def handle_call(:modules_loaded, _from, %{loaded: :done} = state) do
{:reply, 0, state}
end
def handle_call(:modules_loaded, _from, %{loaded: loaded} = state) when is_integer(loaded) do
diff = System.convert_time_unit(System.monotonic_time() - loaded, :native, :microsecond)
{:reply, diff, take_modules(%{state | loaded: :done})}
@@ -32,7 +32,6 @@ defmodule ExUnit.CallbacksTest do
end
end
ExUnit.Server.modules_loaded()
assert capture_io(fn -> ExUnit.run() end) =~ "1 test, 0 failures"
end
@@ -63,7 +62,6 @@ defmodule ExUnit.CallbacksTest do
defp store_5(context), do: store(context, 5)
end
ExUnit.Server.modules_loaded()
assert capture_io(fn -> ExUnit.run() end) =~ "1 test, 0 failures"
end
@@ -82,8 +80,6 @@ defmodule ExUnit.CallbacksTest do
defp error, do: :error
end
ExUnit.Server.modules_loaded()
assert capture_io(fn -> ExUnit.run() end) =~
"** (MatchError) no match of right hand side value: :error"
end
@@ -103,8 +99,6 @@ defmodule ExUnit.CallbacksTest do
defp error, do: :error
end
ExUnit.Server.modules_loaded()
assert capture_io(fn -> ExUnit.run() end) =~
"** (MatchError) no match of right hand side value: :error"
end
@@ -124,7 +118,6 @@ defmodule ExUnit.CallbacksTest do
end
end
ExUnit.Server.modules_loaded()
assert capture_io(fn -> ExUnit.run() end) =~ "supervisor shutdown timed out after 500ms"
end
@@ -140,8 +133,6 @@ defmodule ExUnit.CallbacksTest do
defp error, do: :error
end
ExUnit.Server.modules_loaded()
assert capture_io(fn -> ExUnit.run() end) =~
"** (MatchError) no match of right hand side value: :error"
end
@@ -156,7 +147,6 @@ defmodule ExUnit.CallbacksTest do
end
end
ExUnit.Server.modules_loaded()
assert capture_io(fn -> ExUnit.run() end) =~ ">) killed"
end
@@ -199,7 +189,6 @@ defmodule ExUnit.CallbacksTest do
end
end
ExUnit.Server.modules_loaded()
output = capture_io(fn -> ExUnit.run() end)
assert output =~ "on_exit run"
assert output =~ "1 test, 0 failures"
@@ -251,7 +240,6 @@ defmodule ExUnit.CallbacksTest do
end
no_formatters!()
ExUnit.Server.modules_loaded()
output = capture_io(fn -> ExUnit.run() end)
assert output =~ """
@@ -295,7 +283,6 @@ defmodule ExUnit.CallbacksTest do
end
no_formatters!()
ExUnit.Server.modules_loaded()
output = capture_io(fn -> ExUnit.run() end)
assert output =~ """
@@ -318,8 +305,6 @@ defmodule ExUnit.CallbacksTest do
end
end
ExUnit.Server.modules_loaded()
assert capture_io(fn -> ExUnit.run() end) =~
"** (RuntimeError) expected ExUnit callback in " <>
"ExUnit.CallbacksTest.SetupErrorTest to return " <>
@@ -339,8 +324,6 @@ defmodule ExUnit.CallbacksTest do
end
end
ExUnit.Server.modules_loaded()
assert capture_io(fn -> ExUnit.run() end) =~
"** (RuntimeError) ExUnit callback in " <>
"ExUnit.CallbacksTest.SetupReservedTest is " <>
@@ -477,7 +477,6 @@ defmodule ExUnit.DocTestTest do
doctest ExUnit.DocTestTest.SomewhatGoodModuleWithOnly, only: [one: 0, two: 0], import: true
end
ExUnit.Server.modules_loaded()
assert capture_io(fn -> ExUnit.run() end) =~ "2 doctests, 1 failure"
end
@@ -487,7 +486,6 @@ defmodule ExUnit.DocTestTest do
doctest ExUnit.DocTestTest.SomewhatGoodModuleWithOnly, only: [], import: true
end
ExUnit.Server.modules_loaded()
output = capture_io(fn -> ExUnit.run() end)
assert output =~ "0 failures"
@@ -500,7 +498,6 @@ defmodule ExUnit.DocTestTest do
doctest ExUnit.DocTestTest.SomewhatGoodModuleWithOnly, tags: [skip: true], import: true
end
ExUnit.Server.modules_loaded()
output = capture_io(fn -> ExUnit.run() end)
assert output =~ "0 failures"
@@ -519,7 +516,6 @@ defmodule ExUnit.DocTestTest do
doctest_line = __ENV__.line - 3
ExUnit.configure(seed: 0, colors: [enabled: false])
ExUnit.Server.modules_loaded()
output = capture_io(fn -> ExUnit.run() end)
assert output =~ """
@@ -716,7 +712,6 @@ defmodule ExUnit.DocTestTest do
starting_line = ExUnit.DocTestTest.PatternMatching.starting_line() + 18
ExUnit.configure(seed: 0, colors: [enabled: false])
ExUnit.Server.modules_loaded()
output = capture_io(fn -> ExUnit.run() end)
assert output =~ """
@@ -818,7 +813,6 @@ defmodule ExUnit.DocTestTest do
doctest ExUnit.DocTestTest.Numbered
end
ExUnit.Server.modules_loaded()
assert capture_io(fn -> ExUnit.run() end) =~ "1 doctest, 0 failures"
end
@@ -847,7 +841,6 @@ defmodule ExUnit.DocTestTest do
end
end
ExUnit.Server.modules_loaded()
assert capture_io(fn -> ExUnit.run() end) =~ "2 doctests, 0 failures"
end
+4 -1
View File
@@ -153,8 +153,9 @@ defmodule ExUnit.FormatterTest do
end
failure = [{{:EXIT, self()}, {error, stack}, []}]
format = trim_multiline_whitespace(format_test_failure(test(), failure, 1, 80, &formatter/2))
assert trim_multiline_whitespace(format_test_failure(test(), failure, 1, 80, &formatter/2)) =~
assert format =~
"""
1) world (Hello)
test/ex_unit/formatter_test.exs:1
@@ -174,6 +175,8 @@ defmodule ExUnit.FormatterTest do
def fetch(%module{} = container, key)
"""
assert format =~ ~r"lib/access.ex:\d+: Access.fetch/2"
end
test "formats test EXITs with assertion errors" do
@@ -28,8 +28,6 @@ defmodule ExUnit.RegisterTest do
defp succeed, do: true
end
ExUnit.Server.modules_loaded()
assert capture_io(fn ->
assert ExUnit.run() == %{failures: 0, skipped: 0, total: 2, excluded: 0}
end) =~ "1 property, 1 test, 0 failures"
@@ -68,8 +66,6 @@ defmodule ExUnit.RegisterTest do
defp succeed, do: true
end
ExUnit.Server.modules_loaded()
assert capture_io(fn ->
assert ExUnit.run() == %{failures: 0, skipped: 0, total: 4, excluded: 0}
end) =~ "2 properties, 2 tests, 0 failures"
+8 -28
View File
@@ -5,7 +5,7 @@ defmodule ExUnitTest do
import ExUnit.CaptureIO
test "supports many runs" do
test "supports many runs and loads" do
defmodule SampleTest do
use ExUnit.Case
@@ -18,12 +18,18 @@ defmodule ExUnitTest do
end
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit([])
assert capture_io(fn ->
assert ExUnit.run() == %{failures: 2, skipped: 0, total: 2, excluded: 0}
end) =~ "\n2 tests, 2 failures\n"
ExUnit.Server.modules_loaded()
assert capture_io(fn ->
assert ExUnit.async_run() |> ExUnit.await_run() ==
%{failures: 0, skipped: 0, total: 0, excluded: 0}
end) =~ "\n0 failures\n"
end
test "prints aborted runs on sigquit", config do
@@ -50,7 +56,6 @@ defmodule ExUnitTest do
test "true", do: :ok
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit(max_cases: 8)
result =
@@ -94,7 +99,6 @@ defmodule ExUnitTest do
end
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit([])
assert capture_io(fn ->
@@ -112,8 +116,6 @@ defmodule ExUnitTest do
end
end
ExUnit.Server.modules_loaded()
output = capture_io(fn -> ExUnit.run() end)
assert output =~ "** (ExUnit.TimeoutError) test timed out after 10ms"
assert output =~ ~r"\(elixir #{System.version()}\) lib/process\.ex:\d+: Process\.sleep/1"
@@ -129,7 +131,6 @@ defmodule ExUnitTest do
end
ExUnit.configure(timeout: 5)
ExUnit.Server.modules_loaded()
output = capture_io(fn -> ExUnit.run() end)
assert output =~ "** (ExUnit.TimeoutError) test timed out after 5ms"
after
@@ -155,7 +156,6 @@ defmodule ExUnitTest do
end
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit(slowest: 2)
output = capture_io(fn -> ExUnit.run() end)
@@ -273,7 +273,6 @@ defmodule ExUnitTest do
end
end
ExUnit.Server.modules_loaded()
output = capture_io(&ExUnit.run/0)
assert output =~ "[debug] two\n"
refute output =~ "[debug] one\n"
@@ -308,7 +307,6 @@ defmodule ExUnitTest do
end
end)
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit([])
output =
@@ -364,7 +362,6 @@ defmodule ExUnitTest do
test "this is not implemented yet"
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit([])
output =
@@ -392,7 +389,6 @@ defmodule ExUnitTest do
test "this will also raise", do: raise("oops")
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit([])
output =
@@ -461,7 +457,6 @@ defmodule ExUnitTest do
test "sample", do: :ok
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit([])
output =
@@ -483,8 +478,6 @@ defmodule ExUnitTest do
test "sample", do: :ok
end
ExUnit.Server.modules_loaded()
output =
capture_io(fn ->
assert ExUnit.run() == %{failures: 1, skipped: 0, total: 1, excluded: 0}
@@ -504,8 +497,6 @@ defmodule ExUnitTest do
test "sample", do: :ok
end
ExUnit.Server.modules_loaded()
capture_io(fn ->
assert ExUnit.run() == %{failures: 0, skipped: 0, total: 1, excluded: 0}
end)
@@ -532,7 +523,6 @@ defmodule ExUnitTest do
end
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit(seed: 1)
assert capture_io(fn ->
@@ -567,7 +557,6 @@ defmodule ExUnitTest do
test "excluded #{__ENV__.line}", do: assert(false)
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit([])
output =
@@ -591,8 +580,6 @@ defmodule ExUnitTest do
end
end
ExUnit.Server.modules_loaded()
ExUnit.after_suite(fn _ -> send(:after_suite_test_process, :first_after_suite) end)
ExUnit.after_suite(fn result -> send(:after_suite_test_process, result) end)
ExUnit.after_suite(fn _ -> send(:after_suite_test_process, :third_after_suite) end)
@@ -645,7 +632,6 @@ defmodule ExUnitTest do
test "excluded #{__ENV__.line}", do: assert(false)
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit(max_failures: 2)
output =
@@ -677,7 +663,6 @@ defmodule ExUnitTest do
test "excluded #{__ENV__.line}", do: assert(false)
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit(max_failures: 3)
output =
@@ -712,7 +697,6 @@ defmodule ExUnitTest do
test "excluded #{__ENV__.line}", do: assert(true)
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit(max_failures: 2)
output =
@@ -747,7 +731,6 @@ defmodule ExUnitTest do
test "excluded #{__ENV__.line}", do: assert(false)
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit(max_failures: 2)
output =
@@ -775,7 +758,6 @@ defmodule ExUnitTest do
test "error", do: assert(false)
end
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit(max_failures: 1)
output =
@@ -787,7 +769,6 @@ defmodule ExUnitTest do
assert output =~ "\n1 test, 1 failure\n"
capture_io(fn ->
ExUnit.Server.modules_loaded()
assert ExUnit.run() == %{total: 0, failures: 0, excluded: 0, skipped: 0}
end)
end
@@ -803,7 +784,6 @@ defmodule ExUnitTest do
end
end) =~ "test context is always a map. The pattern \"[conn: conn]\" will never match"
ExUnit.Server.modules_loaded()
configure_and_reload_on_exit([])
assert capture_io(fn ->
+1 -1
View File
@@ -1,2 +1,2 @@
Logger.configure_backend(:console, colors: [enabled: false])
ExUnit.start(trace: "--trace" in System.argv())
ExUnit.start()
+2 -2
View File
@@ -312,7 +312,7 @@ defmodule IEx do
results in:
$ iex
Erlang/OTP 21 [...]
Erlang/OTP 22 [...]
hello world
Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help)
@@ -336,7 +336,7 @@ defmodule IEx do
Now run the shell:
$ iex
Erlang/OTP 21 [...]
Erlang/OTP 22 [...]
Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> [1, 2, 3, 4, 5]

Some files were not shown because too many files have changed in this diff Show More