mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
tools: add a v where fn join_path
command, for platform independent searching the location of a symbol in the local project, vlib, ~/.vmodules (#15014)
This commit is contained in:
parent
d12a8aef68
commit
28fd17654e
@ -11,7 +11,7 @@ import v.util
|
|||||||
// should be compiled (v folder).
|
// should be compiled (v folder).
|
||||||
// To implement that, these folders are initially skipped, then added
|
// To implement that, these folders are initially skipped, then added
|
||||||
// as a whole *after the testing.prepare_test_session call*.
|
// as a whole *after the testing.prepare_test_session call*.
|
||||||
const tools_in_subfolders = ['vdoc', 'vvet', 'vast']
|
const tools_in_subfolders = ['vdoc', 'vvet', 'vast', 'vwhere']
|
||||||
|
|
||||||
// non_packaged_tools are tools that should not be packaged with
|
// non_packaged_tools are tools that should not be packaged with
|
||||||
// prebuild versions of V, to keep the size smaller.
|
// prebuild versions of V, to keep the size smaller.
|
||||||
|
171
cmd/tools/vwhere/finder.v
Executable file
171
cmd/tools/vwhere/finder.v
Executable file
@ -0,0 +1,171 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import os
|
||||||
|
import term
|
||||||
|
import os.cmdline
|
||||||
|
|
||||||
|
// Finder is entity that contains all the logic
|
||||||
|
struct Finder {
|
||||||
|
mut:
|
||||||
|
symbol Symbol
|
||||||
|
visib Visibility
|
||||||
|
mutab Mutability
|
||||||
|
name string
|
||||||
|
modul string
|
||||||
|
mth_of string
|
||||||
|
dirs []string
|
||||||
|
matches []Match
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut fdr Finder) configure_from_arguments() {
|
||||||
|
match args.len {
|
||||||
|
1 {
|
||||||
|
fdr.name = args[0]
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
fdr.symbol.set_from_str(args[0])
|
||||||
|
fdr.name = args[1]
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fdr.symbol.set_from_str(args[0])
|
||||||
|
fdr.name = args[1]
|
||||||
|
fdr.visib.set_from_str(cmdline.option(args, '-vis', '${Visibility.all}'))
|
||||||
|
fdr.mutab.set_from_str(cmdline.option(args, '-mut', '${Mutability.any}'))
|
||||||
|
if fdr.symbol != .var && fdr.mutab != .any {
|
||||||
|
make_and_print_error('-mut $fdr.mutab just can be setted with symbol_type:',
|
||||||
|
['var'], '$fdr.symbol')
|
||||||
|
}
|
||||||
|
fdr.modul = cmdline.option(args, '-mod', '')
|
||||||
|
fdr.mth_of = cmdline.option(args, '-m-of', '')
|
||||||
|
if fdr.symbol !in [.@fn, .regexp] && fdr.mth_of != '' {
|
||||||
|
make_and_print_error('-m-of $fdr.mth_of just can be setted with symbol_types:',
|
||||||
|
['fn', 'regexp'], '$fdr.symbol')
|
||||||
|
}
|
||||||
|
fdr.dirs = cmdline.options(args, '-dir')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut fdr Finder) search_for_matches() {
|
||||||
|
// Define where search
|
||||||
|
mut recursive := true
|
||||||
|
mut paths_to_search := []string{}
|
||||||
|
if fdr.dirs.len == 0 && fdr.modul == '' {
|
||||||
|
paths_to_search << [current_dir, vmod_dir]
|
||||||
|
if vroot !in paths_to_search {
|
||||||
|
paths_to_search << vroot
|
||||||
|
}
|
||||||
|
paths_to_search << vmod_paths
|
||||||
|
} else if fdr.dirs.len == 0 && fdr.modul != '' {
|
||||||
|
paths_to_search << if fdr.modul == 'main' { current_dir } else { fdr.modul }
|
||||||
|
} else if fdr.dirs.len != 0 && fdr.modul == '' {
|
||||||
|
recursive = false
|
||||||
|
paths_to_search << fdr.dirs
|
||||||
|
} else {
|
||||||
|
recursive = false
|
||||||
|
paths_to_search << if fdr.modul == 'main' { current_dir } else { fdr.modul }
|
||||||
|
paths_to_search << fdr.dirs
|
||||||
|
}
|
||||||
|
mut files_to_search := []string{}
|
||||||
|
for path in paths_to_search {
|
||||||
|
files_to_search << collect_v_files(path, recursive) or { panic(err) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auxiliar rgx
|
||||||
|
sp := r'\s*'
|
||||||
|
op := r'\('
|
||||||
|
cp := r'\)'
|
||||||
|
|
||||||
|
// Build regex query
|
||||||
|
sy := '$fdr.symbol'
|
||||||
|
st := if fdr.mth_of != '' { '$sp$op$sp[a-z].*$sp$fdr.mth_of$cp$sp' } else { '.*' }
|
||||||
|
na := '$fdr.name'
|
||||||
|
|
||||||
|
query := match fdr.symbol {
|
||||||
|
.@fn {
|
||||||
|
'.*$sy$st$na$sp${op}.*${cp}.*'
|
||||||
|
}
|
||||||
|
.var {
|
||||||
|
'.*$na$sp:=.*'
|
||||||
|
}
|
||||||
|
.@const {
|
||||||
|
'.*$na$sp=.*'
|
||||||
|
}
|
||||||
|
.regexp {
|
||||||
|
'$na'
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
'.*$sy$sp$na${sp}.*' // for struct, enum and interface
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// println(query)
|
||||||
|
is_const := fdr.symbol == .@const
|
||||||
|
for file in files_to_search {
|
||||||
|
n_line, line := search_within_file(file, query, is_const, fdr.visib, fdr.mutab)
|
||||||
|
if n_line != 0 {
|
||||||
|
fdr.matches << Match{file, n_line, line}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (fdr Finder) show_results() {
|
||||||
|
if fdr.matches.len < 1 && (verbose || header) {
|
||||||
|
print(fdr)
|
||||||
|
println(maybe_color(term.bright_yellow, 'No Matches found'))
|
||||||
|
} else if verbose || header {
|
||||||
|
print(fdr)
|
||||||
|
println(maybe_color(term.bright_green, '$fdr.matches.len matches Found\n'))
|
||||||
|
for result in fdr.matches {
|
||||||
|
result.show()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for result in fdr.matches {
|
||||||
|
result.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (fdr Finder) str() string {
|
||||||
|
v := maybe_color(term.bright_red, '$fdr.visib')
|
||||||
|
m := maybe_color(term.bright_red, '$fdr.mutab')
|
||||||
|
st := if fdr.mth_of != '' { ' ( _ $fdr.mth_of)' } else { '' }
|
||||||
|
s := maybe_color(term.bright_magenta, '$fdr.symbol')
|
||||||
|
n := maybe_color(term.bright_cyan, '$fdr.name')
|
||||||
|
|
||||||
|
mm := if fdr.modul != '' { maybe_color(term.blue, '$fdr.modul') } else { '' }
|
||||||
|
dd := if fdr.dirs.len != 0 {
|
||||||
|
fdr.dirs.map(maybe_color(term.blue, it))
|
||||||
|
} else {
|
||||||
|
fdr.dirs
|
||||||
|
}
|
||||||
|
|
||||||
|
dm := if fdr.dirs.len == 0 && fdr.modul == '' {
|
||||||
|
'all the project scope'
|
||||||
|
} else if fdr.dirs.len == 0 && fdr.modul != '' {
|
||||||
|
'module $mm'
|
||||||
|
} else if fdr.dirs.len != 0 && fdr.modul == '' {
|
||||||
|
'directories: $dd'
|
||||||
|
} else {
|
||||||
|
'module $mm searching within directories: $dd'
|
||||||
|
}
|
||||||
|
|
||||||
|
return '\nFind: $s$st $n | visibility: $v mutability: $m\nwithin $dm '
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match is one result of the search_for_matches() process
|
||||||
|
struct Match {
|
||||||
|
path string [required]
|
||||||
|
line int [required]
|
||||||
|
text string [required]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mtc Match) show() {
|
||||||
|
path := maybe_color(term.bright_magenta, mtc.path)
|
||||||
|
line := maybe_color(term.bright_yellow, '$mtc.line')
|
||||||
|
text := maybe_color(term.bright_green, '$mtc.text')
|
||||||
|
if verbose || format {
|
||||||
|
println('$path\n$line : [ $text ]\n')
|
||||||
|
} else {
|
||||||
|
println('$path:$line: $text')
|
||||||
|
}
|
||||||
|
}
|
205
cmd/tools/vwhere/finder_utils.v
Executable file
205
cmd/tools/vwhere/finder_utils.v
Executable file
@ -0,0 +1,205 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import os
|
||||||
|
import term
|
||||||
|
import regex
|
||||||
|
import v.pref
|
||||||
|
import os.cmdline
|
||||||
|
|
||||||
|
// Symbol type to search
|
||||||
|
enum Symbol {
|
||||||
|
@fn
|
||||||
|
@struct
|
||||||
|
@interface
|
||||||
|
@enum
|
||||||
|
@const
|
||||||
|
var
|
||||||
|
regexp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visibility of the symbols to search
|
||||||
|
enum Visibility {
|
||||||
|
all
|
||||||
|
@pub
|
||||||
|
pri
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutability of the symbols to search
|
||||||
|
enum Mutability {
|
||||||
|
any
|
||||||
|
yes
|
||||||
|
not
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
args = os.args[2..]
|
||||||
|
verbose = '-v' in cmdline.only_options(args)
|
||||||
|
header = '-h' in cmdline.only_options(args)
|
||||||
|
format = '-f' in cmdline.only_options(args)
|
||||||
|
symbols = {
|
||||||
|
'fn': Symbol.@fn
|
||||||
|
'struct': .@struct
|
||||||
|
'interface': .@interface
|
||||||
|
'enum': .@enum
|
||||||
|
'const': .@const
|
||||||
|
'var': .var
|
||||||
|
'regexp': .regexp
|
||||||
|
}
|
||||||
|
visibilities = {
|
||||||
|
'all': Visibility.all
|
||||||
|
'pub': .@pub
|
||||||
|
'pri': .pri
|
||||||
|
}
|
||||||
|
mutabilities = {
|
||||||
|
'any': Mutability.any
|
||||||
|
'yes': .yes
|
||||||
|
'not': .not
|
||||||
|
}
|
||||||
|
vexe = pref.vexe_path()
|
||||||
|
vroot = os.dir(vexe)
|
||||||
|
vmod_dir = os.vmodules_dir()
|
||||||
|
vmod_paths = os.vmodules_paths()[1..]
|
||||||
|
current_dir = os.abs_path('.')
|
||||||
|
color_out = term.can_show_color_on_stdout()
|
||||||
|
)
|
||||||
|
|
||||||
|
fn (mut cfg Symbol) set_from_str(str_in string) {
|
||||||
|
if str_in !in symbols {
|
||||||
|
invalid_option(cfg, str_in)
|
||||||
|
}
|
||||||
|
cfg = symbols[str_in]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut cfg Visibility) set_from_str(str_in string) {
|
||||||
|
if str_in !in visibilities {
|
||||||
|
invalid_option(cfg, str_in)
|
||||||
|
}
|
||||||
|
cfg = visibilities[str_in]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut cfg Mutability) set_from_str(str_in string) {
|
||||||
|
if str_in !in mutabilities {
|
||||||
|
invalid_option(cfg, str_in)
|
||||||
|
}
|
||||||
|
cfg = mutabilities[str_in]
|
||||||
|
}
|
||||||
|
|
||||||
|
type ParamOption = Mutability | Symbol | Visibility
|
||||||
|
|
||||||
|
// General helpers
|
||||||
|
fn invalid_option(invalid ParamOption, arg string) {
|
||||||
|
match invalid.type_name() {
|
||||||
|
'Symbol' {
|
||||||
|
msg := 'First arg (symbol type) must be one of the following:'
|
||||||
|
make_and_print_error(msg, symbols.keys(), arg)
|
||||||
|
}
|
||||||
|
'Visibility' {
|
||||||
|
msg := '"-vis" (visibility) must be one of the following:'
|
||||||
|
make_and_print_error(msg, visibilities.keys(), arg)
|
||||||
|
}
|
||||||
|
'Mutability' {
|
||||||
|
msg := '"-mut" (mutability) must be one of the following:'
|
||||||
|
make_and_print_error(msg, mutabilities.keys(), arg)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn valid_args_quantity_or_show_help() {
|
||||||
|
if true in [
|
||||||
|
args.len < 1,
|
||||||
|
'-help' in os.args,
|
||||||
|
'--help' in os.args,
|
||||||
|
os.args[1..] == ['where', 'help'],
|
||||||
|
] {
|
||||||
|
os.system('${os.quoted_path(vexe)} help where')
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_and_print_error(msg string, opts []string, arg string) {
|
||||||
|
eprintln('\n' + maybe_color(term.bright_yellow, msg))
|
||||||
|
if opts.len > 0 {
|
||||||
|
eprint(opts.map(maybe_color(term.bright_green, it)).join(' | '))
|
||||||
|
}
|
||||||
|
eprintln(' ...can not be ${maybe_color(term.bright_red, arg)}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn maybe_color(term_color fn (string) string, str string) string {
|
||||||
|
if color_out {
|
||||||
|
return term_color(str)
|
||||||
|
} else {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_v_files(path string, recursive bool) ?[]string {
|
||||||
|
if path.len == 0 {
|
||||||
|
return error('path cannot be empty')
|
||||||
|
}
|
||||||
|
if !os.is_dir(path) {
|
||||||
|
return error('path does not exist or is not a directory')
|
||||||
|
}
|
||||||
|
mut all_files := []string{}
|
||||||
|
mut entries := os.ls(path)?
|
||||||
|
mut local_path_separator := os.path_separator
|
||||||
|
if path.ends_with(os.path_separator) {
|
||||||
|
local_path_separator = ''
|
||||||
|
}
|
||||||
|
for entry in entries {
|
||||||
|
file := path + local_path_separator + entry
|
||||||
|
if os.is_dir(file) && !os.is_link(file) && recursive {
|
||||||
|
all_files << collect_v_files(file, recursive)?
|
||||||
|
} else if os.exists(file) && (file.ends_with('.v') || file.ends_with('.vsh')) {
|
||||||
|
all_files << file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return all_files
|
||||||
|
}
|
||||||
|
|
||||||
|
fn search_within_file(file string, query string, is_const bool, v Visibility, m Mutability) (int, string) {
|
||||||
|
mut re := regex.regex_opt(query) or { panic(err) }
|
||||||
|
lines := os.read_lines(file) or { panic(err) }
|
||||||
|
mut const_found := if is_const { false } else { true }
|
||||||
|
mut n_line := 1
|
||||||
|
for line in lines {
|
||||||
|
if line.starts_with('const') {
|
||||||
|
const_found = true
|
||||||
|
}
|
||||||
|
if re.matches_string(line) && const_found {
|
||||||
|
words := line.split(' ').map(it.trim('\t'))
|
||||||
|
match v {
|
||||||
|
.all {}
|
||||||
|
.@pub {
|
||||||
|
if 'pub' !in words {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pri {
|
||||||
|
if 'pub' in words {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match m {
|
||||||
|
.any {}
|
||||||
|
.yes {
|
||||||
|
if 'mut' !in words {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.not {
|
||||||
|
if 'mut' in words {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n_line, line.replace(' {', '')
|
||||||
|
}
|
||||||
|
n_line++
|
||||||
|
}
|
||||||
|
return 0, ''
|
||||||
|
}
|
9
cmd/tools/vwhere/vwhere.v
Executable file
9
cmd/tools/vwhere/vwhere.v
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
valid_args_quantity_or_show_help()
|
||||||
|
mut fdr := Finder{}
|
||||||
|
fdr.configure_from_arguments()
|
||||||
|
fdr.search_for_matches()
|
||||||
|
fdr.show_results()
|
||||||
|
}
|
@ -32,6 +32,7 @@ V supports the following commands:
|
|||||||
vlib-docs Generate and open the documentation of all the vlib modules.
|
vlib-docs Generate and open the documentation of all the vlib modules.
|
||||||
repl Run the REPL.
|
repl Run the REPL.
|
||||||
watch Re-compile/re-run a source file, each time it is changed.
|
watch Re-compile/re-run a source file, each time it is changed.
|
||||||
|
where Find and print the location of current project declarations.
|
||||||
|
|
||||||
* Installation/self updating:
|
* Installation/self updating:
|
||||||
symlink Create a symbolic link for V.
|
symlink Create a symbolic link for V.
|
||||||
|
42
cmd/v/help/where.txt
Executable file
42
cmd/v/help/where.txt
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
Usage:
|
||||||
|
v where [symbol_type] [symbol_name] [params]
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
v where fn main
|
||||||
|
v where struct User
|
||||||
|
v where fn say_hello -mod Person
|
||||||
|
v where fn area -m-of Square
|
||||||
|
v where interface callable -dir some -dir other
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
Prints the location of the searched symbols in the scope of the current project.
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
symbol_name can be:
|
||||||
|
fn (by default if omit [symbol_type])
|
||||||
|
struct
|
||||||
|
interface
|
||||||
|
enum
|
||||||
|
const
|
||||||
|
var
|
||||||
|
regexp
|
||||||
|
|
||||||
|
params:
|
||||||
|
-mod [mod_name] Restrict to search recursively only within of the given
|
||||||
|
module, if not provided search in entire v scope.
|
||||||
|
-dir [dir_path] Restrict to search non recursively within the given
|
||||||
|
folder/s, if not provided, search in entire v scope.
|
||||||
|
-vis [visibility] Can be: all, pub, pri (all by default if not provided).
|
||||||
|
Restrict to search symbols with the given visibility.
|
||||||
|
-mut [mutability] Can be: any, yes, not (any by default if not provided).
|
||||||
|
Restrict to search symbols with the given mutability.
|
||||||
|
-m-of [struct_name] (just for fn symbol_name).
|
||||||
|
Restrict to search fn as method of the given struct.
|
||||||
|
flags:
|
||||||
|
-h Include header
|
||||||
|
-f Format output (each match uses 3 lines)
|
||||||
|
-v For both above
|
||||||
|
|
||||||
|
Note:
|
||||||
|
This tool is inspired by the vdoc tool and its design. However, this is
|
||||||
|
for a more specific use, and can be improved.
|
1
cmd/v/v.v
Normal file → Executable file
1
cmd/v/v.v
Normal file → Executable file
@ -48,6 +48,7 @@ const (
|
|||||||
'vet',
|
'vet',
|
||||||
'wipe-cache',
|
'wipe-cache',
|
||||||
'watch',
|
'watch',
|
||||||
|
'where',
|
||||||
]
|
]
|
||||||
list_of_flags_that_allow_duplicates = ['cc', 'd', 'define', 'cf', 'cflags']
|
list_of_flags_that_allow_duplicates = ['cc', 'd', 'define', 'cf', 'cflags']
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user