ast

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 26, 2025 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Copyright 2025 The Hulo Authors. All rights reserved. Use of this source code is governed by a MIT-style license that can be found in the LICENSE file.

Package ast declares the types used to represent syntax trees for bash scripts. Bash reference: https://www.gnu.org/software/bash/manual/bash.html

Copyright 2025 The Hulo Authors. All rights reserved. Use of this source code is governed by a MIT-style license that can be found in the LICENSE file.

Copyright 2025 The Hulo Authors. All rights reserved. Use of this source code is governed by a MIT-style license that can be found in the LICENSE file.

Copyright 2025 The Hulo Authors. All rights reserved. Use of this source code is governed by a MIT-style license that can be found in the LICENSE file.

Index

Constants

View Source
const (
	// ExpOperatorU converts lowercase alphabetic characters to uppercase.
	ExpOperatorU = "U"

	// ExpOperatoru converts the first character to uppercase if alphabetic.
	ExpOperatoru = "u"

	// ExpOperatorL converts uppercase alphabetic characters to lowercase.
	ExpOperatorL = "L"

	// ExpOperatorQ quotes the value in a format that can be reused as input.
	ExpOperatorQ = "Q"

	// ExpOperatorE expands backslash escape sequences.
	ExpOperatorE = "E"

	// ExpOperatorP expands the value as a prompt string.
	ExpOperatorP = "P"

	// ExpOperatorA produces an assignment statement that recreates the parameter.
	ExpOperatorA = "A"

	// ExpOperatorK produces a quoted version of the value.
	ExpOperatorK = "K"

	// ExpOperatora produces flag values representing parameter attributes.
	ExpOperatora = "a"

	// ExpOperatork expands keys and values to separate words.
	ExpOperatork = "k"
)

Variables

This section is empty.

Functions

func Inspect

func Inspect(node Node, f func(Node) bool)

func Print

func Print(node Node)

Print prints the AST to the standard output.

func String

func String(node Node) string

String returns the AST as a string.

func Walk

func Walk(v Visitor, node Node)

func Write added in v0.2.0

func Write(node Node, output io.Writer)

Write writes the AST to the output.

Types

type ArithEvalExpr

type ArithEvalExpr struct {
	Lparen token.Pos // position of "(("
	X      Expr      // arithmetic expression
	Rparen token.Pos // position of "))"
}

An ArithEvalExpr node represents an arithmetic evaluation expression. e.g., ((a + b)) or ((i++))

func (*ArithEvalExpr) End

func (x *ArithEvalExpr) End() token.Pos

func (*ArithEvalExpr) Pos

func (x *ArithEvalExpr) Pos() token.Pos

type ArithExpr

type ArithExpr struct {
	Dollar token.Pos // position of "$"
	Lparen token.Pos // position of "(("
	X      Expr      // arithmetic expression
	Rparen token.Pos // position of "))"
}

An ArithExpr node represents an arithmetic expansion expression. e.g., $((a + b))

func (*ArithExpr) End

func (x *ArithExpr) End() token.Pos

func (*ArithExpr) Pos

func (x *ArithExpr) Pos() token.Pos

type ArrExpr

type ArrExpr struct {
	Lparen token.Pos // position of "("
	Vars   []Expr    // array elements
	Rparen token.Pos // position of ")"
}

An ArrExpr node represents an array expression. e.g., (item1 item2 item3)

func (*ArrExpr) End

func (x *ArrExpr) End() token.Pos

func (*ArrExpr) Pos

func (x *ArrExpr) Pos() token.Pos

type ArrayIndexExp

type ArrayIndexExp struct {
	Bitnot   token.Pos   // position of '!'
	Lbracket token.Pos   // position of '['
	Tok      token.Token // Token.AT or Token.MUL
	TokPos   token.Pos   // position of token
	Rbracket token.Pos   // position of ']'
}

ArrayIndexExp represents an array index expansion. e.g., ${!var[*]} or ${!var[@]}

type AssignStmt

type AssignStmt struct {
	Local  token.Pos // position of "local" keyword, if any
	Lhs    Expr      // left-hand side (variable name)
	Assign token.Pos // position of "="
	Rhs    Expr      // right-hand side (value)
}

An AssignStmt node represents a variable assignment. e.g., local var=value or var=value

func (*AssignStmt) End

func (s *AssignStmt) End() token.Pos

End position methods for statements

func (*AssignStmt) Pos

func (s *AssignStmt) Pos() token.Pos

Position methods for statements

type BinaryExpr

type BinaryExpr struct {
	Compress bool        // true if spaces are compressed around operator
	X        Expr        // left operand
	OpPos    token.Pos   // position of Op
	Op       token.Token // operator (EQ, NE, LT, GT, etc.)
	Y        Expr        // right operand
}

A BinaryExpr node represents a binary expression. e.g., $a -eq $b or "string" = "other"

func BinaryExpression added in v0.2.0

func BinaryExpression(x Expr, op token.Token, y Expr) *BinaryExpr

func (*BinaryExpr) End

func (x *BinaryExpr) End() token.Pos

End position methods for expressions

func (*BinaryExpr) Pos

func (x *BinaryExpr) Pos() token.Pos

Position methods for expressions

type BlockStmt

type BlockStmt struct {
	Tok     token.Token // Token.NONE | Token.LBRACE
	Opening token.Pos   // position of "{"
	List    []Stmt      // list of statements
	Closing token.Pos   // position of "}"
}

A BlockStmt node represents a braced statement list. e.g., { command1; command2; }

func (*BlockStmt) End

func (s *BlockStmt) End() token.Pos

func (*BlockStmt) Pos

func (s *BlockStmt) Pos() token.Pos

type CaseClause

type CaseClause struct {
	Conds  []Expr     // pattern expressions
	Rparen token.Pos  // position of ")"
	Body   *BlockStmt // commands to execute
	Semi   token.Pos  // position of ";;"
}

A CaseClause represents a single case pattern and its commands.

type CaseConversionExp

type CaseConversionExp struct {
	FirstChar bool // true for single character conversion
	ToUpper   bool // true for uppercase conversion
}

CaseConversionExp represents a case conversion expansion. e.g., ${var,} or ${var^} or ${var,,} or ${var^^}

type CaseStmt

type CaseStmt struct {
	Case     token.Pos     // position of "case"
	X        Expr          // expression to match
	In       token.Pos     // position of "in"
	Patterns []*CaseClause // list of case clauses
	Else     *BlockStmt    // else clause (optional)
	Esac     token.Pos     // position of "esac"
}

A CaseStmt node represents a case statement. e.g., case $var in pattern1) commands;; pattern2) commands;; esac

func (*CaseStmt) End

func (s *CaseStmt) End() token.Pos

func (*CaseStmt) Pos

func (s *CaseStmt) Pos() token.Pos

type CmdExpr added in v0.2.0

type CmdExpr struct {
	Name *Ident // command name
	Recv []Expr // command arguments
}

A CmdExpr node represents a command expression. e.g., echo "hello" or ls -la

func Break added in v0.2.0

func Break(n ...int) *CmdExpr

func CmdExpression added in v0.2.0

func CmdExpression(name string, args ...Expr) *CmdExpr

func Continue added in v0.2.0

func Continue(n ...int) *CmdExpr

func ExecCmd added in v0.2.0

func ExecCmd(args ...Expr) *CmdExpr

func Exit added in v0.2.0

func Exit(n ...int) *CmdExpr

func False added in v0.2.0

func False() *CmdExpr

func NoOpCmd added in v0.2.0

func NoOpCmd(args ...Expr) *CmdExpr

func SourceCmd added in v0.2.0

func SourceCmd(file string) *CmdExpr

func True added in v0.2.0

func True() *CmdExpr

func (*CmdExpr) End added in v0.2.0

func (x *CmdExpr) End() token.Pos

func (*CmdExpr) Pos added in v0.2.0

func (x *CmdExpr) Pos() token.Pos

type CmdGroup

type CmdGroup struct {
	Op      token.Token // Token.LBRACE or Token.LPAREN
	Opening token.Pos   // position of opening brace/paren
	List    []Expr      // list of commands
	Closing token.Pos   // position of closing brace/paren
}

A CmdGroup node represents a command group expression. e.g., { cmd1; cmd2; } or (cmd1; cmd2)

func (*CmdGroup) End added in v0.2.0

func (x *CmdGroup) End() token.Pos

func (*CmdGroup) Pos added in v0.2.0

func (x *CmdGroup) Pos() token.Pos

type CmdListExpr added in v0.2.0

type CmdListExpr struct {
	CtrOp token.Token // Token.OrOr or Token.AndAnd
	Cmds  []Expr      // list of commands
}

A CmdListExpr node represents a command list with control operators. e.g., cmd1 && cmd2 or cmd1 || cmd2

func (*CmdListExpr) End added in v0.2.0

func (x *CmdListExpr) End() token.Pos

func (*CmdListExpr) Pos added in v0.2.0

func (x *CmdListExpr) Pos() token.Pos

type CmdSubst

type CmdSubst struct {
	Dollar  token.Pos   // position of "$"
	Tok     token.Token // Token.DollParen or Token.BckQuote or Token.DollBrace
	Opening token.Pos   // position of opening delimiter
	X       Expr        // command expression
	Closing token.Pos   // position of closing delimiter
}

A CmdSubst node represents a command substitution expression. e.g., $(command) or `command` or ${command}

func (*CmdSubst) End

func (x *CmdSubst) End() token.Pos

func (*CmdSubst) Pos

func (x *CmdSubst) Pos() token.Pos

type Comment

type Comment struct {
	Hash token.Pos // position of "#" character
	Text string    // comment text (excluding '#' and trailing newline)
}

A Comment node represents a single #-style comment. The Text field contains the comment text without the leading # character.

func (*Comment) End

func (c *Comment) End() token.Pos

func (*Comment) Pos

func (c *Comment) Pos() token.Pos

type CommentGroup

type CommentGroup struct {
	List []*Comment // len(List) > 0
}

A CommentGroup represents a sequence of comments with no other tokens and no empty lines between.

func (*CommentGroup) End

func (g *CommentGroup) End() token.Pos

func (*CommentGroup) Pos

func (g *CommentGroup) Pos() token.Pos

type DefaultValAssignExp

type DefaultValAssignExp struct {
	Colon  token.Pos // position of ":"
	Assign token.Pos // position of "="
	Val    Expr      // default value
}

DefaultValAssignExp represents a default value assignment expansion. e.g., ${var:=default}

type DefaultValExp

type DefaultValExp struct {
	Colon token.Pos // position of ":"
	Sub   token.Pos // position of "-"
	Val   Expr      // default value
}

DefaultValExp represents a default value expansion. e.g., ${var:-default}

type DelPrefix

type DelPrefix struct {
	Longest bool      // true for ## (longest match)
	Hash    token.Pos // position of "#" or "##"
	Val     Expr      // prefix to delete
}

DelPrefix represents a prefix deletion expansion. e.g., ${var#prefix} or ${var##prefix}

type DelSuffix

type DelSuffix struct {
	Longest bool      // true for %% (longest match)
	Mod     token.Pos // position of "%" or "%%"
	Val     Expr      // suffix to delete
}

DelSuffix represents a suffix deletion expansion. e.g., ${var%suffix} or ${var%%suffix}

type ExpOperator

type ExpOperator string

ExpOperator represents a parameter expansion operator.

type Expr

type Expr interface {
	Node
	// contains filtered or unexported methods
}

All expression nodes implement the Expr interface. An Expr represents any expression in the bash syntax tree.

type ExprStmt

type ExprStmt struct {
	X Expr // expression
}

An ExprStmt node represents a standalone expression. e.g., echo "hello" or ls -la

func (*ExprStmt) End

func (s *ExprStmt) End() token.Pos

func (*ExprStmt) Pos

func (s *ExprStmt) Pos() token.Pos

type ExtendedTestExpr

type ExtendedTestExpr struct {
	Lbrack token.Pos // position of "[["
	X      Expr      // test expression
	Rbrack token.Pos // position of "]]"
}

An ExtendedTestExpr node represents an extended test command expression. e.g., [[ -f file ]] or [[ $a == $b ]]

func (*ExtendedTestExpr) End

func (x *ExtendedTestExpr) End() token.Pos

func (*ExtendedTestExpr) Pos

func (x *ExtendedTestExpr) Pos() token.Pos

type File

type File struct {
	Doc *CommentGroup // associated documentation

	Stmts []Stmt // list of statements
}

A File node represents a bash source file.

func (*File) End

func (*File) End() token.Pos

func (*File) Pos

func (*File) Pos() token.Pos

type ForInStmt

type ForInStmt struct {
	For  token.Pos  // position of "for"
	Var  Expr       // variable name
	In   token.Pos  // position of "in"
	List Expr       // list expression
	Semi token.Pos  // position of ";"
	Do   token.Pos  // position of "do"
	Body *BlockStmt // loop body
	Done token.Pos  // position of "done"
}

A ForInStmt node represents a for-in loop. e.g., for var in list; do commands; done

func (*ForInStmt) End

func (s *ForInStmt) End() token.Pos

func (*ForInStmt) Pos

func (s *ForInStmt) Pos() token.Pos

type ForStmt

type ForStmt struct {
	For    token.Pos  // position of "for"
	Lparen token.Pos  // position of "(("
	Init   Node       // initialization expression
	Semi1  token.Pos  // position of ";"
	Cond   Expr       // condition expression
	Semi2  token.Pos  // position of ";"
	Post   Node       // post-iteration expression
	Rparen token.Pos  // position of "))"
	Do     token.Pos  // position of "do"
	Body   *BlockStmt // loop body
	Done   token.Pos  // position of "done"
}

A ForStmt node represents a C-style for loop. e.g., for ((i=0; i<10; i++)); do commands; done

func (*ForStmt) End

func (s *ForStmt) End() token.Pos

func (*ForStmt) Pos

func (s *ForStmt) Pos() token.Pos

type FuncDecl

type FuncDecl struct {
	Function token.Pos  // position of "function" keyword, if any
	Name     *Ident     // function name
	Lparen   token.Pos  // position of "("
	Rparen   token.Pos  // position of ")"
	Body     *BlockStmt // function body
}

A FuncDecl node represents a function declaration. e.g., function_name() { ... } or function function_name { ... }

func (*FuncDecl) End

func (d *FuncDecl) End() token.Pos

func (*FuncDecl) Pos

func (d *FuncDecl) Pos() token.Pos

type Ident

type Ident struct {
	NamePos token.Pos // identifier position
	Name    string    // identifier name
}

An Ident node represents an identifier. e.g., variable names, function names

func Identifier added in v0.2.0

func Identifier(name string) *Ident

func Option added in v0.2.0

func Option(name string) *Ident

func (*Ident) End

func (x *Ident) End() token.Pos

func (*Ident) Pos

func (x *Ident) Pos() token.Pos

type IfStmt

type IfStmt struct {
	If   token.Pos  // position of "if"
	Cond Expr       // condition expression
	Semi token.Pos  // position of ";"
	Then token.Pos  // position of "then"
	Body *BlockStmt // if body
	Else Stmt       // else clause (can be IfStmt for elif)
	Fi   token.Pos  // position of "fi"
}

An IfStmt node represents an if statement. e.g., if condition; then commands; else commands; fi

func (*IfStmt) End

func (s *IfStmt) End() token.Pos

func (*IfStmt) Pos

func (s *IfStmt) Pos() token.Pos

type IndexExpr

type IndexExpr struct {
	X      Expr      // array expression
	Lbrack token.Pos // position of "["
	Y      Expr      // index expression
	Rbrack token.Pos // position of "]"
}

An IndexExpr node represents an array index expression. e.g., array[index]

func (*IndexExpr) End

func (x *IndexExpr) End() token.Pos

func (*IndexExpr) Pos

func (x *IndexExpr) Pos() token.Pos

type LengthExp

type LengthExp struct {
	Hash token.Pos // position of "#"
}

LengthExp represents a length expansion. e.g., ${#var}

type Node

type Node interface {
	Pos() token.Pos // position of first character belonging to the node
	End() token.Pos // position of first character immediately after the node
}

All node types implement the Node interface. A Node represents any node in the bash syntax tree.

type NonNullCheckExp

type NonNullCheckExp struct {
	Colon token.Pos // position of ":"
	Quest token.Pos // position of "?"
	Val   Expr      // error message
}

NonNullCheckExp represents a non-null check expansion. e.g., ${var:?error_message}

type NonNullExp

type NonNullExp struct {
	Colon token.Pos // position of ":"
	Add   token.Pos // position of "+"
	Val   Expr      // value to substitute
}

NonNullExp represents a non-null expansion. e.g., ${var:+value}

type OperatorExp

type OperatorExp struct {
	At token.Pos   // position of "@"
	Op ExpOperator // expansion operator
}

OperatorExp represents an operator expansion. e.g., ${var@U} or ${var@L}

type ParamExp added in v0.2.0

type ParamExp interface {
	// contains filtered or unexported methods
}

ParamExp represents a parameter expansion operation.

type ParamExpExpr

type ParamExpExpr struct {
	Dollar   token.Pos // position of "$"
	Lbrace   token.Pos // position of "{"
	Var      Expr      // variable name
	ParamExp ParamExp  // parameter expansion operation
	Rbrace   token.Pos // position of "}"
}

A ParamExpExpr node represents a parameter expansion expression. e.g., ${var:-default} or ${var#prefix}

func (*ParamExpExpr) End

func (x *ParamExpExpr) End() token.Pos

func (*ParamExpExpr) Pos

func (x *ParamExpExpr) Pos() token.Pos

type PipelineExpr added in v0.2.0

type PipelineExpr struct {
	CtrOp token.Token // Token.Or or Token.OrAnd
	Cmds  []Expr      // list of commands
}

A PipelineExpr node represents a pipeline expression. e.g., cmd1 | cmd2 or cmd1 |& cmd2

func (*PipelineExpr) End added in v0.2.0

func (x *PipelineExpr) End() token.Pos

func (*PipelineExpr) Pos added in v0.2.0

func (x *PipelineExpr) Pos() token.Pos

type PrefixArrayExp

type PrefixArrayExp struct {
	Bitnot token.Pos // position of '!'
	At     token.Pos // position of '@'
}

PrefixArrayExp represents a prefix array expansion. e.g., ${!var@}

type PrefixExp

type PrefixExp struct {
	Bitnot token.Pos // position of '!'
	Mul    token.Pos // position of '*'
}

PrefixExp represents a prefix expansion. e.g., ${!var*}

type ProcSubst

type ProcSubst struct {
	CtrOp   token.Token // Token.CmdIn or Token.CmdOut
	Opening token.Pos   // position of opening delimiter
	X       Expr        // command expression
	Closing token.Pos   // position of closing delimiter
}

A ProcSubst node represents a process substitution expression. e.g., <(command) or >(command)

func (*ProcSubst) End

func (x *ProcSubst) End() token.Pos

func (*ProcSubst) Pos

func (x *ProcSubst) Pos() token.Pos

type Redirect added in v0.2.0

type Redirect struct {
	N     Expr        // file descriptor number (optional)
	CtrOp token.Token // redirection operator
	OpPos token.Pos   // position of operator
	Word  Expr        // target file or descriptor
}

A Redirect represents an I/O redirection. e.g., >file, <file, 2>&1

func (*Redirect) End added in v0.2.0

func (x *Redirect) End() token.Pos

func (*Redirect) Pos added in v0.2.0

func (x *Redirect) Pos() token.Pos

type ReplaceExp

type ReplaceExp struct {
	All  bool      // true for // (global replacement)
	Div1 token.Pos // position of "/" or "//"
	Old  string    // pattern to replace
	Div2 token.Pos // position of "/"
	New  string    // replacement string
}

ReplaceExp represents a pattern replacement expansion. e.g., ${var/old/new} or ${var//old/new}

type ReplacePrefixExp

type ReplacePrefixExp struct {
	Div1 token.Pos // position of "/"
	Hash token.Pos // position of "#"
	Old  string    // prefix pattern
	Div2 token.Pos // position of "/"
	New  string    // replacement string
}

ReplacePrefixExp represents a prefix replacement expansion. e.g., ${var/#old/new}

type ReplaceSuffixExp

type ReplaceSuffixExp struct {
	Div1 token.Pos // position of "/"
	Mod  token.Pos // position of "%"
	Old  string    // suffix pattern
	Div2 token.Pos // position of "/"
	New  string    // replacement string
}

ReplaceSuffixExp represents a suffix replacement expansion. e.g., ${var/%old/new}

type ReturnStmt

type ReturnStmt struct {
	Return token.Pos // position of "return"
	X      Expr      // return value expression
}

A ReturnStmt node represents a return statement. e.g., return 0 or return $?

func (*ReturnStmt) End

func (s *ReturnStmt) End() token.Pos

func (*ReturnStmt) Pos

func (s *ReturnStmt) Pos() token.Pos

type SelectStmt

type SelectStmt struct {
	Select token.Pos  // position of "select"
	Var    Expr       // variable name
	In     token.Pos  // position of "in"
	List   Expr       // list expression
	Semi   token.Pos  // position of ";"
	Do     token.Pos  // position of "do"
	Body   *BlockStmt // loop body
	Done   token.Pos  // position of "done"
}

A SelectStmt node represents a select statement. e.g., select var in list; do commands; done

func (*SelectStmt) End

func (s *SelectStmt) End() token.Pos

func (*SelectStmt) Pos

func (s *SelectStmt) Pos() token.Pos

type Stmt

type Stmt interface {
	Node
	// contains filtered or unexported methods
}

All statement nodes implement the Stmt interface. A Stmt represents any statement in the bash syntax tree.

type SubstringExp

type SubstringExp struct {
	Colon1 token.Pos // position of ":"
	Offset int       // offset value
	Colon2 token.Pos // position of ":" (for length)
	Length int       // length value
}

SubstringExp represents a substring expansion. e.g., ${var:offset} or ${var:offset:length}

type TestExpr

type TestExpr struct {
	Lbrack token.Pos // position of "["
	X      Expr      // test expression
	Rbrack token.Pos // position of "]"
}

A TestExpr node represents a test command expression. e.g., [ -f file ] or [ $a -eq $b ]

func (*TestExpr) End

func (x *TestExpr) End() token.Pos

func (*TestExpr) Pos

func (x *TestExpr) Pos() token.Pos

type UnaryExpr

type UnaryExpr struct {
	OpPos token.Pos   // position of Op
	Op    token.Token // operator
	X     Expr        // operand
}

A UnaryExpr node represents a unary expression. e.g., !condition or -n string

func (*UnaryExpr) End

func (x *UnaryExpr) End() token.Pos

func (*UnaryExpr) Pos

func (x *UnaryExpr) Pos() token.Pos

type UntilStmt

type UntilStmt struct {
	Until token.Pos  // position of "until"
	Cond  Expr       // condition expression
	Semi  token.Pos  // position of ";"
	Do    token.Pos  // position of "do"
	Body  *BlockStmt // loop body
	Done  token.Pos  // position of "done"
}

An UntilStmt node represents an until loop. e.g., until condition; do commands; done

func (*UntilStmt) End

func (s *UntilStmt) End() token.Pos

func (*UntilStmt) Pos

func (s *UntilStmt) Pos() token.Pos

type VarExpExpr

type VarExpExpr struct {
	Dollar token.Pos // position of "$"
	X      Expr      // variable name
}

A VarExpExpr node represents a variable expansion expression. e.g., $variable

func (*VarExpExpr) End

func (x *VarExpExpr) End() token.Pos

func (*VarExpExpr) Pos

func (x *VarExpExpr) Pos() token.Pos

type Visitor

type Visitor interface {
	Visit(node Node) (w Visitor)
}

A Visitor's Visit method is invoked for each node encountered by Walk. If the result visitor w is not nil, Walk visits each of the children of node with the visitor w, followed by a call of w.Visit(nil).

type WhileStmt

type WhileStmt struct {
	While token.Pos  // position of "while"
	Cond  Expr       // condition expression
	Semi  token.Pos  // position of ";"
	Do    token.Pos  // position of "do"
	Body  *BlockStmt // loop body
	Done  token.Pos  // position of "done"
}

A WhileStmt node represents a while loop. e.g., while condition; do commands; done

func (*WhileStmt) End

func (s *WhileStmt) End() token.Pos

func (*WhileStmt) Pos

func (s *WhileStmt) Pos() token.Pos

type Word added in v0.2.0

type Word struct {
	Val    string    // word value
	ValPos token.Pos // word position
}

A Word node represents a word (string literal or variable). e.g., "hello world" or $variable

func Literal added in v0.2.0

func Literal(v string) *Word

func (*Word) End added in v0.2.0

func (x *Word) End() token.Pos

func (*Word) Pos added in v0.2.0

func (x *Word) Pos() token.Pos

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL