@@ -23,6 +23,7 @@ defmodule Gradient.ElixirFmt do
2323 alias Gradient.ElixirType
2424 alias Gradient.ElixirExpr
2525 alias Gradient.Types
26+ alias Gradient.Anno
2627
2728 @ type colors_opts ( ) :: [
2829 use_colors: boolean ( ) ,
@@ -311,54 +312,81 @@ defmodule Gradient.ElixirFmt do
311312 context
312313 |> Enum . with_index ( 1 )
313314 |> filter_context ( anno , 2 )
314- |> underscore_line ( anno , opts )
315+ |> maybe_underscore_lines ( anno , opts )
315316 |> Enum . join ( "\n " )
316317 end
317318
318- def filter_context ( lines , loc , ctx_size \\ 1 ) do
319- line = :erl_anno . line ( loc )
320- range = ( line - ctx_size ) .. ( line + ctx_size )
319+ def filter_context ( lines , anno , ctx_size \\ 1 ) do
320+ line = Anno . line ( anno )
321+ end_line = Anno . end_line ( anno )
322+ range = ( line - ctx_size ) .. ( end_line + ctx_size )
321323
322324 Enum . filter ( lines , fn { _ , number } -> number in range end )
323325 end
324326
325- def end_location ( anno ) when is_list ( anno ) do
326- Keyword . get ( anno , :end_location , :undefined )
327- end
328- def end_location ( _anno ) do
329- :undefined
330- end
331-
332- def underscore_line ( lines , anno , opts ) do
333- line = :erl_anno . line ( anno )
334- column = :erl_anno . column ( anno )
335- IO . inspect ( column , label: "COLUMN" )
336- endl = end_location ( anno )
337- IO . inspect ( endl , label: "END LOCATION" )
327+ def maybe_underscore_lines ( lines , anno , opts ) do
328+ Anno . location ( anno ) |> IO . inspect ( label: "START LOC" )
329+ Anno . end_location ( anno ) |> IO . inspect ( label: "END LOC" )
338330
339331 Enum . map ( lines , fn { str , n } ->
340- if ( n == line ) do
332+ if need_underscore? ( n , anno ) do
341333 colors = get_colors_with_default ( opts )
342- { :ok , use_colors } = Keyword . fetch ( colors , :use_colors )
343- { :ok , color } = Keyword . fetch ( colors , :underscored_line )
344- { bef , aft } = split_at_col ( str , column )
345- indent = to_string ( n ) <> " " <> bef
346-
347- [
348- indent ,
349- [
350- IO.ANSI . underline ( ) ,
351- IO.ANSI . format_fragment ( [ color , aft ] , use_colors ) ,
352- IO.ANSI . reset ( )
353- ]
354- ]
334+ underscore_line ( str , n , anno , colors )
355335 else
356- to_string ( n ) <> " " <> str
336+ [ to_string ( n ) , " " , str ]
357337 end
358338 end )
359339 end
360340
361- def split_at_col ( str , col ) when is_integer ( col ) , do: String . split_at ( str , col - 1 )
341+ def underscore_line ( str , n , anno , colors ) do
342+ { start_line , start_col } = Anno . location ( anno )
343+ { end_line , end_col } = Anno . end_location ( anno )
344+
345+ case n do
346+ l when l == start_line and l == end_line ->
347+ { prefix , str } = split_at_col ( str , start_col )
348+ { str , suffix } = split_at_col ( str , end_col - start_col )
349+ [ prefix , make_underscore ( str , colors ) , suffix ]
350+
351+ ^ start_line ->
352+ { prefix , str } = split_at_col ( str , start_col )
353+ [ prefix , make_underscore ( str , colors ) ]
354+
355+ ^ end_line ->
356+ { str , suffix } = split_at_col ( str , end_col )
357+ [ indent , str ] = separate_indent ( str )
358+ [ indent , make_underscore ( str , colors ) , suffix ]
359+
360+ _otherwise ->
361+ separate_indent ( str )
362+ end
363+ |> add_line_number ( n )
364+ end
365+
366+ def add_line_number ( iolist , n ) , do: [ to_string ( n ) , " " , iolist ]
367+
368+ def separate_indent ( str ) do
369+ trim_str = String . trim ( str )
370+ indent = gen_indent ( String . length ( str ) - String . length ( trim_str ) )
371+ [ indent , trim_str ]
372+ end
373+
374+ def gen_indent ( length ) , do: Stream . cycle ( ' ' ) |> Stream . take ( length ) |> Enum . to_list ( )
375+
376+ def make_underscore ( text , colors ) do
377+ { :ok , use_colors } = Keyword . fetch ( colors , :use_colors )
378+ { :ok , color } = Keyword . fetch ( colors , :underscored_line )
379+
380+ [
381+ IO.ANSI . underline ( ) ,
382+ IO.ANSI . format_fragment ( [ color , text ] , use_colors ) ,
383+ IO.ANSI . reset ( )
384+ ]
385+ end
386+
387+ def need_underscore? ( index , anno ) , do: index >= Anno . line ( anno ) && index <= Anno . end_line ( anno )
388+
389+ def split_at_col ( str , col ) when is_integer ( col ) , do: String . split_at ( str , col )
362390 def split_at_col ( str , _ ) , do: { "" , str }
363391
364392 def get_ex_file_path ( [ { :attribute , 1 , :file , { path , 1 } } | _ ] ) , do: { :ok , path }
0 commit comments