@@ -3,10 +3,12 @@ package language
33import (
44 "context"
55 "fmt"
6+ "io"
67 "os"
78 "path/filepath"
89 "strings"
910
11+ "github.com/wakatime/wakatime-cli/pkg/file"
1012 "github.com/wakatime/wakatime-cli/pkg/heartbeat"
1113 "github.com/wakatime/wakatime-cli/pkg/log"
1214)
@@ -72,11 +74,7 @@ func Detect(ctx context.Context, fp string, guessLanguage bool) (heartbeat.Langu
7274 language = languageChroma
7375 }
7476
75- languageVim , weightVim , okVim := detectVimModeline (fp )
76- if okVim && weightVim > weight {
77- // use language from vim modeline, if weight is higher
78- language = languageVim
79- }
77+ language = detectOverrideCases (ctx , fp , language , weight )
8078
8179 if language == heartbeat .LanguageUnknown {
8280 return heartbeat .LanguageUnknown , fmt .Errorf ("could not detect the language of file %q" , fp )
@@ -131,6 +129,54 @@ func detectSpecialCases(ctx context.Context, fp string) (heartbeat.Language, boo
131129 return heartbeat .LanguageUnknown , false
132130}
133131
132+ // detectOverrideCases overwrides the Chroma detected language based on file contents.
133+ func detectOverrideCases (ctx context.Context , fp string , language heartbeat.Language , weight float32 ) heartbeat.Language {
134+ logger := log .Extract (ctx )
135+
136+ f , err := file .OpenNoLock (fp ) // nolint:gosec
137+ if err != nil {
138+ logger .Debugf ("failed to open file: %s" , err )
139+ return language
140+ }
141+
142+ defer func () {
143+ if err := f .Close (); err != nil {
144+ logger .Debugf ("failed to close file: %s" , err )
145+ }
146+ }()
147+
148+ buf := make ([]byte , 4096 )
149+ c , err := f .Read (buf )
150+ if err != nil && err != io .EOF {
151+ logger .Debugf ("failed to open file: %s" , err )
152+ return language
153+ }
154+
155+ text := string (buf [:c ])
156+
157+ languageVim , weightVim , okVim := detectVimModeline (text )
158+ if okVim && weightVim > weight {
159+ language = languageVim
160+ }
161+
162+ _ , file := filepath .Split (fp )
163+ ext := strings .ToLower (filepath .Ext (file ))
164+
165+ if ext == ".fs" {
166+ languageForth , weightForth , okForth := detectForthFromContents (text )
167+ if okForth && weightForth >= weight {
168+ language = languageForth
169+ }
170+
171+ languageFSharp , weightFSharp , okFSharp := detectFSharpFromContents (text )
172+ if okFSharp && weightFSharp >= weight {
173+ language = languageFSharp
174+ }
175+ }
176+
177+ return language
178+ }
179+
134180// folderContainsCFiles returns true, if filder contains c files.
135181func folderContainsCFiles (ctx context.Context , dir string ) bool {
136182 if dir == "" {
0 commit comments