@@ -551,6 +551,35 @@ func (m model) sortOptionsRender() string {
551
551
return sortOptionsModalBorderStyle (panel .sortOptions .height , panel .sortOptions .width , bottomBorder ).Render (sortOptionsContent )
552
552
}
553
553
554
+ func readFileContent (filepath string , maxLineLength int , previewLine int ) (string , error ) {
555
+ // String builder is much better for efficiency
556
+ // See - https://stackoverflow.com/questions/1760757/how-to-efficiently-concatenate-strings-in-go/47798475#47798475
557
+ var resultBuilder strings.Builder
558
+ file , err := os .Open (filepath )
559
+ if err != nil {
560
+ return resultBuilder .String (), err
561
+ }
562
+ defer file .Close ()
563
+
564
+ scanner := bufio .NewScanner (file )
565
+ lineCount := 0
566
+ for scanner .Scan () {
567
+ line := scanner .Text ()
568
+ if len (line ) > maxLineLength {
569
+ line = line [:maxLineLength ]
570
+ }
571
+ // This is critical to avoid layout break, removes non Printable ASCII control characters.
572
+ line = makePrintable (line )
573
+ resultBuilder .WriteString (line + "\n " )
574
+ lineCount ++
575
+ if previewLine > 0 && lineCount >= previewLine {
576
+ break
577
+ }
578
+ }
579
+ // returns the first non-EOF error that was encountered by the [Scanner]
580
+ return resultBuilder .String (), scanner .Err ()
581
+ }
582
+
554
583
func (m model ) filePreviewPanelRender () string {
555
584
previewLine := m .mainPanelHeight + 2
556
585
m .fileModel .filePreview .width += m .fullWidth - Config .SidebarWidth - m .fileModel .filePreview .width - ((m .fileModel .width + 2 ) * len (m .fileModel .filePanels )) - 2
@@ -630,86 +659,42 @@ func (m model) filePreviewPanelRender() string {
630
659
}
631
660
632
661
format := lexers .Match (filepath .Base (itemPath ))
633
- if format != nil {
634
- var codeHighlight string
635
- var err error
636
- var fileContent string
637
- file , err := os .Open (itemPath )
662
+
663
+ if format == nil {
664
+ isText , err := isTextFile (itemPath )
638
665
if err != nil {
639
- outPutLog (err )
640
- return box .Render ("\n --- " + icon .Error + " Error open file ---" )
666
+ outPutLog ("Error while checking text file" , err )
667
+ return box .Render ("\n --- " + icon .Error + " Error get file info ---" )
668
+ } else if ! isText {
669
+ return box .Render ("\n --- " + icon .Error + " Unsupported formats ---" )
641
670
}
642
- defer file .Close ()
643
-
644
- scanner := bufio .NewScanner (file )
645
- lineCount := 0
671
+ }
646
672
647
- maxLineLength := m .fileModel .width + 20
648
- for scanner .Scan () {
649
- line := scanner .Text ()
650
- if len (line ) > maxLineLength {
651
- line = line [:maxLineLength ]
652
- }
653
- fileContent += line + "\n "
654
- lineCount ++
655
- if previewLine > 0 && lineCount >= previewLine {
656
- break
657
- }
658
- }
673
+ // At this point either format is not nil, or we can read the file
674
+ fileContent , err := readFileContent (itemPath , m .fileModel .width + 20 , previewLine )
675
+ if err != nil {
676
+ outPutLog (err )
677
+ return box .Render ("\n --- " + icon .Error + " Error open file ---" )
678
+ }
659
679
660
- if Config .TransparentBackground {
661
- codeHighlight , err = ansichroma .HightlightString (fileContent , format .Config ().Name , theme .CodeSyntaxHighlightTheme , "" )
662
- } else {
663
- codeHighlight , err = ansichroma .HightlightString (fileContent , format .Config ().Name , theme .CodeSyntaxHighlightTheme , theme .FilePanelBG )
680
+ // We know the format of file, and we can apply syntax highlighting
681
+ if format != nil {
682
+ background := ""
683
+ if ! Config .TransparentBackground {
684
+ background = theme .FilePanelBG
664
685
}
686
+ fileContent , err = ansichroma .HightlightString (fileContent , format .Config ().Name , theme .CodeSyntaxHighlightTheme , background )
665
687
if err != nil {
666
688
outPutLog ("Error render code highlight" , err )
667
689
return box .Render ("\n --- " + icon .Error + " Error render code highlight ---" )
668
690
}
669
- if codeHighlight == "" {
670
- return box .Render ("\n --- empty ---" )
671
- }
672
-
673
- codeHighlight = checkAndTruncateLineLengths (codeHighlight , m .fileModel .filePreview .width )
674
-
675
- return box .Render (codeHighlight )
676
- } else {
677
- textFile , err := isTextFile (itemPath )
678
- if err != nil {
679
- outPutLog ("Error check text file" , err )
680
- }
681
- if textFile {
682
- var fileContent string
683
- file , err := os .Open (itemPath )
684
- if err != nil {
685
- outPutLog (err )
686
- return box .Render ("\n --- " + icon .Error + " Error open file ---" )
687
- }
688
- defer file .Close ()
689
-
690
- scanner := bufio .NewScanner (file )
691
- lineCount := 0
692
-
693
- for scanner .Scan () {
694
- fileContent += scanner .Text () + "\n "
695
- lineCount ++
696
- if previewLine > 0 && lineCount >= previewLine {
697
- break
698
- }
699
- }
700
-
701
- if err := scanner .Err (); err != nil {
702
- outPutLog (err )
703
- return box .Render ("\n --- " + icon .Error + " Error open file ---" )
704
- }
705
-
706
- textContent := checkAndTruncateLineLengths (fileContent , m .fileModel .filePreview .width )
707
-
708
- return box .Render (textContent )
709
- }
710
691
}
711
692
712
- return box .Render ("\n --- " + icon .Error + " Unsupported formats ---" )
693
+ if fileContent == "" {
694
+ return box .Render ("\n --- empty ---" )
695
+ }
696
+ fileContent = checkAndTruncateLineLengths (fileContent , m .fileModel .filePreview .width )
697
+ return box .Render (fileContent )
713
698
}
714
699
715
700
func (m model ) commandLineInputBoxRender () string {
0 commit comments