<commit_before>// +build darwin freebsd linux openbsd netbsd dragonfly

package libedit

import (
	"errors"
	"fmt"
	"io"
	"os"
	"syscall"
	"unsafe"
)

// #cgo openbsd netbsd freebsd dragonfly darwin LDFLAGS: -ledit
// #cgo openbsd netbsd freebsd dragonfly darwin CPPFLAGS: -Ishim
// #cgo linux LDFLAGS: -lncurses
// #cgo linux CFLAGS: -Wno-unused-result
// #cgo linux CPPFLAGS: -Isrc -Isrc/c-libedit -Isrc/c-libedit/editline -Isrc/c-libedit/linux-build
//
// #include <stdlib.h>
// #include <stdio.h>
// #include <unistd.h>
// #include <limits.h>
//
// #include <histedit.h>
// #include "c_editline.h"
import "C"

type state struct {
	el              *C.EditLine
	h               *C.History
	cIn, cOut, cErr *C.FILE
	inf, outf, errf *os.File
	promptGenLeft   LeftPromptGenerator
	promptGenRight  RightPromptGenerator
	cPromptLeft     *C.char
	cPromptRight    *C.char
	completer       CompletionGenerator
	histFile        *C.char
	autoSaveHistory bool
}

var editors []state

var errUnknown = errors.New("unknown error")

func Init(appName string) (EditLine, error) {
	return InitFiles(appName, os.Stdin, os.Stdout, os.Stderr)
}

func InitFiles(appName string, inf, outf, errf *os.File) (e EditLine, err error) {
	var inFile, outFile, errFile *C.FILE
	defer func() {
		if err == nil {
			return
		}
		if inFile != nil {
			C.fclose(inFile)
		}
		if outFile != nil {
			C.fclose(outFile)
		}
		if errFile != nil {
			C.fclose(errFile)
		}
	}()

	inFile, err = C.fdopen(C.dup(C.int(inf.Fd())), C.go_libedit_mode_read)
	if err != nil {
		return -1, fmt.Errorf("fdopen(inf): %v", err)
	}
	outFile, err = C.fdopen(C.dup(C.int(outf.Fd())), C.go_libedit_mode_write)
	if err != nil {
		return -1, fmt.Errorf("fdopen(outf): %v", err)
	}
	errFile, err = C.fdopen(C.dup(C.int(errf.Fd())), C.go_libedit_mode_write)
	if err != nil {
		return -1, fmt.Errorf("fdopen(errf): %v", err)
	}
	cAppName := C.CString(appName)
	defer C.free(unsafe.Pointer(cAppName))
	el, err := C.go_libedit_init(cAppName, inFile, outFile, errFile)
	if el == nil || err != nil {
		if err == nil {
			err = errUnknown
		}
		return -1, fmt.Errorf("el_init: %v", err)
	}
<commit_msg>Avoid failing if ~/.editrc does not exist.<commit_after>// +build darwin freebsd linux openbsd netbsd dragonfly

package libedit

import (
	"errors"
	"fmt"
	"io"
	"os"
	"syscall"
	"unsafe"
)

// #cgo openbsd netbsd freebsd dragonfly darwin LDFLAGS: -ledit
// #cgo openbsd netbsd freebsd dragonfly darwin CPPFLAGS: -Ishim
// #cgo linux LDFLAGS: -lncurses
// #cgo linux CFLAGS: -Wno-unused-result
// #cgo linux CPPFLAGS: -Isrc -Isrc/c-libedit -Isrc/c-libedit/editline -Isrc/c-libedit/linux-build
//
// #include <stdlib.h>
// #include <stdio.h>
// #include <unistd.h>
// #include <limits.h>
//
// #include <histedit.h>
// #include "c_editline.h"
import "C"

type state struct {
	el              *C.EditLine
	h               *C.History
	cIn, cOut, cErr *C.FILE
	inf, outf, errf *os.File
	promptGenLeft   LeftPromptGenerator
	promptGenRight  RightPromptGenerator
	cPromptLeft     *C.char
	cPromptRight    *C.char
	completer       CompletionGenerator
	histFile        *C.char
	autoSaveHistory bool
}

var editors []state

var errUnknown = errors.New("unknown error")

func Init(appName string) (EditLine, error) {
	return InitFiles(appName, os.Stdin, os.Stdout, os.Stderr)
}

func InitFiles(appName string, inf, outf, errf *os.File) (e EditLine, err error) {
	var inFile, outFile, errFile *C.FILE
	defer func() {
		if err == nil {
			return
		}
		if inFile != nil {
			C.fclose(inFile)
		}
		if outFile != nil {
			C.fclose(outFile)
		}
		if errFile != nil {
			C.fclose(errFile)
		}
	}()

	inFile, err = C.fdopen(C.dup(C.int(inf.Fd())), C.go_libedit_mode_read)
	if err != nil {
		return -1, fmt.Errorf("fdopen(inf): %v", err)
	}
	outFile, err = C.fdopen(C.dup(C.int(outf.Fd())), C.go_libedit_mode_write)
	if err != nil {
		return -1, fmt.Errorf("fdopen(outf): %v", err)
	}
	errFile, err = C.fdopen(C.dup(C.int(errf.Fd())), C.go_libedit_mode_write)
	if err != nil {
		return -1, fmt.Errorf("fdopen(errf): %v", err)
	}
	cAppName := C.CString(appName)
	defer C.free(unsafe.Pointer(cAppName))
	el, err := C.go_libedit_init(cAppName, inFile, outFile, errFile)
	// If the settings file did not exist, ignore the error.
	if err == syscall.ENOENT {
		err = nil
	}
	if el == nil || err != nil {
		if err == nil {
			err = errUnknown
		}
		return -1, fmt.Errorf("el_init: %v", err)
	}

{'fraction_non_alphanumeric': 0.1523809523809524, 'fraction_numerical': 0.0018140589569160999, 'mean_word_length': 3.2950340798442066, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, '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': '5652503', 'n_tokens_mistral': 1891, 'n_tokens_neox': 1789, 'n_words': 427}