Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42807d288e | ||
|
|
3b8d7fa15d | ||
|
|
d1d5e04319 | ||
|
|
ba1fd1abb8 | ||
|
|
8fd6c8f845 | ||
|
|
95dcbe9fe0 | ||
|
|
98a79dc839 | ||
|
|
29444793b7 | ||
|
|
ff3674ddef | ||
|
|
0460017c5c | ||
|
|
f3b870857a | ||
|
|
faa2f35d8e | ||
|
|
3339168330 | ||
|
|
1c3ee4ed72 | ||
|
|
926455ca24 | ||
|
|
f73e318bce | ||
|
|
1f3b022340 | ||
|
|
f82f2c7b3e | ||
|
|
63e6f24457 | ||
|
|
aa25920f75 | ||
|
|
64dcd3f937 | ||
|
|
4c6f393bd0 | ||
|
|
d11396204b | ||
|
|
05ab231bc6 | ||
|
|
9fcdf234dd | ||
|
|
14afabb7c8 | ||
|
|
2d5141d69d | ||
|
|
480c19cb5b | ||
|
|
1c9d7365db | ||
|
|
a5caf4bf56 | ||
|
|
767e3479df | ||
|
|
863c49899c | ||
|
|
5467b4e335 | ||
|
|
7aec544b22 | ||
|
|
f71f37e43d | ||
|
|
ff96fa2834 | ||
|
|
49bc4fc0ea | ||
|
|
fe3c393c3f | ||
|
|
d9d70158a6 | ||
|
|
a582bd931f | ||
|
|
f358cd4977 | ||
|
|
47b4952d73 | ||
|
|
ce321f8cf4 | ||
|
|
77fa0c4f46 | ||
|
|
3842dcce87 | ||
|
|
22f2fa9ddc | ||
|
|
148cdcec14 | ||
|
|
c13335ffd4 | ||
|
|
d85d13fb28 | ||
|
|
0b4eb72609 | ||
|
|
a83fddb3c8 | ||
|
|
81d04d80fa | ||
|
|
ccb554614d | ||
|
|
02d0567f05 | ||
|
|
4582f87faf | ||
|
|
274557b131 | ||
|
|
d7946202bf | ||
|
|
9cfa855237 | ||
|
|
381991149c | ||
|
|
bd38b6ed4c | ||
|
|
b571ddb3e0 | ||
|
|
877b3d929b | ||
|
|
7e2b22402c | ||
|
|
3df04b23f9 | ||
|
|
33feac639a | ||
|
|
8c4bed23e6 | ||
|
|
b9c374e9bb | ||
|
|
c045969850 | ||
|
|
56e01f151b | ||
|
|
171caface8 | ||
|
|
b2a04575c3 | ||
|
|
5ce4ede684 | ||
|
|
31d2b99879 | ||
|
|
b49bac34d4 | ||
|
|
5b3ef7705e | ||
|
|
64fca3cdb1 | ||
|
|
415d4647c4 | ||
|
|
91344a24a8 | ||
|
|
5fbdee2714 | ||
|
|
832fbce136 | ||
|
|
c45d9ab13d | ||
|
|
94096055ad | ||
|
|
02e9b898c4 | ||
|
|
1c01996c29 | ||
|
|
103db3a2ef | ||
|
|
6f95bf274f | ||
|
|
7210ab2fbd | ||
|
|
174b77150e | ||
|
|
1dd09cb0bc | ||
|
|
203cb4bb6f | ||
|
|
8ff5c76b9c | ||
|
|
51de0e09a7 | ||
|
|
9b38e4ed07 | ||
|
|
2d40ad09d1 | ||
|
|
00d1bc6765 | ||
|
|
544466a4d1 | ||
|
|
385d2cd54a |
+4
-3
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+45
-11
@@ -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,38 @@ 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.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 +116,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 +130,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 +145,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 +165,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
|
||||
|
||||
@@ -169,11 +196,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 +227,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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -180,7 +180,7 @@ 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)
|
||||
COMPILE_DOCS = 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: compile ../ex_doc/bin/ex_doc docs_elixir docs_eex docs_mix docs_iex docs_ex_unit docs_logger
|
||||
|
||||
@@ -192,27 +192,27 @@ docs_elixir: compile ../ex_doc/bin/ex_doc
|
||||
docs_eex: compile ../ex_doc/bin/ex_doc
|
||||
@ echo "==> ex_doc (eex)"
|
||||
$(Q) rm -rf doc/eex
|
||||
$(call COMPILE_DOCS,EEx,eex,EEx)
|
||||
$(call COMPILE_DOCS,EEx,eex,EEx,--config "lib/mix/docs.exs")
|
||||
|
||||
docs_mix: compile ../ex_doc/bin/ex_doc
|
||||
@ echo "==> ex_doc (mix)"
|
||||
$(Q) rm -rf doc/mix
|
||||
$(call COMPILE_DOCS,Mix,mix,Mix)
|
||||
$(call COMPILE_DOCS,Mix,mix,Mix,--config "lib/mix/docs.exs")
|
||||
|
||||
docs_iex: compile ../ex_doc/bin/ex_doc
|
||||
@ echo "==> ex_doc (iex)"
|
||||
$(Q) rm -rf doc/iex
|
||||
$(call COMPILE_DOCS,IEx,iex,IEx)
|
||||
$(call COMPILE_DOCS,IEx,iex,IEx,--config "lib/mix/docs.exs")
|
||||
|
||||
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 COMPILE_DOCS,ExUnit,ex_unit,ExUnit,--config "lib/mix/docs.exs")
|
||||
|
||||
docs_logger: compile ../ex_doc/bin/ex_doc
|
||||
@ echo "==> ex_doc (logger)"
|
||||
$(Q) rm -rf doc/logger
|
||||
$(call COMPILE_DOCS,Logger,logger,Logger)
|
||||
$(call COMPILE_DOCS,Logger,logger,Logger,--config "lib/mix/docs.exs")
|
||||
|
||||
../ex_doc/bin/ex_doc:
|
||||
@ echo "ex_doc is not found in ../ex_doc as expected. See README for more information."
|
||||
|
||||
@@ -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
@@ -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,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)
|
||||
],
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -694,9 +694,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 +702,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 """
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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 = "ed_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 = "ed_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 = "ed_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 = "ed_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 = "ed_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])
|
||||
|
||||
@@ -83,7 +83,7 @@ defmodule Code.Identifier do
|
||||
charlist = Atom.to_charlist(atom)
|
||||
|
||||
cond do
|
||||
atom in [:%, :%{}, :{}, :<<>>, :..., :.., :., :..//, :->] ->
|
||||
atom in [:%, :%{}, :{}, :<<>>, :..., :.., :., :"..//", :->] ->
|
||||
:not_callable
|
||||
|
||||
atom in [:"::", :"//"] ->
|
||||
|
||||
@@ -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)
|
||||
|
||||
+49
-32
@@ -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)
|
||||
@@ -2026,11 +2026,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 +2223,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 +2549,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
|
||||
@@ -3146,11 +3144,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 +3352,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 +3370,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 +3626,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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
+23
-5
@@ -508,6 +508,16 @@ 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)
|
||||
|
||||
"""
|
||||
def stream, do: stream(:stdio, :line)
|
||||
|
||||
@doc """
|
||||
Converts the IO `device` into an `IO.Stream`.
|
||||
|
||||
@@ -533,12 +543,22 @@ 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)
|
||||
|
||||
"""
|
||||
def binstream, do: binstream(:stdio, :line)
|
||||
|
||||
@doc """
|
||||
Converts the IO `device` into an `IO.Stream`. The operation is Unicode unsafe.
|
||||
|
||||
@@ -547,18 +567,16 @@ 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.
|
||||
|
||||
Finally, do not use this function on IO devices in Unicode
|
||||
mode as it will return the wrong result.
|
||||
|
||||
"""
|
||||
@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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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}
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -688,8 +688,6 @@ defmodule Protocol do
|
||||
def: 2,
|
||||
defp: 1,
|
||||
defp: 2,
|
||||
defdelegate: 2,
|
||||
defexception: 1,
|
||||
defguard: 1,
|
||||
defguardp: 1,
|
||||
defmacro: 1,
|
||||
|
||||
+31
-47
@@ -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,6 +180,7 @@ 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
|
||||
@@ -242,7 +226,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 +257,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}
|
||||
|
||||
@@ -309,7 +293,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 ->
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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].
|
||||
|
||||
@@ -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,14 +128,14 @@ 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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -21,6 +21,146 @@ 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, []}
|
||||
|
||||
@@ -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}]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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("") == ""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+2240
-61
File diff suppressed because it is too large
Load Diff
@@ -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>>] ->
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,2 +1,2 @@
|
||||
Logger.configure_backend(:console, colors: [enabled: false])
|
||||
ExUnit.start(trace: "--trace" in System.argv())
|
||||
ExUnit.start()
|
||||
|
||||
+2
-2
@@ -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]
|
||||
|
||||
+156
-236
@@ -20,55 +20,60 @@ defmodule IEx.Autocomplete do
|
||||
Some of the expansion has to be use the current shell
|
||||
environment, which is found via the broker.
|
||||
"""
|
||||
def expand(expr, shell \\ IEx.Broker.shell())
|
||||
def expand(code, shell \\ IEx.Broker.shell()) do
|
||||
code = Enum.reverse(code)
|
||||
helper = get_helper(code)
|
||||
|
||||
def expand('', shell) do
|
||||
expand_variable_or_import("", shell)
|
||||
end
|
||||
case Code.cursor_context(code) do
|
||||
{:alias, alias} ->
|
||||
expand_aliases(List.to_string(alias), shell)
|
||||
|
||||
def expand([h | t] = expr, shell) do
|
||||
helper = get_helper(expr)
|
||||
{:unquoted_atom, unquoted_atom} ->
|
||||
expand_erlang_modules(List.to_string(unquoted_atom))
|
||||
|
||||
cond do
|
||||
helper == ?t ->
|
||||
expand_custom(expr, shell, &get_module_types/1)
|
||||
expansion when helper == ?b ->
|
||||
expand_typespecs(expansion, shell, &get_module_callbacks/1)
|
||||
|
||||
helper == ?b ->
|
||||
expand_custom(expr, shell, &get_module_callbacks/1)
|
||||
expansion when helper == ?t ->
|
||||
expand_typespecs(expansion, shell, &get_module_types/1)
|
||||
|
||||
h == ?. and t != [] ->
|
||||
expand_dot(reduce(t), shell)
|
||||
{:dot, path, hint} ->
|
||||
expand_dot(path, List.to_string(hint), shell)
|
||||
|
||||
h == ?: and t == [] ->
|
||||
expand_erlang_modules()
|
||||
{:dot_arity, path, hint} ->
|
||||
expand_dot(path, List.to_string(hint), shell)
|
||||
|
||||
identifier?(h) ->
|
||||
expand_expr(reduce(expr), shell)
|
||||
{:dot_call, path, hint} ->
|
||||
expand_dot_call(path, List.to_atom(hint), shell)
|
||||
|
||||
h == ?/ and t != [] and identifier?(hd(t)) ->
|
||||
expand_expr(reduce(t), shell)
|
||||
:expr ->
|
||||
expand_local_or_var("", shell)
|
||||
|
||||
h in ' (' and t != [] and identifier?(hd(t)) ->
|
||||
expand_help(reduce(expr), shell)
|
||||
{:local_or_var, local_or_var} ->
|
||||
expand_local_or_var(List.to_string(local_or_var), shell)
|
||||
|
||||
h in '([{' ->
|
||||
expand('')
|
||||
{:local_arity, local} ->
|
||||
expand_local(List.to_string(local), shell)
|
||||
|
||||
true ->
|
||||
{:local_call, local} ->
|
||||
expand_local_call(List.to_atom(local), shell)
|
||||
|
||||
# {:module_attribute, charlist}
|
||||
# :none
|
||||
_ ->
|
||||
no()
|
||||
end
|
||||
end
|
||||
|
||||
defp get_helper(expr) do
|
||||
with [helper | rest] when helper in 'bt' <- Enum.reverse(expr),
|
||||
with [helper | rest] when helper in 'bt' <- expr,
|
||||
[space_or_paren, char | _] <- squeeze_spaces(rest),
|
||||
true <-
|
||||
space_or_paren in ' (' and
|
||||
(char in ?A..?Z or char in ?a..?z or char in ?0..?9 or char in '_:') do
|
||||
helper
|
||||
else
|
||||
_ ->
|
||||
nil
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -84,47 +89,38 @@ defmodule IEx.Autocomplete do
|
||||
end
|
||||
end
|
||||
|
||||
defp identifier?(h) do
|
||||
h in ?a..?z or h in ?A..?Z or h in ?0..?9 or h in [?_, ??, ?!]
|
||||
end
|
||||
## Typespecs
|
||||
|
||||
defp expand_dot(expr, shell) do
|
||||
case Code.string_to_quoted(expr) do
|
||||
{:ok, atom} when is_atom(atom) ->
|
||||
expand_call(atom, "", shell)
|
||||
defp expand_typespecs({:dot, path, hint}, shell, fun) do
|
||||
hint = List.to_string(hint)
|
||||
|
||||
{:ok, {:__aliases__, _, list}} ->
|
||||
expand_elixir_modules(list, "", shell)
|
||||
|
||||
{:ok, {_, _, _} = ast_node} ->
|
||||
expand_call(ast_node, "", shell)
|
||||
case expand_dot_path(path, shell) do
|
||||
{:ok, mod} when is_atom(mod) ->
|
||||
mod
|
||||
|> fun.()
|
||||
|> match_module_funs(hint)
|
||||
|> format_expansion(hint)
|
||||
|
||||
_ ->
|
||||
no()
|
||||
end
|
||||
end
|
||||
|
||||
defp expand_expr(expr, shell) do
|
||||
case Code.string_to_quoted(expr) do
|
||||
{:ok, atom} when is_atom(atom) ->
|
||||
expand_erlang_modules(Atom.to_string(atom))
|
||||
defp expand_typespecs(_, _, _), do: no()
|
||||
|
||||
{:ok, {atom, _, nil}} when is_atom(atom) ->
|
||||
expand_variable_or_import(Atom.to_string(atom), shell)
|
||||
## Expand call
|
||||
|
||||
{:ok, {:__aliases__, _, [root]}} ->
|
||||
expand_elixir_modules([], Atom.to_string(root), shell)
|
||||
defp expand_local_call(fun, shell) do
|
||||
imports_from_env(shell)
|
||||
|> Enum.filter(fn {_, funs} -> List.keymember?(funs, fun, 0) end)
|
||||
|> Enum.flat_map(fn {module, _} -> get_signatures(fun, module) end)
|
||||
|> expand_signatures(shell)
|
||||
end
|
||||
|
||||
{:ok, {:__aliases__, _, [h | _] = list}} when is_atom(h) ->
|
||||
hint = Atom.to_string(List.last(list))
|
||||
list = Enum.take(list, length(list) - 1)
|
||||
expand_elixir_modules(list, hint, shell)
|
||||
|
||||
{:ok, {{:., _, [ast_node, fun]}, _, []}} when is_atom(fun) ->
|
||||
expand_call(ast_node, Atom.to_string(fun), shell)
|
||||
|
||||
_ ->
|
||||
no()
|
||||
defp expand_dot_call(path, fun, shell) do
|
||||
case expand_dot_path(path, shell) do
|
||||
{:ok, mod} when is_atom(mod) -> get_signatures(fun, mod) |> expand_signatures(shell)
|
||||
_ -> no()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -132,165 +128,48 @@ defmodule IEx.Autocomplete do
|
||||
with docs when is_list(docs) <- get_docs(module, [:function, :macro], name) do
|
||||
Enum.map(docs, fn {_, _, signatures, _, _} -> Enum.join(signatures, " ") end)
|
||||
else
|
||||
_ -> []
|
||||
end
|
||||
end
|
||||
|
||||
defp expand_signatures([_ | _] = signatures, _shell) do
|
||||
[head | tail] = Enum.sort(signatures, &(String.length(&1) <= String.length(&2)))
|
||||
if tail != [], do: IO.write("\n" <> (tail |> Enum.reverse() |> Enum.join("\n")))
|
||||
yes("", [head])
|
||||
end
|
||||
|
||||
defp expand_signatures([], shell), do: expand_local_or_var("", shell)
|
||||
|
||||
## Expand dot
|
||||
|
||||
defp expand_dot(path, hint, shell) do
|
||||
case expand_dot_path(path, shell) do
|
||||
{:ok, mod} when is_atom(mod) and hint == "" -> expand_aliases(mod, "", [], true)
|
||||
{:ok, mod} when is_atom(mod) -> expand_require(mod, hint)
|
||||
{:ok, map} when is_map(map) -> expand_map_field_access(map, hint)
|
||||
_ -> no()
|
||||
end
|
||||
end
|
||||
|
||||
defp expand_dot_path({:var, var}, shell) do
|
||||
value_from_binding({List.to_atom(var), [], nil}, shell)
|
||||
end
|
||||
|
||||
defp expand_dot_path({:alias, var}, shell) do
|
||||
var |> List.to_string() |> String.split(".") |> value_from_alias(shell)
|
||||
end
|
||||
|
||||
defp expand_dot_path({:unquoted_atom, var}, _shell) do
|
||||
{:ok, List.to_atom(var)}
|
||||
end
|
||||
|
||||
defp expand_dot_path({:dot, parent, call}, shell) do
|
||||
case expand_dot_path(parent, shell) do
|
||||
{:ok, %{} = map} -> Map.fetch(map, List.to_atom(call))
|
||||
_ -> :error
|
||||
end
|
||||
end
|
||||
|
||||
defp expand_help(expr, shell) do
|
||||
signatures =
|
||||
case Code.string_to_quoted(expr) do
|
||||
{:ok, {{:., _, [{:__aliases__, _, mod}, fun]}, _, []}} when is_atom(fun) ->
|
||||
with {:ok, mod} <- expand_alias(mod, shell) do
|
||||
get_signatures(fun, mod)
|
||||
end
|
||||
|
||||
{:ok, {fun, _, _}} when is_atom(fun) ->
|
||||
imports_from_env(shell)
|
||||
|> Enum.filter(fn {_, funs} -> List.keymember?(funs, fun, 0) end)
|
||||
|> Enum.flat_map(fn {module, _} -> get_signatures(fun, module) end)
|
||||
|
||||
{:ok, {{:., _, [mod, fun]}, _, []}} when is_atom(mod) and is_atom(fun) ->
|
||||
get_signatures(fun, mod)
|
||||
|
||||
_ ->
|
||||
:error
|
||||
end
|
||||
|
||||
case signatures do
|
||||
[_ | _] ->
|
||||
[head | tail] = Enum.sort(signatures, &(String.length(&1) <= String.length(&2)))
|
||||
if tail != [], do: IO.write("\n" <> (tail |> Enum.reverse() |> Enum.join("\n")))
|
||||
yes("", [head])
|
||||
|
||||
_ ->
|
||||
expand('')
|
||||
end
|
||||
end
|
||||
|
||||
defp expand_custom([?. | expr], shell, fun) do
|
||||
case Code.string_to_quoted(reduce(expr)) do
|
||||
{:ok, atom} when is_atom(atom) ->
|
||||
expand_elixir_module_custom(atom, "", fun)
|
||||
|
||||
{:ok, {:__aliases__, _, [h | _] = list}} when is_atom(h) ->
|
||||
case expand_alias(list, shell) do
|
||||
{:ok, alias} ->
|
||||
expand_elixir_module_custom(alias, "", fun)
|
||||
|
||||
:error ->
|
||||
no()
|
||||
end
|
||||
|
||||
_ ->
|
||||
no()
|
||||
end
|
||||
end
|
||||
|
||||
defp expand_custom(expr, shell, fun) do
|
||||
case Code.string_to_quoted(reduce(expr)) do
|
||||
{:ok, atom} when is_atom(atom) ->
|
||||
expand_erlang_modules(Atom.to_string(atom))
|
||||
|
||||
{:ok, {:__aliases__, _, [root]}} ->
|
||||
expand_elixir_modules([], Atom.to_string(root), shell)
|
||||
|
||||
{:ok, {:__aliases__, _, [h | _] = list}} when is_atom(h) ->
|
||||
hint = Atom.to_string(List.last(list))
|
||||
list = Enum.take(list, length(list) - 1)
|
||||
expand_elixir_modules(list, hint, shell)
|
||||
|
||||
{:ok, {{:., _, [{:__aliases__, _, list}, type]}, _, []}} when is_atom(type) ->
|
||||
case expand_alias(list, shell) do
|
||||
{:ok, alias} ->
|
||||
expand_elixir_module_custom(alias, Atom.to_string(type), fun)
|
||||
|
||||
:error ->
|
||||
no()
|
||||
end
|
||||
|
||||
{:ok, {{:., _, [module, type]}, _, []}} when is_atom(type) ->
|
||||
expand_elixir_module_custom(module, Atom.to_string(type), fun)
|
||||
|
||||
_ ->
|
||||
no()
|
||||
end
|
||||
end
|
||||
|
||||
defp reduce(expr) do
|
||||
Enum.reduce(' ([{', expr, fn token, acc ->
|
||||
hd(:string.tokens(acc, [token]))
|
||||
end)
|
||||
|> Enum.reverse()
|
||||
|> trim_leading(?&)
|
||||
|> trim_leading(?%)
|
||||
|> trim_leading(?!)
|
||||
|> trim_leading(?^)
|
||||
end
|
||||
|
||||
defp trim_leading([char | rest], char), do: rest
|
||||
defp trim_leading(expr, _char), do: expr
|
||||
|
||||
defp yes(hint, entries) do
|
||||
{:yes, String.to_charlist(hint), Enum.map(entries, &String.to_charlist/1)}
|
||||
end
|
||||
|
||||
defp no do
|
||||
{:no, '', []}
|
||||
end
|
||||
|
||||
## Formatting
|
||||
|
||||
defp format_expansion([], _) do
|
||||
no()
|
||||
end
|
||||
|
||||
defp format_expansion([uniq], hint) do
|
||||
case to_hint(uniq, hint) do
|
||||
"" -> yes("", to_uniq_entries(uniq))
|
||||
hint -> yes(hint, [])
|
||||
end
|
||||
end
|
||||
|
||||
defp format_expansion([first | _] = entries, hint) do
|
||||
binary = Enum.map(entries, & &1.name)
|
||||
length = byte_size(hint)
|
||||
prefix = :binary.longest_common_prefix(binary)
|
||||
|
||||
if prefix in [0, length] do
|
||||
yes("", Enum.flat_map(entries, &to_entries/1))
|
||||
else
|
||||
yes(binary_part(first.name, prefix, length - prefix), [])
|
||||
end
|
||||
end
|
||||
|
||||
## Expand calls
|
||||
|
||||
# :atom.fun
|
||||
defp expand_call(mod, hint, _shell) when is_atom(mod) do
|
||||
expand_require(mod, hint)
|
||||
end
|
||||
|
||||
# Elixir.fun
|
||||
defp expand_call({:__aliases__, _, list}, hint, shell) do
|
||||
case expand_alias(list, shell) do
|
||||
{:ok, alias} -> expand_require(alias, hint)
|
||||
:error -> no()
|
||||
end
|
||||
end
|
||||
|
||||
# variable.fun_or_key
|
||||
defp expand_call({_, _, _} = ast_node, hint, shell) do
|
||||
case value_from_binding(ast_node, shell) do
|
||||
{:ok, mod} when is_atom(mod) -> expand_call(mod, hint, shell)
|
||||
{:ok, map} when is_map(map) -> expand_map_field_access(map, hint)
|
||||
_otherwise -> no()
|
||||
end
|
||||
end
|
||||
|
||||
defp expand_call(_, _, _) do
|
||||
no()
|
||||
end
|
||||
|
||||
defp expand_map_field_access(map, hint) do
|
||||
case match_map_fields(map, hint) do
|
||||
[%{kind: :map_key, name: ^hint, value_is_map: false}] -> no()
|
||||
@@ -302,15 +181,23 @@ defmodule IEx.Autocomplete do
|
||||
format_expansion(match_module_funs(get_module_funs(mod), hint), hint)
|
||||
end
|
||||
|
||||
defp expand_variable_or_import(hint, shell) do
|
||||
variables = expand_variable(hint, shell)
|
||||
imports = imports_from_env(shell) |> Enum.flat_map(&elem(&1, 1))
|
||||
module_funs = get_module_funs(Kernel.SpecialForms)
|
||||
funs = match_module_funs(imports ++ module_funs, hint)
|
||||
format_expansion(variables ++ funs, hint)
|
||||
## Expand local or var
|
||||
|
||||
defp expand_local_or_var(hint, shell) do
|
||||
format_expansion(match_var(hint, shell) ++ match_local(hint, shell), hint)
|
||||
end
|
||||
|
||||
defp expand_variable(hint, shell) do
|
||||
defp expand_local(hint, shell) do
|
||||
format_expansion(match_local(hint, shell), hint)
|
||||
end
|
||||
|
||||
defp match_local(hint, shell) do
|
||||
imports = imports_from_env(shell) |> Enum.flat_map(&elem(&1, 1))
|
||||
module_funs = get_module_funs(Kernel.SpecialForms)
|
||||
match_module_funs(imports ++ module_funs, hint)
|
||||
end
|
||||
|
||||
defp match_var(hint, shell) do
|
||||
variables_from_binding(hint, shell)
|
||||
|> Enum.sort()
|
||||
|> Enum.map(&%{kind: :variable, name: &1})
|
||||
@@ -318,7 +205,7 @@ defmodule IEx.Autocomplete do
|
||||
|
||||
## Erlang modules
|
||||
|
||||
defp expand_erlang_modules(hint \\ "") do
|
||||
defp expand_erlang_modules(hint) do
|
||||
format_expansion(match_erlang_modules(hint), hint)
|
||||
end
|
||||
|
||||
@@ -330,26 +217,33 @@ defmodule IEx.Autocomplete do
|
||||
|
||||
## Elixir modules
|
||||
|
||||
defp expand_elixir_modules([], hint, shell) do
|
||||
aliases = match_aliases(hint, shell)
|
||||
expand_elixir_modules_from_aliases(Elixir, hint, aliases)
|
||||
end
|
||||
defp expand_aliases(all, shell) do
|
||||
case String.split(all, ".") do
|
||||
[hint] ->
|
||||
aliases = match_aliases(hint, shell)
|
||||
expand_aliases(Elixir, hint, aliases, false)
|
||||
|
||||
defp expand_elixir_modules(list, hint, shell) do
|
||||
case expand_alias(list, shell) do
|
||||
{:ok, alias} -> expand_elixir_modules_from_aliases(alias, hint, [])
|
||||
:error -> no()
|
||||
parts ->
|
||||
hint = List.last(parts)
|
||||
list = Enum.take(parts, length(parts) - 1)
|
||||
|
||||
case value_from_alias(list, shell) do
|
||||
{:ok, alias} -> expand_aliases(alias, hint, [], false)
|
||||
:error -> no()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp expand_elixir_modules_from_aliases(mod, hint, aliases) do
|
||||
defp expand_aliases(mod, hint, aliases, include_funs?) do
|
||||
aliases
|
||||
|> Kernel.++(match_elixir_modules(mod, hint))
|
||||
|> Kernel.++(match_module_funs(get_module_funs(mod), hint))
|
||||
|> Kernel.++(if include_funs?, do: match_module_funs(get_module_funs(mod), hint), else: [])
|
||||
|> format_expansion(hint)
|
||||
end
|
||||
|
||||
defp expand_alias([name | rest], shell) when is_atom(name) do
|
||||
defp value_from_alias([name | rest], shell) when is_binary(name) do
|
||||
name = String.to_atom(name)
|
||||
|
||||
case Keyword.fetch(aliases_from_env(shell), Module.concat(Elixir, name)) do
|
||||
{:ok, name} when rest == [] -> {:ok, name}
|
||||
{:ok, name} -> {:ok, Module.concat([name | rest])}
|
||||
@@ -357,7 +251,7 @@ defmodule IEx.Autocomplete do
|
||||
end
|
||||
end
|
||||
|
||||
defp expand_alias([_ | _], _) do
|
||||
defp value_from_alias([_ | _], _) do
|
||||
:error
|
||||
end
|
||||
|
||||
@@ -398,11 +292,37 @@ defmodule IEx.Autocomplete do
|
||||
defp valid_alias_rest?(<<>>), do: true
|
||||
defp valid_alias_rest?(rest), do: valid_alias_piece?(rest)
|
||||
|
||||
## Elixir Types
|
||||
## Formatting
|
||||
|
||||
defp expand_elixir_module_custom(mod, hint, fun) do
|
||||
types = match_module_funs(fun.(mod), hint)
|
||||
format_expansion(types, hint)
|
||||
defp format_expansion([], _) do
|
||||
no()
|
||||
end
|
||||
|
||||
defp format_expansion([uniq], hint) do
|
||||
case to_hint(uniq, hint) do
|
||||
"" -> yes("", to_uniq_entries(uniq))
|
||||
hint -> yes(hint, [])
|
||||
end
|
||||
end
|
||||
|
||||
defp format_expansion([first | _] = entries, hint) do
|
||||
binary = Enum.map(entries, & &1.name)
|
||||
length = byte_size(hint)
|
||||
prefix = :binary.longest_common_prefix(binary)
|
||||
|
||||
if prefix in [0, length] do
|
||||
yes("", Enum.flat_map(entries, &to_entries/1))
|
||||
else
|
||||
yes(binary_part(first.name, prefix, length - prefix), [])
|
||||
end
|
||||
end
|
||||
|
||||
defp yes(hint, entries) do
|
||||
{:yes, String.to_charlist(hint), Enum.map(entries, &String.to_charlist/1)}
|
||||
end
|
||||
|
||||
defp no do
|
||||
{:no, '', []}
|
||||
end
|
||||
|
||||
## Helpers
|
||||
|
||||
@@ -616,7 +616,7 @@ defmodule IEx.Helpers do
|
||||
IO.puts("#{pad_key(key)}#{min} / #{max} (#{percentage}% used)")
|
||||
end
|
||||
|
||||
defp get_stat(:ets_count), do: length(:ets.all())
|
||||
defp get_stat(:ets_count), do: :erlang.system_info(:ets_count)
|
||||
defp get_stat(other), do: :erlang.system_info(other)
|
||||
|
||||
defp print_memory(key, memory) do
|
||||
|
||||
@@ -28,7 +28,6 @@ defmodule IEx.AutocompleteTest do
|
||||
|
||||
test "Erlang module no completion" do
|
||||
assert expand(':unknown') == {:no, '', []}
|
||||
assert expand('Enum:') == {:no, '', []}
|
||||
end
|
||||
|
||||
test "Erlang module multiple values completion" do
|
||||
@@ -385,14 +384,6 @@ defmodule IEx.AutocompleteTest do
|
||||
:code.delete(:"Elixir.IEx.AutocompleteTest.Unicodé")
|
||||
end
|
||||
|
||||
test "no signature help" do
|
||||
default_expand = expand('[')
|
||||
|
||||
assert expand('(') == default_expand
|
||||
assert expand('x(') == default_expand
|
||||
assert expand('Foo.x(') == default_expand
|
||||
end
|
||||
|
||||
test "signature help for functions and macros" do
|
||||
assert expand('String.graphemes(') == {:yes, '', ['graphemes(string)']}
|
||||
assert expand('def ') == {:yes, '', ['def(call, expr \\\\ nil)']}
|
||||
@@ -407,5 +398,11 @@ defmodule IEx.AutocompleteTest do
|
||||
|
||||
assert expand('take(') == {:yes, '', ['take(enumerable, amount)']}
|
||||
assert expand('derive(') == {:yes, '', ['derive(protocol, module, options \\\\ [])']}
|
||||
|
||||
defmodule NoDocs do
|
||||
def sample(a), do: a
|
||||
end
|
||||
|
||||
assert {:yes, [], [_ | _]} = expand('NoDocs.sample(')
|
||||
end
|
||||
end
|
||||
|
||||
+15
-26
@@ -289,31 +289,24 @@ defmodule Logger do
|
||||
|
||||
The initial backends are loaded via the `:backends` configuration,
|
||||
which must be set before the `:logger` application is started.
|
||||
Backends can also be added dynamically through `add_backend/2`.
|
||||
However, it preferred to add and remove backends via `add_backend/2`
|
||||
and `remove_backend/2` functions. This is often done in your
|
||||
`c:Application.start/2` callback:
|
||||
|
||||
For example, to add multiple backends to your application, modify your
|
||||
configuration:
|
||||
@impl true
|
||||
def start(_type, _args) do
|
||||
Logger.add_backend(MyCustomBackend)
|
||||
|
||||
config :logger,
|
||||
backends: [:console, MyCustomBackend]
|
||||
The backend can be configured either on the `add_backend/2` call:
|
||||
|
||||
Multiple instances of the same backend can be specified by adding tuples
|
||||
in the format `{BackendModuleName, :backend_name}`:
|
||||
@impl true
|
||||
def start(_type, _args) do
|
||||
Logger.add_backend(MyCustomBackend, some_config: ...)
|
||||
|
||||
config :logger,
|
||||
backends: [
|
||||
:console,
|
||||
{MyCustomBackend, :error_backend},
|
||||
{MyCustomBackend, :debug_backend}
|
||||
]
|
||||
Or in your config files:
|
||||
|
||||
config :logger, :error_backend,
|
||||
level: :error
|
||||
# other options
|
||||
|
||||
config :logger, :debug_backend,
|
||||
level: :debug
|
||||
# other options
|
||||
config :logger, MyCustomBackend,
|
||||
some_config: ...
|
||||
|
||||
### Elixir custom backends
|
||||
|
||||
@@ -413,12 +406,8 @@ defmodule Logger do
|
||||
responsibility to implement it
|
||||
|
||||
The good news is that developers can use third-party implementations of
|
||||
both Elixir backends and Erlang handlers.
|
||||
|
||||
Elixir backends can be configured directly under the `:logger` application
|
||||
in your `config/config.exs`:
|
||||
|
||||
config :logger, backends: [ACustomBackend]
|
||||
both Elixir backends and Erlang handlers. We have already covered Elixir
|
||||
backends, so let's see how to add Erlang/OTP handlers.
|
||||
|
||||
Erlang/OTP handlers must be listed under your own application:
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ defmodule Logger.App do
|
||||
def start(_type, _args) do
|
||||
start_options = Application.get_env(:logger, :start_options)
|
||||
otp_reports? = Application.fetch_env!(:logger, :handle_otp_reports)
|
||||
config = Logger.Counter.new()
|
||||
counter = :counters.new(1, [:atomics])
|
||||
|
||||
children = [
|
||||
%{
|
||||
@@ -17,13 +17,13 @@ defmodule Logger.App do
|
||||
start: {:gen_event, :start_link, [{:local, Logger}, start_options]},
|
||||
modules: :dynamic
|
||||
},
|
||||
{Logger.Watcher, {Logger.Config, config}},
|
||||
{Logger.Watcher, {Logger.Config, counter}},
|
||||
Logger.BackendSupervisor
|
||||
]
|
||||
|
||||
case Supervisor.start_link(children, strategy: :rest_for_one, name: Logger.Supervisor) do
|
||||
{:ok, sup} ->
|
||||
primary_config = add_elixir_handler(otp_reports?, config)
|
||||
primary_config = add_elixir_handler(otp_reports?, counter)
|
||||
|
||||
default_handlers =
|
||||
if otp_reports? do
|
||||
@@ -33,10 +33,9 @@ defmodule Logger.App do
|
||||
end
|
||||
|
||||
handlers = [{:primary, primary_config} | default_handlers]
|
||||
{:ok, sup, {config, handlers}}
|
||||
{:ok, sup, handlers}
|
||||
|
||||
{:error, _} = error ->
|
||||
Logger.Counter.delete(config)
|
||||
error
|
||||
end
|
||||
end
|
||||
@@ -47,12 +46,10 @@ defmodule Logger.App do
|
||||
end
|
||||
|
||||
@doc false
|
||||
def stop({config, handlers}) do
|
||||
def stop(handlers) do
|
||||
_ = :logger.remove_handler(Logger)
|
||||
_ = :logger.remove_primary_filter(:process_disabled)
|
||||
|
||||
add_handlers(handlers)
|
||||
Logger.Counter.delete(config)
|
||||
|
||||
:logger.add_primary_filter(
|
||||
:silence_logger_exit,
|
||||
|
||||
@@ -5,8 +5,6 @@ defmodule Logger.Config do
|
||||
@name __MODULE__
|
||||
@update_counter_message {__MODULE__, :update_counter}
|
||||
|
||||
alias Logger.Counter
|
||||
|
||||
def configure(options) do
|
||||
:gen_event.call(Logger, @name, {:configure, options})
|
||||
end
|
||||
@@ -76,6 +74,8 @@ defmodule Logger.Config do
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
@counter_pos 1
|
||||
|
||||
defp update_counter({counter, log, discard_threshold, discard_period}, periodic_check?) do
|
||||
# If length is more than the total, it means the counter is behind,
|
||||
# due to non-log messages, so we need to increase the counter.
|
||||
@@ -88,9 +88,9 @@ defmodule Logger.Config do
|
||||
# deliver the message yet. Those bumps will be lost. At the same time,
|
||||
# we are careful to read the counter first here, so if the counter is
|
||||
# bumped after we read from it, those bumps won't be lost.
|
||||
total = Counter.read(counter)
|
||||
total = :counters.get(counter, @counter_pos)
|
||||
{:message_queue_len, length} = Process.info(self(), :message_queue_len)
|
||||
Counter.add(counter, length - total)
|
||||
:counters.add(counter, @counter_pos, length - total)
|
||||
|
||||
# In case we are logging but we reached the threshold, we log that we
|
||||
# started discarding messages. This can only be reverted by the periodic
|
||||
@@ -128,7 +128,6 @@ defmodule Logger.Config do
|
||||
{:ok, %{config: data}} = :logger.get_handler_config(Logger)
|
||||
translators = fun.(data.translators)
|
||||
Application.put_env(:logger, :translators, translators)
|
||||
# TODO: Use update_handler_config on Erlang/OTP 22+.
|
||||
:ok = :logger.set_handler_config(Logger, :config, %{data | translators: translators})
|
||||
:ok = :logger.update_handler_config(Logger, :config, translators: translators)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
defmodule Logger.Counter do
|
||||
@moduledoc false
|
||||
|
||||
@table __MODULE__
|
||||
@pos 1
|
||||
|
||||
# TODO Remove this once we support Erlang/OTP 22+ exclusively.
|
||||
@compile {:no_warn_undefined, [:counters]}
|
||||
|
||||
@type type() :: :ets | :counters
|
||||
@type t() :: {type(), :ets.tid() | :counters.counters_ref()}
|
||||
|
||||
@spec new() :: t()
|
||||
def new do
|
||||
if Code.ensure_loaded?(:counters) do
|
||||
{:counters, :counters.new(1, [:atomics])}
|
||||
else
|
||||
table = :ets.new(@table, [:public])
|
||||
:ets.insert(table, [{@pos, 0}])
|
||||
{:ets, table}
|
||||
end
|
||||
end
|
||||
|
||||
@spec delete(t()) :: :ok
|
||||
def delete({:ets, counter}), do: :ets.delete(counter)
|
||||
def delete({:counters, _}), do: :ok
|
||||
|
||||
@spec read(t()) :: integer()
|
||||
def read({:ets, counter}), do: :ets.lookup_element(counter, @pos, 2)
|
||||
def read({:counters, counter}), do: :counters.get(counter, @pos)
|
||||
|
||||
@spec add(t(), integer()) :: :ok
|
||||
def add({:ets, counter}, value), do: :ets.update_counter(counter, @pos, {2, value})
|
||||
def add({:counters, counter}, value), do: :counters.add(counter, @pos, value)
|
||||
|
||||
@spec bump(t()) :: integer()
|
||||
def bump({:ets, counter}),
|
||||
do: :ets.update_counter(counter, @pos, {2, 1})
|
||||
|
||||
def bump({:counters, counter}) do
|
||||
:counters.add(counter, @pos, 1)
|
||||
:counters.get(counter, @pos)
|
||||
end
|
||||
end
|
||||
@@ -1,6 +1,5 @@
|
||||
defmodule Logger.Handler do
|
||||
@moduledoc false
|
||||
alias Logger.Counter
|
||||
|
||||
@internal_keys [:counter]
|
||||
|
||||
@@ -28,9 +27,6 @@ defmodule Logger.Handler do
|
||||
{:ok, update_in(config.config, &Map.merge(default_config(), &1))}
|
||||
end
|
||||
|
||||
# TODO: Remove this once we support Erlang/OTP 22+ exclusively.
|
||||
def changing_config(current, new), do: changing_config(:set, current, new)
|
||||
|
||||
def changing_config(
|
||||
op,
|
||||
%{config: %{counter: counter} = old_data} = old_config,
|
||||
@@ -169,13 +165,16 @@ defmodule Logger.Handler do
|
||||
defp truncate(data, n) when is_binary(data), do: Logger.Utils.truncate(data, n)
|
||||
defp truncate(data, n), do: Logger.Utils.truncate(to_string(data), n)
|
||||
|
||||
@counter_pos 1
|
||||
|
||||
defp threshold(config) do
|
||||
%{
|
||||
counter: counter,
|
||||
thresholds: {sync, discard}
|
||||
} = config
|
||||
|
||||
value = Counter.bump(counter)
|
||||
:counters.add(counter, @counter_pos, 1)
|
||||
value = :counters.get(counter, @counter_pos)
|
||||
|
||||
cond do
|
||||
value >= discard -> :discard
|
||||
|
||||
@@ -34,8 +34,6 @@ defmodule Logger.Translator do
|
||||
"""
|
||||
def translate(min_level, level, kind, message)
|
||||
|
||||
## Erlang/OTP 21 and after
|
||||
|
||||
def translate(min_level, _level, :report, {:logger, %{label: label} = report}) do
|
||||
case label do
|
||||
{:gen_server, :terminate} ->
|
||||
@@ -357,15 +355,22 @@ defmodule Logger.Translator do
|
||||
[]
|
||||
end
|
||||
|
||||
defp child_debug(:debug, restart_type: restart, shutdown: shutdown, child_type: type) do
|
||||
["\nRestart: ", inspect(restart), "\nShutdown: ", inspect(shutdown)] ++
|
||||
["\nType: ", inspect(type)]
|
||||
defp child_debug(:debug, opts) do
|
||||
for {key, value} <- opts do
|
||||
child_debug_key(key, value)
|
||||
end
|
||||
end
|
||||
|
||||
defp child_debug(_min_level, _child) do
|
||||
[]
|
||||
end
|
||||
|
||||
defp child_debug_key(:restart_type, value), do: ["\nRestart: " | inspect(value)]
|
||||
defp child_debug_key(:shutdown, value), do: ["\nShutdown: " | inspect(value)]
|
||||
defp child_debug_key(:child_type, value), do: ["\nType: " | inspect(value)]
|
||||
defp child_debug_key(:significant, value), do: if(value, do: "\nSignificant: true", else: [])
|
||||
defp child_debug_key(_, _), do: []
|
||||
|
||||
defp report_crash(min_level, [[{:initial_call, initial_call} | crashed], linked]) do
|
||||
mfa = initial_call_to_mfa(initial_call)
|
||||
report_crash(min_level, crashed, [{:initial_call, mfa}], linked)
|
||||
|
||||
@@ -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}"
|
||||
]
|
||||
]
|
||||
+57
-25
@@ -480,8 +480,8 @@ defmodule Mix do
|
||||
will avoid unnecessary downloads and compilations. The location of the cache
|
||||
directory can be controlled using the `MIX_INSTALL_DIR` environment variable.
|
||||
|
||||
This function can only be called outside of a Mix project and only once in a
|
||||
given VM.
|
||||
This function can only be called outside of a Mix project and only with the
|
||||
same dependencies in the given VM.
|
||||
|
||||
**Note:** this feature is currently experimental and it may change
|
||||
in future releases.
|
||||
@@ -516,8 +516,32 @@ defmodule Mix do
|
||||
Mix.raise("Mix.install/2 cannot be used inside a Mix project")
|
||||
end
|
||||
|
||||
if Mix.State.get(:install_called?) do
|
||||
Mix.raise("Mix.install/2 can only be called once")
|
||||
deps =
|
||||
Enum.map(deps, fn
|
||||
dep when is_atom(dep) ->
|
||||
{dep, ">= 0.0.0"}
|
||||
|
||||
{app, opts} when is_atom(app) and is_list(opts) ->
|
||||
{app, maybe_expand_path_dep(opts)}
|
||||
|
||||
{app, requirement, opts} when is_atom(app) and is_binary(requirement) and is_list(opts) ->
|
||||
{app, requirement, maybe_expand_path_dep(opts)}
|
||||
|
||||
other ->
|
||||
other
|
||||
end)
|
||||
|
||||
force? = !!opts[:force]
|
||||
|
||||
case Mix.State.get(:installed) do
|
||||
nil ->
|
||||
:ok
|
||||
|
||||
^deps when not force? ->
|
||||
:ok
|
||||
|
||||
_ ->
|
||||
Mix.raise("Mix.install/2 can only be called with the same dependencies in the given VM")
|
||||
end
|
||||
|
||||
installs_root =
|
||||
@@ -532,16 +556,10 @@ defmodule Mix do
|
||||
Mix.shell().info("using #{dir}")
|
||||
end
|
||||
|
||||
if opts[:force] do
|
||||
if force? do
|
||||
File.rm_rf!(dir)
|
||||
end
|
||||
|
||||
deps =
|
||||
Enum.map(deps, fn
|
||||
dep when is_atom(dep) -> {dep, ">= 0.0.0"}
|
||||
dep -> dep
|
||||
end)
|
||||
|
||||
config = [
|
||||
version: "0.1.0",
|
||||
build_per_environment: true,
|
||||
@@ -552,29 +570,43 @@ defmodule Mix do
|
||||
app: :mix_install,
|
||||
erlc_paths: ["src"],
|
||||
elixirc_paths: ["lib"],
|
||||
compilers: [],
|
||||
consolidate_protocols: Keyword.get(opts, :consolidate_protocols, true)
|
||||
]
|
||||
|
||||
:ok = Mix.ProjectStack.push(__MODULE__.InstallProject, config, "nofile")
|
||||
:ok = Mix.Local.append_archives()
|
||||
:ok = Mix.ProjectStack.push(__MODULE__.InstallProject, config, "nofile")
|
||||
build_dir = Path.join(dir, "_build")
|
||||
|
||||
dir? = File.dir?(dir)
|
||||
File.mkdir_p!(dir)
|
||||
try do
|
||||
run_deps? = not File.dir?(build_dir)
|
||||
File.mkdir_p!(dir)
|
||||
|
||||
File.cd!(dir, fn ->
|
||||
unless dir? do
|
||||
Mix.Task.run("deps.get")
|
||||
File.cd!(dir, fn ->
|
||||
if run_deps? do
|
||||
Mix.Task.rerun("deps.get")
|
||||
end
|
||||
|
||||
Mix.Task.rerun("deps.loadpaths")
|
||||
Mix.Task.rerun("compile")
|
||||
end)
|
||||
|
||||
for app <- Mix.Project.deps_apps() do
|
||||
Application.ensure_all_started(app)
|
||||
end
|
||||
|
||||
Mix.Task.run("compile")
|
||||
end)
|
||||
|
||||
for app <- Mix.Project.deps_apps() do
|
||||
Application.ensure_all_started(app)
|
||||
Mix.State.put(:installed, deps)
|
||||
:ok
|
||||
after
|
||||
Mix.ProjectStack.pop()
|
||||
end
|
||||
end
|
||||
|
||||
Mix.ProjectStack.pop()
|
||||
Mix.State.put(:install_called?, true)
|
||||
:ok
|
||||
defp maybe_expand_path_dep(opts) do
|
||||
if Keyword.has_key?(opts, :path) do
|
||||
Keyword.update!(opts, :path, &Path.expand/1)
|
||||
else
|
||||
opts
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,7 +11,8 @@ defmodule Mix.Compilers.Test do
|
||||
runtime_references: [],
|
||||
external: []
|
||||
|
||||
@compile {:no_warn_undefined, ExUnit.Server}
|
||||
# Necessary to avoid warnings during bootstrap
|
||||
@compile {:no_warn_undefined, ExUnit}
|
||||
@stale_manifest "compile.test_stale"
|
||||
@manifest_vsn 1
|
||||
|
||||
@@ -34,7 +35,7 @@ defmodule Mix.Compilers.Test do
|
||||
if test_files == [] do
|
||||
:noop
|
||||
else
|
||||
task = Task.async(ExUnit, :run, [])
|
||||
task = ExUnit.async_run()
|
||||
|
||||
try do
|
||||
case Kernel.ParallelCompiler.require(test_files, parallel_require_callbacks) do
|
||||
@@ -42,8 +43,7 @@ defmodule Mix.Compilers.Test do
|
||||
{:error, _, _} -> exit({:shutdown, 1})
|
||||
end
|
||||
|
||||
ExUnit.Server.modules_loaded()
|
||||
%{failures: failures} = results = Task.await(task, :infinity)
|
||||
%{failures: failures} = results = ExUnit.await_run(task)
|
||||
|
||||
if failures == 0 do
|
||||
agent_write_manifest(stale_manifest_pid)
|
||||
|
||||
@@ -418,13 +418,41 @@ defmodule Mix.Release do
|
||||
:ok
|
||||
|
||||
{:error, reason} ->
|
||||
{:error,
|
||||
"Could not read configuration file. It likely has invalid configuration terms " <>
|
||||
"such as functions, references, and pids. Please make sure your configuration " <>
|
||||
"is made of numbers, atoms, strings, maps, tuples and lists. Reason: #{inspect(reason)}"}
|
||||
invalid =
|
||||
for {app, kv} <- sys_config,
|
||||
{key, value} <- kv,
|
||||
not valid_config?(value),
|
||||
do: """
|
||||
|
||||
Application: #{inspect(app)}
|
||||
Key: #{inspect(key)}
|
||||
Value: #{inspect(value)}
|
||||
"""
|
||||
|
||||
message =
|
||||
case invalid do
|
||||
[] ->
|
||||
"Could not read configuration file. Reason: #{inspect(reason)}"
|
||||
|
||||
_ ->
|
||||
"Could not read configuration file. It has invalid configuration terms " <>
|
||||
"such as functions, references, and pids. Please make sure your configuration " <>
|
||||
"is made of numbers, atoms, strings, maps, tuples and lists. The following entries " <>
|
||||
"are wrong:\n#{Enum.join(invalid)}"
|
||||
end
|
||||
|
||||
{:error, message}
|
||||
end
|
||||
end
|
||||
|
||||
defp valid_config?(n) when is_number(n), do: true
|
||||
defp valid_config?(a) when is_atom(a), do: true
|
||||
defp valid_config?(b) when is_binary(b), do: true
|
||||
defp valid_config?(l) when is_list(l), do: Enum.all?(l, &valid_config?/1)
|
||||
defp valid_config?(m) when is_map(m), do: Enum.all?(m, &valid_config?/1)
|
||||
defp valid_config?(t) when is_tuple(t), do: Enum.all?(Tuple.to_list(t), &valid_config?/1)
|
||||
defp valid_config?(_), do: false
|
||||
|
||||
defp merge_provider_config(%{config_providers: []}, sys_config, _), do: {sys_config, false}
|
||||
|
||||
defp merge_provider_config(release, sys_config, config_path) do
|
||||
|
||||
@@ -270,14 +270,17 @@ defmodule Mix.SCM.Git do
|
||||
{response, 0} ->
|
||||
response
|
||||
|
||||
{response, _} ->
|
||||
{response, _} when is_binary(response) ->
|
||||
Mix.raise("Command \"git #{Enum.join(args, " ")}\" failed with reason: #{response}")
|
||||
|
||||
{_, _} ->
|
||||
Mix.raise("Command \"git #{Enum.join(args, " ")}\" failed")
|
||||
end
|
||||
end
|
||||
|
||||
defp default_into() do
|
||||
case Mix.shell() do
|
||||
Mix.Shell.IO -> IO.stream(:stdio, :line)
|
||||
Mix.Shell.IO -> IO.stream()
|
||||
_ -> ""
|
||||
end
|
||||
end
|
||||
|
||||
+18
-59
@@ -3,6 +3,9 @@ defmodule Mix.Shell do
|
||||
Defines `Mix.Shell` contract.
|
||||
"""
|
||||
|
||||
@doc false
|
||||
defstruct [:callback]
|
||||
|
||||
@doc """
|
||||
Prints the given ANSI message to the shell.
|
||||
"""
|
||||
@@ -87,73 +90,29 @@ defmodule Mix.Shell do
|
||||
"""
|
||||
def cmd(command, options \\ [], callback) when is_function(callback, 1) do
|
||||
callback =
|
||||
if Keyword.get(options, :quiet, false) do
|
||||
if options[:quiet] do
|
||||
fn x -> x end
|
||||
else
|
||||
callback
|
||||
end
|
||||
|
||||
env = validate_env(Keyword.get(options, :env, []))
|
||||
options =
|
||||
options
|
||||
|> Keyword.take([:cd, :stderr_to_stdout, :env])
|
||||
|> Keyword.put(:into, %Mix.Shell{callback: callback})
|
||||
|> Keyword.put_new(:stderr_to_stdout, true)
|
||||
|
||||
args =
|
||||
if Keyword.get(options, :stderr_to_stdout, true) do
|
||||
[:stderr_to_stdout]
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
opts =
|
||||
[:stream, :binary, :exit_status, :hide, :use_stdio, {:env, env}] ++
|
||||
args ++ Keyword.take(options, [:cd])
|
||||
|
||||
port = Port.open({:spawn, shell_command(command)}, opts)
|
||||
port_read(port, callback)
|
||||
{_, status} = System.shell(command, options)
|
||||
status
|
||||
end
|
||||
|
||||
defp port_read(port, callback) do
|
||||
receive do
|
||||
{^port, {:data, data}} ->
|
||||
_ = callback.(data)
|
||||
port_read(port, callback)
|
||||
|
||||
{^port, {:exit_status, status}} ->
|
||||
status
|
||||
defimpl Collectable do
|
||||
def into(%Mix.Shell{callback: fun}) do
|
||||
{:ok,
|
||||
fn
|
||||
_, {:cont, data} -> fun.(data)
|
||||
_, _ -> :ok
|
||||
end}
|
||||
end
|
||||
end
|
||||
|
||||
# Finding shell command logic from :os.cmd in OTP
|
||||
# https://github.com/erlang/otp/blob/8deb96fb1d017307e22d2ab88968b9ef9f1b71d0/lib/kernel/src/os.erl#L184
|
||||
defp shell_command(command) do
|
||||
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
|
||||
end
|
||||
|
||||
defp validate_env(enum) do
|
||||
Enum.map(enum, fn
|
||||
{k, nil} ->
|
||||
{String.to_charlist(k), false}
|
||||
|
||||
{k, v} ->
|
||||
{String.to_charlist(k), String.to_charlist(v)}
|
||||
|
||||
other ->
|
||||
raise ArgumentError, "invalid environment key-value #{inspect(other)}"
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -197,31 +197,15 @@ defmodule Mix.Tasks.Deps.Compile do
|
||||
config_path = Path.join(dep_path, "mix.rebar.config")
|
||||
lib_path = Path.join(config[:env_path], "lib/*/ebin")
|
||||
|
||||
# REBAR_BARE_COMPILER_OUTPUT_DIR is only honored by rebar3 >= 3.14
|
||||
env = [
|
||||
{"REBAR_CONFIG", config_path},
|
||||
{"TERM", "dumb"},
|
||||
{"REBAR_BARE_COMPILER_OUTPUT_DIR", dep_path}
|
||||
{"TERM", "dumb"}
|
||||
]
|
||||
|
||||
cmd = "#{rebar_cmd(dep)} bare compile --paths #{lib_path}"
|
||||
|
||||
File.mkdir_p!(dep_path)
|
||||
File.write!(config_path, rebar_config(dep))
|
||||
|
||||
# We need to copy/symlink include/priv in case it is
|
||||
# needed for compiling the dependency itself. Later on
|
||||
# we will build the whole structure and also symlink/copy
|
||||
# ebin.
|
||||
#
|
||||
# Note both configurations are necessary when using the
|
||||
# bare compiler with compiler output dir, otherwise includes
|
||||
# and priv files can't be found. For example, without those
|
||||
# options, we were unable to compile certifi, which uses
|
||||
# both parse transforms and reads from priv at compilation.
|
||||
Mix.Utils.symlink_or_copy(Path.join(opts[:dest], "include"), Path.join(dep_path, "include"))
|
||||
Mix.Utils.symlink_or_copy(Path.join(opts[:dest], "priv"), Path.join(dep_path, "priv"))
|
||||
|
||||
do_command(dep, config, cmd, false, env)
|
||||
end
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user