-
Notifications
You must be signed in to change notification settings - Fork 182
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New option --numeric to print indentation for emacs
- Loading branch information
Showing
15 changed files
with
549 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
(**************************************************************************) | ||
(* *) | ||
(* OCamlFormat *) | ||
(* *) | ||
(* Copyright (c) Facebook, Inc. and its affiliates. *) | ||
(* *) | ||
(* This source code is licensed under the MIT license found in *) | ||
(* the LICENSE file in the root directory of this source tree. *) | ||
(* *) | ||
(**************************************************************************) | ||
|
||
open Migrate_ast | ||
open Result.Monad_infix | ||
|
||
let rec loc_of_line loctree locs line = | ||
match locs with | ||
| [] -> None | ||
| (h : Location.t) :: t -> | ||
if h.loc_start.pos_lnum = line then Some h | ||
else if h.loc_start.pos_lnum <= line && line <= h.loc_end.pos_lnum then | ||
match Loc_tree.children loctree h with | ||
| [] -> Some h | ||
| children -> ( | ||
match loc_of_line loctree children line with | ||
| Some loc -> Some loc | ||
| None -> Some h ) | ||
else loc_of_line loctree t line | ||
|
||
let matching_loc loc locs locs' = | ||
match List.zip locs locs' with | ||
| Ok assoc -> ( | ||
let equal x y = Location.compare x y = 0 in | ||
match List.Assoc.find assoc ~equal loc with | ||
| Some loc -> Ok loc | ||
| None -> | ||
Error (`Msg "Cannot find matching location in formatted output.") ) | ||
| Unequal_lengths -> | ||
Error (`Msg "Cannot match pre-post formatting locations.") | ||
|
||
let indentation_of_line l = String.(length l - length (lstrip l)) | ||
|
||
let indentation_1_line ?prev (loctree, locs) (_, locs') formatted_src nlines | ||
~line = | ||
if line = nlines + 1 then Ok 0 | ||
else | ||
match loc_of_line loctree locs line with | ||
| Some loc -> ( | ||
matching_loc loc locs locs' | ||
>>= fun (loc' : Location.t) -> | ||
let line_nb = loc'.loc_start.pos_lnum - 1 in | ||
let line' = | ||
List.nth_exn (String.split_lines formatted_src) line_nb | ||
in | ||
let indent = indentation_of_line line' in | ||
match prev with | ||
| Some (prev_indent, prev_line) | ||
when indent = prev_indent || indent = 0 -> ( | ||
(* in case this is a line that is split but could fit on a single | ||
line, consecutive lines will have the same indentation, we try | ||
to infer some artificial indentation here, even though it will | ||
be squeezed together and fit on a single line when the whole | ||
file is reformatted *) | ||
match | ||
Source.infer_indent_from_prev_line (Source.create prev_line) | ||
with | ||
| Some i -> Ok (prev_indent + i) | ||
| None -> Ok indent ) | ||
| _ -> Ok indent ) | ||
| None -> Ok 0 | ||
|
||
let indentation_1_line_fallback ?prev src nlines ~line = | ||
if line = nlines + 1 then Ok 0 | ||
else | ||
let line_nb = line - 1 in | ||
let line' = List.nth_exn (String.split_lines src) line_nb in | ||
let indent = indentation_of_line line' in | ||
match prev with | ||
| Some (prev_indent, prev_line) -> ( | ||
match Source.infer_indent_from_prev_line (Source.create prev_line) with | ||
| Some i -> Ok (prev_indent + i) | ||
| None -> Ok indent ) | ||
| _ -> Ok indent | ||
|
||
type 'a parsed = {ast: 'a; source: string} | ||
|
||
let indent_from_locs fragment ~unformatted:{ast; source} | ||
~formatted:{ast= formatted_ast; source= formatted_source} ~lines | ||
~range:(low, high) = | ||
let nlines = List.length lines in | ||
let prev = | ||
Option.map | ||
(List.nth lines (low - 2)) | ||
~f:(fun line -> (indentation_of_line line, line)) | ||
in | ||
let locs = Loc_tree.of_ast fragment ast (Source.create source) in | ||
let locs' = | ||
Loc_tree.of_ast fragment formatted_ast (Source.create formatted_source) | ||
in | ||
let rec aux ?prev acc i = | ||
if i > high then Ok (List.rev acc) | ||
else | ||
indentation_1_line ?prev locs locs' formatted_source nlines ~line:i | ||
>>= fun indent -> | ||
let line = Option.value (List.nth lines (i - 1)) ~default:"" in | ||
aux ~prev:(indent, line) (indent :: acc) (i + 1) | ||
in | ||
aux ?prev [] low | ||
|
||
let indent_from_lines ~source ~lines ~range:(low, high) = | ||
let nlines = List.length lines in | ||
let prev = | ||
Option.map | ||
(List.nth lines (low - 2)) | ||
~f:(fun line -> (indentation_of_line line, line)) | ||
in | ||
let rec aux ?prev acc i = | ||
if i > high then Ok (List.rev acc) | ||
else | ||
indentation_1_line_fallback ?prev source nlines ~line:i | ||
>>= fun indent -> | ||
let line = Option.value (List.nth lines (i - 1)) ~default:"" in | ||
aux ~prev:(indent, line) (indent :: acc) (i + 1) | ||
in | ||
aux ?prev [] low |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
(**************************************************************************) | ||
(* *) | ||
(* OCamlFormat *) | ||
(* *) | ||
(* Copyright (c) Facebook, Inc. and its affiliates. *) | ||
(* *) | ||
(* This source code is licensed under the MIT license found in *) | ||
(* the LICENSE file in the root directory of this source tree. *) | ||
(* *) | ||
(**************************************************************************) | ||
|
||
type 'a parsed = {ast: 'a; source: string} | ||
|
||
val indent_from_locs : | ||
'a Migrate_ast.Mapper.fragment | ||
-> unformatted:'a parsed | ||
-> formatted:'a parsed | ||
-> lines:string list | ||
-> range:int * int | ||
-> (int list, [`Msg of string]) Result.t | ||
|
||
val indent_from_lines : | ||
source:string | ||
-> lines:string list | ||
-> range:int * int | ||
-> (int list, [`Msg of string]) Result.t |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.