package inputrc
import (
"bytes"
"errors"
"fmt"
"io"
"os"
"os/user"
"path/filepath"
"runtime"
"strings"
"unicode"
)
func Parse (r io .Reader , h Handler , opts ...Option ) error {
return New (opts ...).Parse (r , h )
}
func ParseBytes (buf []byte , h Handler , opts ...Option ) error {
return New (opts ...).Parse (bytes .NewReader (buf ), h )
}
func ParseFile (name string , h Handler , opts ...Option ) error {
f , err := os .Open (name )
if err != nil {
return err
}
defer f .Close ()
return New (append (opts , WithName (name ))...).Parse (f , h )
}
func UserDefault (u *user .User , cfg *Config , opts ...Option ) error {
var files []string
if name := os .Getenv ("INPUTRC" ); name != "" {
files = append (files , name )
}
if u != nil {
name := ".inputrc"
if runtime .GOOS == "windows" {
name = "_inputrc"
}
files = append (files , filepath .Join (u .HomeDir , name ))
}
if runtime .GOOS != "windows" {
files = append (files , "/etc/inputrc" )
}
for _ , name := range files {
buf , err := cfg .ReadFile (name )
switch {
case err != nil && errors .Is (err , os .ErrNotExist ):
continue
case err != nil :
return err
}
return ParseBytes (buf , cfg , append (opts , WithName (name ))...)
}
return nil
}
func Unescape (s string ) string {
r := []rune (s )
return unescapeRunes (r , 0 , len (r ))
}
func Escape (s string ) string {
return escape (s , map [rune ]string {
Delete : `\C-?` ,
Return : `\C-M` ,
})
}
func EscapeMacro (s string ) string {
return escape (s , map [rune ]string {
Delete : `\d` ,
Return : `\r` ,
})
}
func escape(s string , m map [rune ]string ) string {
var v []string
for _ , c := range s {
switch c {
case Alert :
v = append (v , `\a` )
case Backspace :
v = append (v , `\b` )
case Delete :
v = append (v , m [Delete ])
case Esc :
v = append (v , `\e` )
case Formfeed :
v = append (v , `\f` )
case Newline :
v = append (v , `\n` )
case Return :
v = append (v , m [Return ])
case Tab :
v = append (v , `\t` )
case Vertical :
v = append (v , `\v` )
case '\\' , '"' , '\'' :
v = append (v , `\` +string (c ))
default :
var s string
if IsControl (c ) {
s += `\C-`
c = Decontrol (c )
}
if IsMeta (c ) {
s += `\M-`
c = Demeta (c )
}
if unicode .IsPrint (c ) {
s += string (c )
} else {
s += fmt .Sprintf (`\x%2x` , c )
}
v = append (v , s )
}
}
return strings .Join (v , "" )
}
func Encontrol (c rune ) rune {
return unicode .ToUpper (c ) & Control
}
func Decontrol (c rune ) rune {
return unicode .ToUpper (c | 0x40 )
}
func IsControl (c rune ) bool {
return c < Space && c &Meta == 0
}
func Enmeta (c rune ) rune {
return c | Meta
}
func Demeta (c rune ) rune {
return c & ^Meta
}
func IsMeta (c rune ) bool {
return c > Delete && c <= 0xff
}
type Error string
const (
ErrBindMissingClosingQuote Error = `bind missing closing quote`
ErrMissingColon Error = "missing :"
ErrMacroMissingClosingQuote Error = `macro missing closing quote`
ErrInvalidKeymap Error = "invalid keymap"
ErrInvalidEditingMode Error = "invalid editing mode"
ErrElseWithoutMatchingIf Error = "$else without matching $if"
ErrEndifWithoutMatchingIf Error = "$endif without matching $if"
ErrUnknownModifier Error = "unknown modifier"
)
func (err Error ) Error () string {
return string (err )
}
const (
Control rune = 0x1f
Meta rune = 0x80
Esc rune = 0x1b
Delete rune = 0x7f
Alert rune = '\a'
Backspace rune = '\b'
Formfeed rune = '\f'
Newline rune = '\n'
Return rune = '\r'
Tab rune = '\t'
Vertical rune = '\v'
Space rune = ' '
)
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .