ffmt 0.3.0__tar.gz → 0.3.4__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 (59) hide show
  1. {ffmt-0.3.0 → ffmt-0.3.4}/.github/workflows/ci.yml +1 -1
  2. {ffmt-0.3.0 → ffmt-0.3.4}/Cargo.lock +1 -1
  3. {ffmt-0.3.0 → ffmt-0.3.4}/Cargo.toml +1 -1
  4. {ffmt-0.3.0 → ffmt-0.3.4}/PKG-INFO +2 -2
  5. {ffmt-0.3.0 → ffmt-0.3.4}/README.md +1 -1
  6. {ffmt-0.3.0 → ffmt-0.3.4}/pyproject.toml +1 -1
  7. {ffmt-0.3.0 → ffmt-0.3.4}/src/formatter.rs +33 -0
  8. {ffmt-0.3.0 → ffmt-0.3.4}/src/whitespace.rs +47 -2
  9. {ffmt-0.3.0 → ffmt-0.3.4}/tests/fixtures/blank_lines.expected.fpp +0 -1
  10. ffmt-0.3.4/tests/fixtures/blank_lines.input.fpp +11 -0
  11. ffmt-0.3.4/tests/fixtures/call_block.input.fpp +10 -0
  12. ffmt-0.3.4/tests/fixtures/directives.input.fpp +17 -0
  13. {ffmt-0.3.0 → ffmt-0.3.4}/tests/fixtures/doxygen_spacing.input.fpp +17 -4
  14. ffmt-0.3.4/tests/fixtures/fypp.input.fpp +31 -0
  15. {ffmt-0.3.0 → ffmt-0.3.4}/tests/fixtures/simple.expected.fpp +2 -0
  16. ffmt-0.3.4/tests/fixtures/simple.input.fpp +27 -0
  17. ffmt-0.3.0/tests/fixtures/blank_lines.input.fpp +0 -12
  18. ffmt-0.3.0/tests/fixtures/call_block.input.fpp +0 -8
  19. ffmt-0.3.0/tests/fixtures/directives.input.fpp +0 -14
  20. ffmt-0.3.0/tests/fixtures/fypp.input.fpp +0 -26
  21. ffmt-0.3.0/tests/fixtures/simple.input.fpp +0 -19
  22. {ffmt-0.3.0 → ffmt-0.3.4}/.github/workflows/release.yml +0 -0
  23. {ffmt-0.3.0 → ffmt-0.3.4}/.github/workflows/update-readme-version.yml +0 -0
  24. {ffmt-0.3.0 → ffmt-0.3.4}/.gitignore +0 -0
  25. {ffmt-0.3.0 → ffmt-0.3.4}/.markdownlint.json +0 -0
  26. {ffmt-0.3.0 → ffmt-0.3.4}/.pre-commit-hooks.yaml +0 -0
  27. {ffmt-0.3.0 → ffmt-0.3.4}/.readthedocs.yml +0 -0
  28. {ffmt-0.3.0 → ffmt-0.3.4}/LICENSE +0 -0
  29. {ffmt-0.3.0 → ffmt-0.3.4}/action.yml +0 -0
  30. {ffmt-0.3.0 → ffmt-0.3.4}/docs/ci.md +0 -0
  31. {ffmt-0.3.0 → ffmt-0.3.4}/docs/configuration.md +0 -0
  32. {ffmt-0.3.0 → ffmt-0.3.4}/docs/editors.md +0 -0
  33. {ffmt-0.3.0 → ffmt-0.3.4}/docs/getting-started.md +0 -0
  34. {ffmt-0.3.0 → ffmt-0.3.4}/docs/index.md +0 -0
  35. {ffmt-0.3.0 → ffmt-0.3.4}/docs/requirements.txt +0 -0
  36. {ffmt-0.3.0 → ffmt-0.3.4}/mkdocs.yml +0 -0
  37. {ffmt-0.3.0 → ffmt-0.3.4}/src/align.rs +0 -0
  38. {ffmt-0.3.0 → ffmt-0.3.4}/src/case_norm.rs +0 -0
  39. {ffmt-0.3.0 → ffmt-0.3.4}/src/classifier.rs +0 -0
  40. {ffmt-0.3.0 → ffmt-0.3.4}/src/cli.rs +0 -0
  41. {ffmt-0.3.0 → ffmt-0.3.4}/src/config.rs +0 -0
  42. {ffmt-0.3.0 → ffmt-0.3.4}/src/keyword_norm.rs +0 -0
  43. {ffmt-0.3.0 → ffmt-0.3.4}/src/lib.rs +0 -0
  44. {ffmt-0.3.0 → ffmt-0.3.4}/src/lsp.rs +0 -0
  45. {ffmt-0.3.0 → ffmt-0.3.4}/src/main.rs +0 -0
  46. {ffmt-0.3.0 → ffmt-0.3.4}/src/reader.rs +0 -0
  47. {ffmt-0.3.0 → ffmt-0.3.4}/src/scope.rs +0 -0
  48. {ffmt-0.3.0 → ffmt-0.3.4}/src/unicode.rs +0 -0
  49. {ffmt-0.3.0 → ffmt-0.3.4}/tests/case_norm.rs +0 -0
  50. {ffmt-0.3.0 → ffmt-0.3.4}/tests/classifier.rs +0 -0
  51. {ffmt-0.3.0 → ffmt-0.3.4}/tests/config_integration.rs +0 -0
  52. {ffmt-0.3.0 → ffmt-0.3.4}/tests/fixtures/call_block.expected.fpp +0 -0
  53. {ffmt-0.3.0 → ffmt-0.3.4}/tests/fixtures/directives.expected.fpp +0 -0
  54. {ffmt-0.3.0 → ffmt-0.3.4}/tests/fixtures/doxygen_spacing.expected.fpp +0 -0
  55. {ffmt-0.3.0 → ffmt-0.3.4}/tests/fixtures/fypp.expected.fpp +0 -0
  56. {ffmt-0.3.0 → ffmt-0.3.4}/tests/integration.rs +0 -0
  57. {ffmt-0.3.0 → ffmt-0.3.4}/tests/reader.rs +0 -0
  58. {ffmt-0.3.0 → ffmt-0.3.4}/tests/scope.rs +0 -0
  59. {ffmt-0.3.0 → ffmt-0.3.4}/tests/whitespace.rs +0 -0
@@ -126,7 +126,7 @@ jobs:
126
126
  strategy:
127
127
  fail-fast: false
128
128
  matrix:
129
- target: [cpu, gpu-acc, gpu-omp]
129
+ target: [cpu, gpu-omp]
130
130
  steps:
131
131
  - uses: actions/checkout@v4
132
132
 
@@ -156,7 +156,7 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
156
156
 
157
157
  [[package]]
158
158
  name = "ffmt"
159
- version = "0.3.0"
159
+ version = "0.3.4"
160
160
  dependencies = [
161
161
  "clap",
162
162
  "ignore",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "ffmt"
3
- version = "0.3.0"
3
+ version = "0.3.4"
4
4
  edition = "2021"
5
5
  description = "A fast, configurable Fortran formatter with Fypp, Doxygen, and OpenACC/OpenMP support"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ffmt
3
- Version: 0.3.0
3
+ Version: 0.3.4
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: Intended Audience :: Science/Research
@@ -88,7 +88,7 @@ multdiv = false
88
88
  # pre-commit
89
89
  repos:
90
90
  - repo: https://github.com/sbryngelson/ffmt
91
- rev: v0.2.8
91
+ rev: v0.3.3
92
92
  hooks:
93
93
  - id: ffmt
94
94
  ```
@@ -71,7 +71,7 @@ multdiv = false
71
71
  # pre-commit
72
72
  repos:
73
73
  - repo: https://github.com/sbryngelson/ffmt
74
- rev: v0.2.8
74
+ rev: v0.3.3
75
75
  hooks:
76
76
  - id: ffmt
77
77
  ```
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "ffmt"
7
- version = "0.3.0"
7
+ version = "0.3.4"
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"
@@ -517,6 +517,9 @@ pub fn format_with_config(source: &str, config: &Config, range: Option<(usize, u
517
517
  output_lines = apply(output_lines, &|lines| reformat_use_statements(lines, iw));
518
518
  }
519
519
 
520
+ // Ensure blank line before and after `implicit none`
521
+ output_lines = apply(output_lines, &ensure_implicit_none_spacing);
522
+
520
523
  // Remove blank lines immediately before block closers/continuations
521
524
  output_lines = apply(output_lines, &remove_blanks_before_closers);
522
525
 
@@ -1182,6 +1185,36 @@ fn compact_use_statements(lines: &[String]) -> Vec<String> {
1182
1185
  result
1183
1186
  }
1184
1187
 
1188
+ /// Ensure one blank line before and after `implicit none`.
1189
+ /// The blank line before separates it from `use` statements.
1190
+ /// The blank line after separates it from declarations.
1191
+ fn ensure_implicit_none_spacing(lines: &[String]) -> Vec<String> {
1192
+ let mut result = Vec::with_capacity(lines.len() + 4);
1193
+ for (i, line) in lines.iter().enumerate() {
1194
+ let trimmed = line.trim().to_ascii_lowercase();
1195
+ if trimmed == "implicit none" {
1196
+ // Ensure blank line before (unless at start or already blank)
1197
+ if i > 0 {
1198
+ let prev = result
1199
+ .last()
1200
+ .map(|s: &String| s.trim().is_empty())
1201
+ .unwrap_or(true);
1202
+ if !prev {
1203
+ result.push(String::new());
1204
+ }
1205
+ }
1206
+ result.push(line.clone());
1207
+ // Ensure blank line after (unless next is blank or end)
1208
+ if i + 1 < lines.len() && !lines[i + 1].trim().is_empty() {
1209
+ result.push(String::new());
1210
+ }
1211
+ } else {
1212
+ result.push(line.clone());
1213
+ }
1214
+ }
1215
+ result
1216
+ }
1217
+
1185
1218
  /// Remove blank lines immediately before block closers/continuations
1186
1219
  /// and immediately after block openers.
1187
1220
  fn remove_blanks_before_closers(lines: &[String]) -> Vec<String> {
@@ -730,6 +730,45 @@ fn is_io_format_star(tokens: &[Token]) -> bool {
730
730
  false
731
731
  }
732
732
 
733
+ /// Check if a comma at `idx` is inside a slice expression.
734
+ /// A comma is a "slice comma" if either the preceding or following dimension
735
+ /// (at the same paren depth) contains a SliceColon.
736
+ fn is_slice_comma(tokens: &[Token], idx: usize) -> bool {
737
+ // Look backward from idx for a SliceColon at the same nesting level
738
+ let mut depth: i32 = 0;
739
+ for token in tokens[..idx].iter().rev() {
740
+ match token {
741
+ Token::Op(OpKind::CloseParen, _) => depth += 1,
742
+ Token::Op(OpKind::OpenParen, _) => {
743
+ if depth == 0 {
744
+ break;
745
+ }
746
+ depth -= 1;
747
+ }
748
+ Token::Op(OpKind::SliceColon, _) if depth == 0 => return true,
749
+ Token::Op(OpKind::Comma, _) if depth == 0 => break,
750
+ _ => {}
751
+ }
752
+ }
753
+ // Look forward from idx for a SliceColon at the same nesting level
754
+ depth = 0;
755
+ for token in tokens.iter().skip(idx + 1) {
756
+ match token {
757
+ Token::Op(OpKind::OpenParen, _) => depth += 1,
758
+ Token::Op(OpKind::CloseParen, _) => {
759
+ if depth == 0 {
760
+ break;
761
+ }
762
+ depth -= 1;
763
+ }
764
+ Token::Op(OpKind::SliceColon, _) if depth == 0 => return true,
765
+ Token::Op(OpKind::Comma, _) if depth == 0 => break,
766
+ _ => {}
767
+ }
768
+ }
769
+ false
770
+ }
771
+
733
772
  fn is_unary_context(tokens: &[Token]) -> bool {
734
773
  // Walk backwards, skipping Space tokens
735
774
  for token in tokens.iter().rev() {
@@ -829,12 +868,18 @@ fn render(tokens: &[Token], ws: &WhitespaceConfig) -> String {
829
868
  out.push_str(op_str);
830
869
  }
831
870
  }
832
- // Comma: no space before, configurable space after
871
+ // Comma: no space before, configurable space after.
872
+ // When slice_colon is compact, commas inside slice expressions
873
+ // (adjacent to a SliceColon) also omit the trailing space.
833
874
  OpKind::Comma => {
834
875
  trim_trailing_space(&mut out);
835
876
  out.push_str(op_str);
836
877
  if spaced {
837
- out.push(' ');
878
+ let in_slice =
879
+ !ws.slice_colon.is_enabled() && is_slice_comma(tokens, idx);
880
+ if !in_slice {
881
+ out.push(' ');
882
+ }
838
883
  }
839
884
  }
840
885
  // Keyword arg = : always no spaces
@@ -1,7 +1,6 @@
1
1
  subroutine s_test()
2
2
 
3
3
  integer :: i
4
-
5
4
  integer :: j
6
5
  !$acc parallel loop
7
6
 
@@ -0,0 +1,11 @@
1
+ subroutine s_test()
2
+
3
+ integer :: i
4
+ integer :: j
5
+ !$acc parallel loop
6
+
7
+ do i = 1, n
8
+ x(i) = 0
9
+ end do
10
+
11
+ end subroutine s_test
@@ -0,0 +1,10 @@
1
+ subroutine s_test()
2
+
3
+ #:call GPU_HOST_DATA(use_device_addr='[buff]')
4
+ call MPI_Send(buff, n, mpi_p, dst, tag, comm, ierr)
5
+ do i = 1, n
6
+ x(i) = y(i)
7
+ end do
8
+ #:endcall GPU_HOST_DATA
9
+
10
+ end subroutine s_test
@@ -0,0 +1,17 @@
1
+ subroutine s_test()
2
+
3
+ integer :: i, j, k
4
+
5
+ #if defined(MFC_OpenACC)
6
+ !$acc parallel loop collapse(3)
7
+ do k = 0, p
8
+ do j = 0, n
9
+ do i = 0, m
10
+ x(i, j, k) = y(i, j, k)*z(i, j, k)
11
+ end do
12
+ end do
13
+ end do
14
+ !$acc end parallel loop
15
+ #endif
16
+
17
+ end subroutine s_test
@@ -5,25 +5,38 @@ module m_test
5
5
  contains
6
6
 
7
7
  subroutine s_first()
8
+
8
9
  integer :: x
10
+
9
11
  x = 1
12
+
10
13
  end subroutine s_first
11
- !> @brief Second procedure
12
- !! Does something else
14
+
15
+ !> @brief Second procedure Does something else
13
16
  subroutine s_second()
17
+
14
18
  integer :: y
19
+
15
20
  y = 2
21
+
16
22
  end subroutine s_second
17
- !> Third procedure with a long description that documents
18
- !! what this function does
23
+
24
+ !> Third procedure with a long description that documents what this function does
19
25
  function f_third() result(z)
26
+
20
27
  integer :: z
28
+
21
29
  z = 3
30
+
22
31
  end function f_third
32
+
23
33
  !> Fourth procedure
24
34
  subroutine s_fourth()
35
+
25
36
  integer :: w
37
+
26
38
  w = 4
39
+
27
40
  end subroutine s_fourth
28
41
 
29
42
  end module m_test
@@ -0,0 +1,31 @@
1
+ #:include 'macros.fpp'
2
+ module m_fypp_test
3
+
4
+ implicit none
5
+
6
+ contains
7
+ subroutine s_test()
8
+
9
+ #:if defined('MFC_OpenACC')
10
+ $:GPU_PARALLEL_LOOP(collapse=3)
11
+ do k = 0, p
12
+ do j = 0, n
13
+ do i = 0, m
14
+ x(i, j, k) = 0.0_wp
15
+ end do
16
+ end do
17
+ end do
18
+ $:END_GPU_PARALLEL_LOOP()
19
+ #:else
20
+ do k = 0, p
21
+ do j = 0, n
22
+ do i = 0, m
23
+ x(i, j, k) = 0.0_wp
24
+ end do
25
+ end do
26
+ end do
27
+ #:endif
28
+
29
+ end subroutine s_test
30
+
31
+ end module m_fypp_test
@@ -1,7 +1,9 @@
1
1
  module m_test
2
2
 
3
3
  use m_types
4
+
4
5
  implicit none
6
+
5
7
  private; public :: s_foo
6
8
  integer :: x
7
9
  real :: y
@@ -0,0 +1,27 @@
1
+ module m_test
2
+
3
+ use m_types
4
+
5
+ implicit none
6
+
7
+ private; public :: s_foo
8
+ integer :: x
9
+ real :: y
10
+
11
+ contains
12
+ subroutine s_foo(a, b)
13
+
14
+ integer, intent(in) :: a, b
15
+
16
+ if (a == b)then
17
+ x = a + b
18
+ else
19
+ x = a - b
20
+ end if
21
+ do i = 1, n
22
+ y = y + x
23
+ end do
24
+
25
+ end subroutine s_foo
26
+
27
+ end module m_test
@@ -1,12 +0,0 @@
1
- SUBROUTINE s_test()
2
- INTEGER :: i
3
-
4
-
5
-
6
- INTEGER :: j
7
- !$acc parallel loop
8
-
9
- DO i=1,n
10
- x(i)=0
11
- END DO
12
- END SUBROUTINE s_test
@@ -1,8 +0,0 @@
1
- SUBROUTINE s_test()
2
- #:call GPU_HOST_DATA(use_device_addr='[buff]')
3
- CALL MPI_Send(buff,n,mpi_p,dst,tag,comm,ierr)
4
- DO i=1,n
5
- x(i)=y(i)
6
- END DO
7
- #:endcall GPU_HOST_DATA
8
- END SUBROUTINE s_test
@@ -1,14 +0,0 @@
1
- SUBROUTINE s_test()
2
- INTEGER :: i,j,k
3
- #if defined(MFC_OpenACC)
4
- !$acc parallel loop collapse(3)
5
- DO k=0,p
6
- DO j=0,n
7
- DO i=0,m
8
- x(i,j,k)=y(i,j,k)*z(i,j,k)
9
- END DO
10
- END DO
11
- END DO
12
- !$acc end parallel loop
13
- #endif
14
- END SUBROUTINE s_test
@@ -1,26 +0,0 @@
1
- #:include 'macros.fpp'
2
- MODULE m_fypp_test
3
- IMPLICIT NONE
4
- CONTAINS
5
- SUBROUTINE s_test()
6
- #:if defined('MFC_OpenACC')
7
- $:GPU_PARALLEL_LOOP(collapse=3)
8
- DO k=0,p
9
- DO j=0,n
10
- DO i=0,m
11
- x(i,j,k)=0.0_wp
12
- END DO
13
- END DO
14
- END DO
15
- $:END_GPU_PARALLEL_LOOP()
16
- #:else
17
- DO k=0,p
18
- DO j=0,n
19
- DO i=0,m
20
- x(i,j,k)=0.0_wp
21
- END DO
22
- END DO
23
- END DO
24
- #:endif
25
- END SUBROUTINE s_test
26
- END MODULE m_fypp_test
@@ -1,19 +0,0 @@
1
- MODULE m_test
2
- USE m_types
3
- IMPLICIT NONE
4
- private;public :: s_foo
5
- INTEGER::x
6
- REAL :: y
7
- CONTAINS
8
- SUBROUTINE s_foo(a,b)
9
- INTEGER,INTENT(IN)::a,b
10
- IF(a==b)THEN
11
- x=a+b
12
- ELSE
13
- x=a-b
14
- END IF
15
- DO i=1,n
16
- y=y+x
17
- END DO
18
- END SUBROUTINE s_foo
19
- END MODULE m_test
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes