<commit_before>// This is free and unencumbered software released into the public
// domain.  For more information, see <http://unlicense.org> or the
// accompanying UNLICENSE file.

package commands

import (
	"fmt"
	"go/token"

	"github.com/nelsam/gxui"
	"github.com/nelsam/gxui/themes/basic"
	"github.com/nelsam/vidar/commander/bind"
	"github.com/nelsam/vidar/editor"
)

type EditorOpener interface {
	Open(string, token.Position) (editor *editor.CodeEditor, existed bool)
}

type Opener interface {
	Open(string, token.Position)
}

// A FileBinder is a type that registers a list of commands
// on file open.
type FileBinder interface {
	// FileBindables returns the bindables that should be registered
	// for the given file.
	FileBindables(path string) []bind.Bindable
}

// A Binder is a type which can bind bindables
type Binder interface {
	Push(...bind.Bindable)
	Pop()
}

type FileOpener struct {
	driver gxui.Driver
	theme  *basic.Theme

	file   *FSLocator
	cursor token.Position
	input  <-chan gxui.Focusable

	binder  Binder
	opener  EditorOpener
	openers []Opener

	hooks []FileBinder
}

func NewFileOpener(driver gxui.Driver, theme *basic.Theme) *FileOpener {
	fileOpener := new(FileOpener)
	fileOpener.Init(driver, theme)
	return fileOpener
}

func (f *FileOpener) Init(driver gxui.Driver, theme *basic.Theme) {
	f.driver = driver
	f.theme = theme
	f.file = NewFSLocator(driver, theme)
}

func (f *FileOpener) SetLocation(filepath string, position token.Position) {
	f.file.SetPath(filepath)
	f.cursor = position
}

func (f *FileOpener) Name() string {
	return "open-file"
}

func (f *FileOpener) Menu() string {
	return "File"
}

func (f *FileOpener) Start(control gxui.Control) gxui.Control {
	f.file.loadEditorDir(control)
	input := make(chan gxui.Focusable, 1)
	f.input = input
	input <- f.file
	close(input)
	return nil
}

func (f *FileOpener) Next() gxui.Focusable {
	return <-f.input
}

func (f *FileOpener) Reset() {
	f.binder = nil
	f.opener = nil
	f.openers = nil
}

func (f *FileOpener) Store(elem interface{}) bind.Status {
	switch src := elem.(type) {
	case EditorOpener:
		f.opener = src
	case Opener:
		f.openers = append(f.openers, src)
	case Binder:
		f.binder = src
	}
	if f.opener != nil && f.binder != nil {
		return bind.Executing
	}
	return bind.Waiting
}

func (f *FileOpener) Exec() error {
	path := f.file.Path()<commit_msg>Reset the file opener's position during Reset<commit_after>// This is free and unencumbered software released into the public
// domain.  For more information, see <http://unlicense.org> or the
// accompanying UNLICENSE file.

package commands

import (
	"fmt"
	"go/token"

	"github.com/nelsam/gxui"
	"github.com/nelsam/gxui/themes/basic"
	"github.com/nelsam/vidar/commander/bind"
	"github.com/nelsam/vidar/editor"
)

type EditorOpener interface {
	Open(string, token.Position) (editor *editor.CodeEditor, existed bool)
}

type Opener interface {
	Open(string, token.Position)
}

// A FileBinder is a type that registers a list of commands
// on file open.
type FileBinder interface {
	// FileBindables returns the bindables that should be registered
	// for the given file.
	FileBindables(path string) []bind.Bindable
}

// A Binder is a type which can bind bindables
type Binder interface {
	Push(...bind.Bindable)
	Pop()
}

type FileOpener struct {
	driver gxui.Driver
	theme  *basic.Theme

	file   *FSLocator
	cursor token.Position
	input  <-chan gxui.Focusable

	binder  Binder
	opener  EditorOpener
	openers []Opener

	hooks []FileBinder
}

func NewFileOpener(driver gxui.Driver, theme *basic.Theme) *FileOpener {
	fileOpener := new(FileOpener)
	fileOpener.Init(driver, theme)
	return fileOpener
}

func (f *FileOpener) Init(driver gxui.Driver, theme *basic.Theme) {
	f.driver = driver
	f.theme = theme
	f.file = NewFSLocator(driver, theme)
}

func (f *FileOpener) SetLocation(filepath string, position token.Position) {
	f.file.SetPath(filepath)
	f.cursor = position
}

func (f *FileOpener) Name() string {
	return "open-file"
}

func (f *FileOpener) Menu() string {
	return "File"
}

func (f *FileOpener) Start(control gxui.Control) gxui.Control {
	f.file.loadEditorDir(control)
	input := make(chan gxui.Focusable, 1)
	f.input = input
	input <- f.file
	close(input)
	return nil
}

func (f *FileOpener) Next() gxui.Focusable {
	return <-f.input
}

func (f *FileOpener) Reset() {
	f.binder = nil
	f.opener = nil
	f.openers = nil
	f.cursor = token.Position{}
}

func (f *FileOpener) Store(elem interface{}) bind.Status {
	switch src := elem.(type) {
	case EditorOpener:
		f.opener = src
	case Opener:
		f.openers = append(f.openers, src)
	case Binder:
		f.binder = src
	}
	if f.opener != nil && f.binder != nil {
		return bind.Executing
	}
	return bind.Waiting
}

func (f *FileOpener) Exec() error {
	path := f.file.Path()
{'fraction_non_alphanumeric': 0.12017525558105571, 'fraction_numerical': 0.00041727519298977677, 'mean_word_length': 3.967875647668394, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6238209', 'n_tokens_mistral': 1776, 'n_tokens_neox': 1757, 'n_words': 479}