ffmt 0.4.4__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. {ffmt-0.4.4 → ffmt-0.5.0}/.github/workflows/ci.yml +79 -27
  2. {ffmt-0.4.4 → ffmt-0.5.0}/.gitignore +0 -1
  3. {ffmt-0.4.4 → ffmt-0.5.0}/Cargo.lock +83 -54
  4. {ffmt-0.4.4 → ffmt-0.5.0}/Cargo.toml +2 -2
  5. {ffmt-0.4.4 → ffmt-0.5.0}/PKG-INFO +4 -4
  6. {ffmt-0.4.4 → ffmt-0.5.0}/README.md +3 -3
  7. {ffmt-0.4.4 → ffmt-0.5.0}/docs/configuration.md +35 -1
  8. {ffmt-0.4.4 → ffmt-0.5.0}/pyproject.toml +1 -1
  9. {ffmt-0.4.4 → ffmt-0.5.0}/src/classifier.rs +53 -73
  10. {ffmt-0.4.4 → ffmt-0.5.0}/src/config.rs +9 -0
  11. {ffmt-0.4.4 → ffmt-0.5.0}/src/formatter.rs +779 -79
  12. {ffmt-0.4.4 → ffmt-0.5.0}/src/keyword_norm.rs +29 -39
  13. {ffmt-0.4.4 → ffmt-0.5.0}/src/whitespace.rs +41 -14
  14. {ffmt-0.4.4 → ffmt-0.5.0}/tests/bugfixes.rs +381 -0
  15. {ffmt-0.4.4 → ffmt-0.5.0}/tests/config_integration.rs +139 -0
  16. ffmt-0.5.0/tests/fixtures/idempotence/break_before_member_access.f90 +12 -0
  17. ffmt-0.5.0/tests/fixtures/idempotence/consumed_doxygen_blanks.f90 +28 -0
  18. ffmt-0.5.0/tests/fixtures/idempotence/fypp_def_keyword_arguments.fpp +5 -0
  19. ffmt-0.5.0/tests/fixtures/idempotence/hoisted_continuation_comment.f90 +10 -0
  20. ffmt-0.5.0/tests/fixtures/idempotence/namelist_bare_commas.f90 +21 -0
  21. ffmt-0.5.0/tests/fixtures/idempotence/trailing_semicolon.f90 +3 -0
  22. ffmt-0.5.0/tests/fixtures/idempotence/wrapped_declaration.f90 +10 -0
  23. {ffmt-0.4.4 → ffmt-0.5.0}/tests/whitespace.rs +41 -0
  24. {ffmt-0.4.4 → ffmt-0.5.0}/.github/workflows/release.yml +0 -0
  25. {ffmt-0.4.4 → ffmt-0.5.0}/.github/workflows/update-readme-version.yml +0 -0
  26. {ffmt-0.4.4 → ffmt-0.5.0}/.markdownlint.json +0 -0
  27. {ffmt-0.4.4 → ffmt-0.5.0}/.pre-commit-hooks.yaml +0 -0
  28. {ffmt-0.4.4 → ffmt-0.5.0}/.readthedocs.yml +0 -0
  29. {ffmt-0.4.4 → ffmt-0.5.0}/LICENSE +0 -0
  30. {ffmt-0.4.4 → ffmt-0.5.0}/action.yml +0 -0
  31. {ffmt-0.4.4 → ffmt-0.5.0}/docs/ci.md +0 -0
  32. {ffmt-0.4.4 → ffmt-0.5.0}/docs/editors.md +0 -0
  33. {ffmt-0.4.4 → ffmt-0.5.0}/docs/getting-started.md +0 -0
  34. {ffmt-0.4.4 → ffmt-0.5.0}/docs/index.md +0 -0
  35. {ffmt-0.4.4 → ffmt-0.5.0}/docs/requirements.txt +0 -0
  36. {ffmt-0.4.4 → ffmt-0.5.0}/mkdocs.yml +0 -0
  37. {ffmt-0.4.4 → ffmt-0.5.0}/src/align.rs +0 -0
  38. {ffmt-0.4.4 → ffmt-0.5.0}/src/case_norm.rs +0 -0
  39. {ffmt-0.4.4 → ffmt-0.5.0}/src/cli.rs +0 -0
  40. {ffmt-0.4.4 → ffmt-0.5.0}/src/lib.rs +0 -0
  41. {ffmt-0.4.4 → ffmt-0.5.0}/src/lsp.rs +0 -0
  42. {ffmt-0.4.4 → ffmt-0.5.0}/src/main.rs +0 -0
  43. {ffmt-0.4.4 → ffmt-0.5.0}/src/reader.rs +0 -0
  44. {ffmt-0.4.4 → ffmt-0.5.0}/src/scope.rs +0 -0
  45. {ffmt-0.4.4 → ffmt-0.5.0}/src/unicode.rs +0 -0
  46. {ffmt-0.4.4 → ffmt-0.5.0}/tests/bughunt_classifier.rs +0 -0
  47. {ffmt-0.4.4 → ffmt-0.5.0}/tests/bughunt_cli.rs +0 -0
  48. {ffmt-0.4.4 → ffmt-0.5.0}/tests/bughunt_norm.rs +0 -0
  49. {ffmt-0.4.4 → ffmt-0.5.0}/tests/case_norm.rs +0 -0
  50. {ffmt-0.4.4 → ffmt-0.5.0}/tests/classifier.rs +0 -0
  51. {ffmt-0.4.4 → ffmt-0.5.0}/tests/cli_bugs.rs +0 -0
  52. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/blank_lines.expected.fpp +0 -0
  53. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/blank_lines.input.fpp +0 -0
  54. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/call_block.expected.fpp +0 -0
  55. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/call_block.input.fpp +0 -0
  56. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/directives.expected.fpp +0 -0
  57. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/directives.input.fpp +0 -0
  58. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/doxygen_spacing.expected.fpp +0 -0
  59. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/doxygen_spacing.input.fpp +0 -0
  60. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/fypp.expected.fpp +0 -0
  61. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/fypp.input.fpp +0 -0
  62. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/member_access_wrap.expected.fpp +0 -0
  63. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/member_access_wrap.input.fpp +0 -0
  64. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/simple.expected.fpp +0 -0
  65. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/simple.input.fpp +0 -0
  66. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/trailing_comment_wrap.expected.fpp +0 -0
  67. {ffmt-0.4.4 → ffmt-0.5.0}/tests/fixtures/trailing_comment_wrap.input.fpp +0 -0
  68. {ffmt-0.4.4 → ffmt-0.5.0}/tests/integration.rs +0 -0
  69. {ffmt-0.4.4 → ffmt-0.5.0}/tests/reader.rs +0 -0
  70. {ffmt-0.4.4 → ffmt-0.5.0}/tests/scope.rs +0 -0
@@ -15,7 +15,7 @@ jobs:
15
15
  with:
16
16
  components: clippy, rustfmt
17
17
  - run: cargo fmt --check
18
- - run: cargo test
18
+ - run: cargo test --locked
19
19
  - run: cargo clippy -- -D warnings
20
20
 
21
21
  # Dogfood: our own test fixtures should be formatted
@@ -116,18 +116,14 @@ jobs:
116
116
  mfc-nvhpc:
117
117
  name: MFC NVHPC ${{ matrix.target }}
118
118
  runs-on: ubuntu-22.04
119
- container: nvcr.io/nvidia/nvhpc:24.5-devel-cuda_multi-ubuntu22.04
120
- env:
121
- CC: nvc
122
- CXX: nvc++
123
- FC: nvfortran
124
- OMPI_ALLOW_RUN_AS_ROOT: 1
125
- OMPI_ALLOW_RUN_AS_ROOT_CONFIRM: 1
126
119
  strategy:
127
120
  fail-fast: false
128
121
  matrix:
129
122
  target: [cpu, gpu-omp]
123
+ env:
124
+ NVHPC_IMAGE: nvcr.io/nvidia/nvhpc:26.3-devel-cuda_multi-ubuntu22.04
130
125
  steps:
126
+ # Free disk on the host before pulling the ~25-30 GB cuda_multi image.
131
127
  - name: Free disk space
132
128
  uses: jlumbroso/free-disk-space@main
133
129
  with:
@@ -139,41 +135,97 @@ jobs:
139
135
 
140
136
  - uses: actions/checkout@v4
141
137
 
138
+ # Retry the pull: nvcr.io intermittently times out ("context deadline
139
+ # exceeded") under load. Pulls resume completed layers, so retries are
140
+ # cheap. This is why the job drives a container by hand instead of using
141
+ # the container: directive, which offers no way to retry.
142
+ - name: Pull NVHPC container
143
+ run: |
144
+ for attempt in 1 2 3 4 5; do
145
+ docker pull "$NVHPC_IMAGE" && exit 0
146
+ echo "docker pull failed (attempt $attempt/5); retrying in $((attempt * 30))s..."
147
+ sleep $((attempt * 30))
148
+ done
149
+ echo "::error::Failed to pull $NVHPC_IMAGE after 5 attempts"
150
+ exit 1
151
+
152
+ # A long-lived container preserves installed packages and env across
153
+ # steps, the way container: did.
154
+ #
155
+ # -tp=px targets generic x86-64 rather than the runner's own CPU.
156
+ # GitHub's ubuntu-22.04 pool mixes AVX-512-capable and non-capable
157
+ # hosts, and nvfortran's default -tp=native turns that into
158
+ # nondeterministic codegen: on an AVX-512 draw it emitted an RSQRT14S
159
+ # that its own LLVM backend could not select, aborting llc while
160
+ # compiling m_model.fpp. Mirrors the flags MFC uses in its own NVHPC CI.
161
+ - name: Start NVHPC container
162
+ run: |
163
+ docker run -d --name nvhpc \
164
+ --security-opt seccomp=unconfined \
165
+ -v "${{ github.workspace }}:/workspace" \
166
+ -w /workspace \
167
+ -e CC=nvc \
168
+ -e CXX=nvc++ \
169
+ -e FC=nvfortran \
170
+ -e OMPI_ALLOW_RUN_AS_ROOT=1 \
171
+ -e OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 \
172
+ -e "FFLAGS=-tp=px -Kieee -noswitcherror" \
173
+ -e CFLAGS=-tp=px \
174
+ -e CXXFLAGS=-tp=px \
175
+ "$NVHPC_IMAGE" sleep infinity
176
+
142
177
  - name: Install dependencies
143
178
  run: |
144
- apt-get update -y
145
- apt-get install -y cmake python3 python3-venv python3-pip \
146
- libfftw3-dev libhdf5-dev hdf5-tools \
147
- openmpi-bin libopenmpi-dev git curl
179
+ docker exec nvhpc bash -c '
180
+ set -e
181
+ apt-get update -y
182
+ apt-get install -y cmake python3 python3-venv python3-pip \
183
+ libfftw3-dev libhdf5-dev hdf5-tools \
184
+ openmpi-bin libopenmpi-dev git curl
185
+ # The repo is bind-mounted from the host, so git sees a different
186
+ # owner. Mark it safe to suppress "dubious ownership" errors.
187
+ git config --global --add safe.directory /workspace
188
+ '
148
189
 
149
190
  - name: Install Rust
150
191
  run: |
151
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
152
- echo "$HOME/.cargo/bin" >> $GITHUB_PATH
192
+ docker exec nvhpc bash -c '
193
+ set -e
194
+ curl --proto "=https" --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
195
+ '
153
196
 
154
197
  - name: Build ffmt
155
198
  run: |
156
- . "$HOME/.cargo/env"
157
- cargo build --release
199
+ docker exec nvhpc bash -c '
200
+ set -e
201
+ . "$HOME/.cargo/env"
202
+ cargo build --release
203
+ '
158
204
 
159
205
  - name: Clone MFC
160
- run: git clone --depth 1 https://github.com/MFlowCode/MFC.git /tmp/MFC
206
+ run: |
207
+ docker exec nvhpc git clone --depth 1 \
208
+ https://github.com/MFlowCode/MFC.git /tmp/MFC
161
209
 
162
210
  - name: Format MFC source with ffmt
163
211
  run: |
164
- . "$HOME/.cargo/env"
165
- ./target/release/ffmt -j $(nproc) /tmp/MFC/src/ 2>/dev/null || true
166
- ./target/release/ffmt -j $(nproc) /tmp/MFC/src/ 2>/dev/null || true
212
+ docker exec nvhpc bash -c '
213
+ ./target/release/ffmt -j $(nproc) /tmp/MFC/src/ 2>/dev/null || true
214
+ ./target/release/ffmt -j $(nproc) /tmp/MFC/src/ 2>/dev/null || true
215
+ '
167
216
 
168
217
  - name: Build MFC
169
218
  run: |
170
- cd /tmp/MFC
171
- pip install -e toolchain/
172
- GPU_FLAG=""
173
- if [ "${{ matrix.target }}" = "gpu-acc" ]; then GPU_FLAG="--gpu acc"; fi
174
- if [ "${{ matrix.target }}" = "gpu-omp" ]; then GPU_FLAG="--gpu mp"; fi
175
- JOBS=${{ matrix.target == 'cpu' && '$(nproc)' || '2' }}
176
- ./mfc.sh build -j $JOBS $GPU_FLAG
219
+ docker exec nvhpc bash -c '
220
+ set -e
221
+ cd /tmp/MFC
222
+ pip install -e toolchain/
223
+ GPU_FLAG=""
224
+ if [ "${{ matrix.target }}" = "gpu-acc" ]; then GPU_FLAG="--gpu acc"; fi
225
+ if [ "${{ matrix.target }}" = "gpu-omp" ]; then GPU_FLAG="--gpu mp"; fi
226
+ JOBS=${{ matrix.target == 'cpu' && '$(nproc)' || '2' }}
227
+ ./mfc.sh build -j $JOBS $GPU_FLAG
228
+ '
177
229
 
178
230
  docs:
179
231
  name: Documentation
@@ -1,4 +1,3 @@
1
1
  /target/
2
2
  .ffmt_cache/
3
- Cargo.lock
4
3
  site/
@@ -4,9 +4,9 @@ version = 4
4
4
 
5
5
  [[package]]
6
6
  name = "aho-corasick"
7
- version = "1.1.4"
7
+ version = "1.1.5"
8
8
  source = "registry+https://github.com/rust-lang/crates.io-index"
9
- checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
9
+ checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba"
10
10
  dependencies = [
11
11
  "memchr",
12
12
  ]
@@ -63,9 +63,9 @@ dependencies = [
63
63
 
64
64
  [[package]]
65
65
  name = "bstr"
66
- version = "1.12.3"
66
+ version = "1.13.1"
67
67
  source = "registry+https://github.com/rust-lang/crates.io-index"
68
- checksum = "5cee35f73844aa3014bb606320a6c1f010249dbdf43342fe54b5a4f6a8ed4b79"
68
+ checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f"
69
69
  dependencies = [
70
70
  "memchr",
71
71
  "serde_core",
@@ -73,9 +73,9 @@ dependencies = [
73
73
 
74
74
  [[package]]
75
75
  name = "clap"
76
- version = "4.6.1"
76
+ version = "4.6.7"
77
77
  source = "registry+https://github.com/rust-lang/crates.io-index"
78
- checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"
78
+ checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946"
79
79
  dependencies = [
80
80
  "clap_builder",
81
81
  "clap_derive",
@@ -83,9 +83,9 @@ dependencies = [
83
83
 
84
84
  [[package]]
85
85
  name = "clap_builder"
86
- version = "4.6.0"
86
+ version = "4.6.7"
87
87
  source = "registry+https://github.com/rust-lang/crates.io-index"
88
- checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
88
+ checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d"
89
89
  dependencies = [
90
90
  "anstream",
91
91
  "anstyle",
@@ -95,9 +95,9 @@ dependencies = [
95
95
 
96
96
  [[package]]
97
97
  name = "clap_derive"
98
- version = "4.6.1"
98
+ version = "4.6.7"
99
99
  source = "registry+https://github.com/rust-lang/crates.io-index"
100
- checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9"
100
+ checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0"
101
101
  dependencies = [
102
102
  "heck",
103
103
  "proc-macro2",
@@ -107,9 +107,9 @@ dependencies = [
107
107
 
108
108
  [[package]]
109
109
  name = "clap_lex"
110
- version = "1.1.0"
110
+ version = "1.1.1"
111
111
  source = "registry+https://github.com/rust-lang/crates.io-index"
112
- checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
112
+ checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486"
113
113
 
114
114
  [[package]]
115
115
  name = "colorchoice"
@@ -119,9 +119,9 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
119
119
 
120
120
  [[package]]
121
121
  name = "crossbeam-deque"
122
- version = "0.8.7"
122
+ version = "0.8.8"
123
123
  source = "registry+https://github.com/rust-lang/crates.io-index"
124
- checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb"
124
+ checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a"
125
125
  dependencies = [
126
126
  "crossbeam-epoch",
127
127
  "crossbeam-utils",
@@ -129,39 +129,39 @@ dependencies = [
129
129
 
130
130
  [[package]]
131
131
  name = "crossbeam-epoch"
132
- version = "0.9.20"
132
+ version = "0.9.21"
133
133
  source = "registry+https://github.com/rust-lang/crates.io-index"
134
- checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
134
+ checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d"
135
135
  dependencies = [
136
136
  "crossbeam-utils",
137
137
  ]
138
138
 
139
139
  [[package]]
140
140
  name = "crossbeam-utils"
141
- version = "0.8.22"
141
+ version = "0.8.23"
142
142
  source = "registry+https://github.com/rust-lang/crates.io-index"
143
- checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
143
+ checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6"
144
144
 
145
145
  [[package]]
146
146
  name = "either"
147
- version = "1.16.0"
147
+ version = "1.19.0"
148
148
  source = "registry+https://github.com/rust-lang/crates.io-index"
149
- checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
149
+ checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be"
150
150
 
151
151
  [[package]]
152
152
  name = "equivalent"
153
- version = "1.0.2"
153
+ version = "1.0.3"
154
154
  source = "registry+https://github.com/rust-lang/crates.io-index"
155
- checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
155
+ checksum = "00d174d5400e5e8fd687ad1049e2f578285fa914201b1af7e8b112a4546bd826"
156
156
 
157
157
  [[package]]
158
158
  name = "ffmt"
159
- version = "0.4.4"
159
+ version = "0.5.0"
160
160
  dependencies = [
161
161
  "clap",
162
162
  "ignore",
163
+ "lazy-regex",
163
164
  "rayon",
164
- "regex",
165
165
  "serde",
166
166
  "serde_json",
167
167
  "toml",
@@ -169,9 +169,9 @@ dependencies = [
169
169
 
170
170
  [[package]]
171
171
  name = "globset"
172
- version = "0.4.18"
172
+ version = "0.4.21"
173
173
  source = "registry+https://github.com/rust-lang/crates.io-index"
174
- checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3"
174
+ checksum = "f98b0d85522dc0a824cfebbc9594ff4a9b289c568bea0370319dfbdf20ccdd2d"
175
175
  dependencies = [
176
176
  "aho-corasick",
177
177
  "bstr",
@@ -194,9 +194,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
194
194
 
195
195
  [[package]]
196
196
  name = "ignore"
197
- version = "0.4.28"
197
+ version = "0.4.34"
198
198
  source = "registry+https://github.com/rust-lang/crates.io-index"
199
- checksum = "2adf14691c72bcfc1058740436a35bdd3ae9c07d1a941ef00b749e9ea16aefa7"
199
+ checksum = "484be5657551d7868d67587df967fb4fcbe9d266a761cc855aaa148fda0b3cc7"
200
200
  dependencies = [
201
201
  "crossbeam-deque",
202
202
  "globset",
@@ -210,9 +210,9 @@ dependencies = [
210
210
 
211
211
  [[package]]
212
212
  name = "indexmap"
213
- version = "2.14.0"
213
+ version = "2.14.2"
214
214
  source = "registry+https://github.com/rust-lang/crates.io-index"
215
- checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
215
+ checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855"
216
216
  dependencies = [
217
217
  "equivalent",
218
218
  "hashbrown",
@@ -226,15 +226,38 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
226
226
 
227
227
  [[package]]
228
228
  name = "itoa"
229
- version = "1.0.18"
229
+ version = "1.0.19"
230
230
  source = "registry+https://github.com/rust-lang/crates.io-index"
231
- checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
231
+ checksum = "3bd1574e617a9a6c1f8f8181bd7e841e1f20e4277607ef28945765188d6284d4"
232
+
233
+ [[package]]
234
+ name = "lazy-regex"
235
+ version = "3.6.2"
236
+ source = "registry+https://github.com/rust-lang/crates.io-index"
237
+ checksum = "f0a2cce8a22920a29fdcc8c9170aa5d29edd9fbcf8bea856e24c2cb1c2419f67"
238
+ dependencies = [
239
+ "lazy-regex-proc_macros",
240
+ "once_cell",
241
+ "regex",
242
+ ]
243
+
244
+ [[package]]
245
+ name = "lazy-regex-proc_macros"
246
+ version = "3.6.2"
247
+ source = "registry+https://github.com/rust-lang/crates.io-index"
248
+ checksum = "6f1e4b1f1d8c71edb4ff2b2150ec4606445fd2ddf67ddc097655daf59286baa6"
249
+ dependencies = [
250
+ "proc-macro2",
251
+ "quote",
252
+ "regex",
253
+ "syn",
254
+ ]
232
255
 
233
256
  [[package]]
234
257
  name = "log"
235
- version = "0.4.33"
258
+ version = "0.4.35"
236
259
  source = "registry+https://github.com/rust-lang/crates.io-index"
237
- checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
260
+ checksum = "5d15f86d12da44cd8d4ec3c73984537eb7f4cadcb9776a575a0a8a05ca11005c"
238
261
 
239
262
  [[package]]
240
263
  name = "memchr"
@@ -242,6 +265,12 @@ version = "2.8.3"
242
265
  source = "registry+https://github.com/rust-lang/crates.io-index"
243
266
  checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
244
267
 
268
+ [[package]]
269
+ name = "once_cell"
270
+ version = "1.21.4"
271
+ source = "registry+https://github.com/rust-lang/crates.io-index"
272
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
273
+
245
274
  [[package]]
246
275
  name = "once_cell_polyfill"
247
276
  version = "1.70.2"
@@ -250,18 +279,18 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
250
279
 
251
280
  [[package]]
252
281
  name = "proc-macro2"
253
- version = "1.0.106"
282
+ version = "1.0.107"
254
283
  source = "registry+https://github.com/rust-lang/crates.io-index"
255
- checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
284
+ checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
256
285
  dependencies = [
257
286
  "unicode-ident",
258
287
  ]
259
288
 
260
289
  [[package]]
261
290
  name = "quote"
262
- version = "1.0.46"
291
+ version = "1.0.47"
263
292
  source = "registry+https://github.com/rust-lang/crates.io-index"
264
- checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
293
+ checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
265
294
  dependencies = [
266
295
  "proc-macro2",
267
296
  ]
@@ -288,9 +317,9 @@ dependencies = [
288
317
 
289
318
  [[package]]
290
319
  name = "regex"
291
- version = "1.13.0"
320
+ version = "1.13.1"
292
321
  source = "registry+https://github.com/rust-lang/crates.io-index"
293
- checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2"
322
+ checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
294
323
  dependencies = [
295
324
  "aho-corasick",
296
325
  "memchr",
@@ -300,9 +329,9 @@ dependencies = [
300
329
 
301
330
  [[package]]
302
331
  name = "regex-automata"
303
- version = "0.4.15"
332
+ version = "0.4.18"
304
333
  source = "registry+https://github.com/rust-lang/crates.io-index"
305
- checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db"
334
+ checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
306
335
  dependencies = [
307
336
  "aho-corasick",
308
337
  "memchr",
@@ -326,9 +355,9 @@ dependencies = [
326
355
 
327
356
  [[package]]
328
357
  name = "serde"
329
- version = "1.0.228"
358
+ version = "1.0.229"
330
359
  source = "registry+https://github.com/rust-lang/crates.io-index"
331
- checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
360
+ checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
332
361
  dependencies = [
333
362
  "serde_core",
334
363
  "serde_derive",
@@ -336,18 +365,18 @@ dependencies = [
336
365
 
337
366
  [[package]]
338
367
  name = "serde_core"
339
- version = "1.0.228"
368
+ version = "1.0.229"
340
369
  source = "registry+https://github.com/rust-lang/crates.io-index"
341
- checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
370
+ checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
342
371
  dependencies = [
343
372
  "serde_derive",
344
373
  ]
345
374
 
346
375
  [[package]]
347
376
  name = "serde_derive"
348
- version = "1.0.228"
377
+ version = "1.0.229"
349
378
  source = "registry+https://github.com/rust-lang/crates.io-index"
350
- checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
379
+ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
351
380
  dependencies = [
352
381
  "proc-macro2",
353
382
  "quote",
@@ -356,9 +385,9 @@ dependencies = [
356
385
 
357
386
  [[package]]
358
387
  name = "serde_json"
359
- version = "1.0.150"
388
+ version = "1.0.154"
360
389
  source = "registry+https://github.com/rust-lang/crates.io-index"
361
- checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
390
+ checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6"
362
391
  dependencies = [
363
392
  "itoa",
364
393
  "memchr",
@@ -384,9 +413,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
384
413
 
385
414
  [[package]]
386
415
  name = "syn"
387
- version = "2.0.118"
416
+ version = "3.0.10"
388
417
  source = "registry+https://github.com/rust-lang/crates.io-index"
389
- checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
418
+ checksum = "4ae9ccbea3a7b0b09443036490c8f34a8b1b760fd345e5c0dae0aac718faea79"
390
419
  dependencies = [
391
420
  "proc-macro2",
392
421
  "quote",
@@ -436,9 +465,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
436
465
 
437
466
  [[package]]
438
467
  name = "unicode-ident"
439
- version = "1.0.24"
468
+ version = "1.0.27"
440
469
  source = "registry+https://github.com/rust-lang/crates.io-index"
441
- checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
470
+ checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
442
471
 
443
472
  [[package]]
444
473
  name = "utf8parse"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "ffmt"
3
- version = "0.4.4"
3
+ version = "0.5.0"
4
4
  edition = "2021"
5
5
  description = "A fast, configurable Fortran formatter with Fypp, Doxygen, and OpenACC/OpenMP support"
6
6
  license = "MIT"
@@ -10,11 +10,11 @@ categories = ["development-tools", "command-line-utilities"]
10
10
  readme = "README.md"
11
11
 
12
12
  [dependencies]
13
- regex = "1"
14
13
  clap = { version = "4", features = ["derive"] }
15
14
  rayon = "1"
16
15
  ignore = "0.4"
17
16
  toml = "0.8"
18
17
  serde = { version = "1", features = ["derive"] }
19
18
  serde_json = "1"
19
+ lazy-regex = "3.3.0"
20
20
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ffmt
3
- Version: 0.4.4
3
+ Version: 0.5.0
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: Intended Audience :: Science/Research
@@ -51,11 +51,11 @@ cat file.fpp | ffmt - # stdin/stdout
51
51
 
52
52
  ## Features
53
53
 
54
- - **Code** -- indentation, whitespace normalization, keyword casing, named ends, line wrapping, operator modernization (`.eq.` -> `==`), double-colon enforcement, trailing semicolon removal
54
+ - **Code** -- indentation, whitespace normalization, keyword casing, named ends, line wrapping, operator modernization (`.eq.` -> `==`), double-colon enforcement, trailing semicolon removal, `only :` -> `only:`
55
55
  - **Comments** -- rewrapping, inline spacing (S102), `!<` alignment, `!&`/`& !` cleanup, format suppression (`! ffmt off/on`)
56
56
  - **Structure** -- blank line management around openers/closers/`#ifdef`, declaration `::` alignment, declaration/use compaction
57
57
  - **Preprocessor** -- Fypp (`#:if`, `$:`, `@:`), C preprocessor (`#ifdef`), OpenACC (`!$acc`), OpenMP (`!$omp`)
58
- - **Opt-in** -- multi-statement splitting, assignment alignment, `&` column alignment, use-statement reformatting
58
+ - **Opt-in** -- multi-statement splitting, assignment alignment, `only:` alignment, `&` column alignment, use-statement reformatting
59
59
 
60
60
  Most options accept `true`, `false`, or `"preserve"`. See the [configuration reference](https://ffmt-fortran.readthedocs.io/en/latest/configuration/) for all options.
61
61
 
@@ -88,7 +88,7 @@ multdiv = false
88
88
  # pre-commit
89
89
  repos:
90
90
  - repo: https://github.com/sbryngelson/ffmt
91
- rev: v0.4.3
91
+ rev: v0.4.5
92
92
  hooks:
93
93
  - id: ffmt
94
94
  ```
@@ -34,11 +34,11 @@ cat file.fpp | ffmt - # stdin/stdout
34
34
 
35
35
  ## Features
36
36
 
37
- - **Code** -- indentation, whitespace normalization, keyword casing, named ends, line wrapping, operator modernization (`.eq.` -> `==`), double-colon enforcement, trailing semicolon removal
37
+ - **Code** -- indentation, whitespace normalization, keyword casing, named ends, line wrapping, operator modernization (`.eq.` -> `==`), double-colon enforcement, trailing semicolon removal, `only :` -> `only:`
38
38
  - **Comments** -- rewrapping, inline spacing (S102), `!<` alignment, `!&`/`& !` cleanup, format suppression (`! ffmt off/on`)
39
39
  - **Structure** -- blank line management around openers/closers/`#ifdef`, declaration `::` alignment, declaration/use compaction
40
40
  - **Preprocessor** -- Fypp (`#:if`, `$:`, `@:`), C preprocessor (`#ifdef`), OpenACC (`!$acc`), OpenMP (`!$omp`)
41
- - **Opt-in** -- multi-statement splitting, assignment alignment, `&` column alignment, use-statement reformatting
41
+ - **Opt-in** -- multi-statement splitting, assignment alignment, `only:` alignment, `&` column alignment, use-statement reformatting
42
42
 
43
43
  Most options accept `true`, `false`, or `"preserve"`. See the [configuration reference](https://ffmt-fortran.readthedocs.io/en/latest/configuration/) for all options.
44
44
 
@@ -71,7 +71,7 @@ multdiv = false
71
71
  # pre-commit
72
72
  repos:
73
73
  - repo: https://github.com/sbryngelson/ffmt
74
- rev: v0.4.3
74
+ rev: v0.4.5
75
75
  hooks:
76
76
  - id: ffmt
77
77
  ```
@@ -125,7 +125,9 @@ private; public :: s_foo private; public :: s_foo ! preserved
125
125
 
126
126
  ### `rewrap-comments` (toggle)
127
127
 
128
- Re-wrap long `!` and `!!` comment blocks at `line-length`. Doxygen `!>` / `!!` blocks are joined and re-wrapped as units. Short consecutive comment lines are merged.
128
+ Re-wrap long `!` and `!!` comment blocks at `line-length`. Doxygen `!>` / `!!` blocks are joined and re-wrapped as units. Short consecutive comment lines are merged. When a comment of running prose overflows, the overflow is pushed into the following prose line of the same block rather than left on a line of its own.
129
+
130
+ Only running text absorbs overflow. A comment line that carries structure ends the block and is never rewritten: any marker (`!!`, `!>`, `!<`, `!*`, `!@`, `!$`, `!&`, or a vendor directive such as `!DEC$`), a blank comment line, a separator banner (`! ----`, `! === Setup ===`), a bullet or numbered item (`! - x`, `! 1. x`), a `TODO:`-style tag, a line indented past the marker for alignment, and `! ffmt off`. A comment written without the space after `!` is left alone as well.
129
131
 
130
132
  **Default:** `true`
131
133
 
@@ -188,6 +190,8 @@ Align `=` signs across consecutive assignment statements.
188
190
 
189
191
  **Default:** `false`
190
192
 
193
+ `"preserve"` only disables this pass; `collapse-double-spaces` and whitespace normalization still run, so existing manual alignment is not retained.
194
+
191
195
  ```fortran
192
196
  ! true ! false
193
197
  x = 1 x = 1
@@ -195,6 +199,36 @@ long_var = 2 long_var = 2
195
199
  y = 3 y = 3
196
200
  ```
197
201
 
202
+ ### `align-use-only` (toggle)
203
+
204
+ Align `only:` across consecutive `use` statements at the same indentation. Padding goes after the comma before `only:`. A `use` without `only:` stays in the group unchanged; a blank line, comment, or other statement ends the group. Lines that would exceed `line-length` are left alone.
205
+
206
+ **Default:** `false`
207
+
208
+ ```fortran
209
+ ! true ! false
210
+ use m_derived_types, only: t_foo use m_derived_types, only: t_foo
211
+ use m_global, only: a, b use m_global, only: a, b
212
+ use m_mpi use m_mpi
213
+ use m_x, only: d use m_x, only: d
214
+ ```
215
+
216
+ ### `leading-ampersand` (boolean)
217
+
218
+ Emit the optional leading `&` on continuation lines. Set to `false` to drop it. The `&` is kept where Fortran requires it (a continued character literal) and where dropping it would expose a `#`, `!`, or Fypp line to the parser.
219
+
220
+ **Default:** `true`
221
+
222
+ ```fortran
223
+ ! true
224
+ call s_foo(x, &
225
+ & y, z)
226
+
227
+ ! false
228
+ call s_foo(x, &
229
+ y, z)
230
+ ```
231
+
198
232
  ### `align-ampersand` (toggle)
199
233
 
200
234
  Align trailing `&` continuation markers at the column limit.
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "ffmt"
7
- version = "0.4.4"
7
+ version = "0.5.0"
8
8
  description = "A fast, configurable Fortran formatter with Fypp, Doxygen, and OpenACC/OpenMP support"
9
9
  license = { text = "MIT" }
10
10
  requires-python = ">=3.8"