Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,13 @@ func main() {
"start as an MCP (Model Context Protocol) server over stdio",
)

flags.StringVar(
&processor.LanguagesFile,
"languages-file",
"",
"path to a custom languages.json file to augment or override built-in languages",
)

// If invoked in the format of "scc completion --shell [name of shell]", generate command line completions instead.
// With the --shell option, unintentionally triggering shell completions should be highly unlikely.
args := os.Args
Expand Down
19 changes: 19 additions & 0 deletions processor/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package processor

import (
"encoding/json"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -146,6 +147,9 @@ var RemapUnknown = ""
// RemapAll allows remapping of all files with a string to search the content for
var RemapAll = ""

// LanguagesFile is the path to a custom languages.json file
var LanguagesFile = ""

type remapRule struct {
pattern []byte
language string
Expand Down Expand Up @@ -324,6 +328,21 @@ func ConfigureLazy(lazy bool) {
// Needs to be called at least once in order for anything to actually happen
func ProcessConstants() {
startTime := makeTimestampNano()
if LanguagesFile != "" {
data, err := os.ReadFile(LanguagesFile)
if err != nil {
printError("failed to read languages file: " + err.Error())
} else {
var customLanguages map[string]Language
if err := json.Unmarshal(data, &customLanguages); err != nil {
printError("failed to parse languages file: " + err.Error())
} else {
for name, lang := range customLanguages {
languageDatabase[name] = lang
}
}
}
}
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think... this needs to come after the load, because we want to allow overriding of existing config. Part of the point being someone may want to count docstrings as code for example.

This also would allow testing differences between configs a little more easily.

for name, value := range languageDatabase {
for _, ext := range value.Extensions {
ExtensionToLanguage[ext] = append(ExtensionToLanguage[ext], name)
Expand Down
24 changes: 24 additions & 0 deletions processor/processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
package processor

import (
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
)
Expand Down Expand Up @@ -154,3 +157,24 @@ func TestSetupCountAsMultiple(t *testing.T) {

CountAs = ""
}
func TestLanguagesFileIsValidJSON(t *testing.T) {
data, err := os.ReadFile("../languages.json")
if err != nil {
t.Fatal("failed to read languages.json", err)
}

var languages map[string]Language
if err := json.Unmarshal(data, &languages); err != nil {
t.Error("languages.json is not valid JSON", err)
}
}

func TestLanguagesFileInvalidJSON(t *testing.T) {
dir, _ := os.MkdirTemp("", "test-languages")
langFile := filepath.Join(dir, "languages.json")
_ = os.WriteFile(langFile, []byte(`not valid json`), 0644)

LanguagesFile = langFile
// should not panic
ProcessConstants()
}
Loading