Compare commits

..

83 commits
qdls ... main

Author SHA1 Message Date
70eedcfc3e scripts: added sqlcmd.sh 2024-10-29 13:59:20 -04:00
2f8f14d77d scripts: added 'wsl.sh' 2024-08-27 09:05:25 -04:00
697929c8ad man: corrected synopsis for wt 2024-08-23 10:51:23 -04:00
cd4e0c63be scripts: added 'charmap.sh' 2024-08-22 15:34:22 -04:00
f43ac5c8d3 scripts: updated 'wt.sh' elevate mode to use the correct binary name 2024-08-22 10:54:56 -04:00
ae32215b1a scripts: 'wt.sh' now exits correctly on elevate 2024-08-22 10:53:17 -04:00
99f7ed5726 man: added missing information to cmd man page 2024-08-22 10:14:58 -04:00
392c3f9230 scripts: fixed 'cmd.sh' never passing arguments 2024-08-22 09:57:44 -04:00
20d9d7294b updated default install location 2024-08-22 09:44:05 -04:00
7e24c0e1ab scripts: updated justfile for renamed 'wt.sh' 2024-08-22 09:42:38 -04:00
dab081eb0b updated README 2024-08-22 09:39:44 -04:00
f4b47946d9 man: justfile now installs section 8 man pages 2024-08-22 09:38:00 -04:00
e0eb36720b man: added man page for 'cmd' 2024-08-22 09:37:07 -04:00
ef547b7be1 man: updated mkwin and wt manuals 2024-08-22 09:37:07 -04:00
1baac5aee9 man: added man page for windows terminal 2024-08-22 09:37:07 -04:00
c1e9bb32ce scripts: renamed 'terminal.sh' to 'wt.sh' for better parity 2024-08-22 09:37:07 -04:00
0ef8aa01e7 scripts: added 'cmd.sh' 2024-08-22 09:27:15 -04:00
45ad9ea79a man: updated os line for all manuals 2024-08-19 09:33:11 -04:00
4555833c3c scripts: 'terminal.sh' elevate flag now consistently works 2024-08-19 09:14:06 -04:00
eb675928a7 initial implementation for 'or' flag 2024-08-12 15:07:57 -04:00
72d6902136 error methods now have the correct return type 2024-08-12 15:07:02 -04:00
ed26c60ceb mkwin: updated help text 2024-07-22 13:46:02 -04:00
a54e5422b4 man: updated 'mkwin' manual 2024-07-22 13:37:57 -04:00
a156009442 mkwin: added env-share flag 2024-07-22 13:32:16 -04:00
f7680216b8 scripts: fixed a typo in 'pwsh.sh' that caused the wrong powershell to be used 2024-07-22 13:21:21 -04:00
b204c440e2 path-convert: non-canonicalized arguments are now passed through correctly 2024-07-16 09:54:58 -04:00
2d88ac6f45 Merge branch 'hug' 2024-07-16 09:05:11 -04:00
662137297d man: fixed typo in 'dos-var' manual 2024-07-15 14:00:22 -04:00
5589490fe2 man: created 'hug' manual 2024-07-15 14:00:02 -04:00
baacf638e7 hug: added just scripts 2024-07-15 13:35:35 -04:00
5775412f18 hug: removed mystery import? 2024-07-15 13:22:57 -04:00
43d5cbd4aa hug: initial implementation 2024-07-15 13:21:43 -04:00
bf3e86a5df scripts: 'pwsh' now uses a more reliable path and fallback 2024-07-15 10:26:31 -04:00
c96fc7bbcb scripts: 'pwsh' script now uses env-share 2024-07-12 14:37:40 -04:00
32731b72b1 scripts: removed 'userprofile' script in favor of 'dos-var' 2024-07-12 14:32:26 -04:00
3fd510a45c dos-var: created justfile 2024-07-12 14:31:31 -04:00
90979cb411 man: created dos-var manual 2024-07-12 14:31:15 -04:00
e59907d81e dos-var: corrected error message 2024-07-12 14:17:58 -04:00
30159a43ae dos-var: usability improvement and added release profile 2024-07-12 14:16:07 -04:00
2b416b6b2f dos-var: initial implementation 2024-07-12 14:05:01 -04:00
5bdeabbe76 all: errors now print to stderr instead of stdout 2024-07-12 10:46:25 -04:00
00068f5e5d added env-share to main justfile 2024-07-08 13:31:51 -04:00
190f17f7e2 env-share: created justfile 2024-07-08 13:26:12 -04:00
18389ca9b8 scripts: created userprofile script 2024-07-08 13:25:59 -04:00
2798682a1d env-share: added git-bash companion script 2024-07-08 13:09:51 -04:00
cceb2048b9 env-share: fixed a couple minor issues and added release profile 2024-07-08 10:26:22 -04:00
7c7d720f8e env-share: initial implementation 2024-07-08 10:12:46 -04:00
2445530f9b man: fixed typos in mkwin manual 2024-07-05 14:25:56 -04:00
dd299c4976 scripts: created pwsh launch script 2024-07-03 16:20:46 -04:00
c5625bf46c man: fixed a typo for path-convert 2024-06-25 13:16:31 -04:00
a7197d6083 man: added pages for mkwin and path-convert 2024-06-25 12:34:40 -04:00
5893a1fbfc updated README 2024-06-25 09:50:49 -04:00
7262fe4a17 scripts: dos.sh now runs with or without args 2024-06-25 09:50:42 -04:00
9738b9a0e9 mkwin: added a 'find' flag to use 'find' to locate binaries with changing paths 2024-06-25 09:45:01 -04:00
63f8e69afc scripts: elevate now only requires a target for DOS mode (Linux mode opens WSL shell) 2024-06-17 08:58:42 -04:00
c097159c05 path-convert: no target converts pwd 2024-06-17 08:45:44 -04:00
67ec5ec90b updated README 2024-06-14 14:01:48 -04:00
edf2fed12d just: moved qdls chmod from base 'install all' script to qdls 'install' script 2024-06-14 13:53:36 -04:00
795f45e607 fixed base install 2024-06-14 13:49:17 -04:00
ccae331e6f fixed syntax errors in base justfile 2024-06-14 11:28:47 -04:00
60833cef60 improved base justfile 2024-06-14 11:26:53 -04:00
64deaeaece initial justfiles 2024-06-14 11:24:46 -04:00
47a05b4508 qlds: updated gitignore 2024-06-14 10:58:17 -04:00
a709ef4585 scripts: added new scripts 'dos' and 'terminal' 2024-06-14 08:51:02 -04:00
40e33e7023 scripts: improved code clarity in elevate.sh 2024-06-13 10:39:43 -04:00
43edc934ec updated README and made explorer.sh a sample 2024-06-12 15:18:04 -04:00
741385cc64 scripts: initial implementation of elevate.sh 2024-06-12 15:17:43 -04:00
480620e192 mkwin: proofread and clarified help text 2024-06-11 11:51:50 -04:00
9bc9ba71ec mkwin: improved help text formatting 2024-06-11 11:43:57 -04:00
1ddf8439f5 mkwin: improved output formatting 2024-06-11 11:41:58 -04:00
a3b3dce376 mkwin: added empty flag to not pass $@ 2024-06-11 11:29:57 -04:00
5386fbdf63 mkwin: updated help text 2024-06-11 11:05:33 -04:00
468727e2ad version bump 2024-06-11 10:57:29 -04:00
05dd7187ac mkwin: implement argument forwarding and improved output formatting 2024-06-11 10:56:56 -04:00
48030490cb path-convert: updated help text 2024-06-11 10:12:18 -04:00
f7e215b548 path-convert: added flag to emit network paths 2024-06-11 10:05:41 -04:00
f62b201c14 updated README 2024-06-11 09:49:13 -04:00
b9cb18ea0b fixed a crash and made paths canonicalize 2024-06-11 09:32:57 -04:00
6ff3b992bc Merge branch 'mkwin' 2024-06-11 09:12:49 -04:00
fa743c5a34 Merge branch 'qdls' 2024-06-11 09:12:45 -04:00
8dca73516d minor repo structure change 2024-06-11 09:12:35 -04:00
d8e7bb5b33 updated README 2024-06-11 09:11:39 -04:00
3ea61d1954 mkwin: initial commit 2024-06-11 09:11:24 -04:00
48 changed files with 1097 additions and 67 deletions

View file

@ -1,7 +1,26 @@
# Winure: WSL inurement tools
These are tools I use to use Windows primarily through WSL.
These are tools I use to use Windows primarily through WSL. Many are
cross-dependent.
## `dos-var`
Gets Windows environment variables from DOS.
## `env-share`
A hacked-together utility for sending WSL variables back to Windows
shells. The utility runs in WSL, and companion scripts run in Windows.
## `hug`
A barebones command wrapper for turning binary-output text into normal text.
## `mkwin`
A Linux utility to quickly make a bash script to run a Windows executable with
certain parameters.
## `path-convert`
@ -13,5 +32,27 @@ their normal DOS form.
## `qdls`
A DOS clone of `ls` that hides Windows hidden files.
A feature-barren DOS clone of `ls` that hides Windows hidden files. Relies on
`dotnet-warp` as a build dependency.
---
## Scripts
- `charmap.sh`: Simple wrapper for Character Map.
- `cmd.sh`: Simple wrapper for `cmd.exe`.
- `dos.sh`: Simple wrapper for executing Windows commands directly.
- `elevate.sh`: Elevate WSL (`-l`) or Windows (`-w`) commands from WSL.
- `explorer.sh`: Launch explorer from WSL.
- `pwsh.sh`: Launch PowerShell Core.
- `sqlcmd.sh`: Simple wrapper for `sqlcmd.exe`.
- `wsl.sh`: A wrapper for `wsl.exe` that wraps in `hug` when piped.
- `wt.sh`: Launch Windows Terminal.
---
## Windows Man Pages
- `cmd(8)`: `cmd.exe`
- `wt(1)`: Windows Terminal

View file

@ -1 +1,2 @@
/target
Cargo.lock

15
dos-var/Cargo.toml Normal file
View file

@ -0,0 +1,15 @@
[package]
name = "dos-var"
version = "0.0.2"
edition = "2021"
[dependencies]
pico-args = "0.5.0"
[profile.release]
opt-level = 's'
codegen-units = 1
debug = false
lto = true
panic = "abort"
strip = "symbols"

10
dos-var/justfile Normal file
View file

@ -0,0 +1,10 @@
alias b := build
alias i := install
build:
cargo build --release
install DIR: build
cp ./target/release/dos-var "{{DIR}}/dos-var"

13
dos-var/src/error.rs Normal file
View file

@ -0,0 +1,13 @@
use std::process::exit;
pub fn not_found(target: &String) {
eprintln!("dos-var: %{target}% has no value");
exit(1);
}
pub fn missing_arg() {
eprintln!("dos-var: no argument found");
exit(2);
}

40
dos-var/src/main.rs Normal file
View file

@ -0,0 +1,40 @@
use std::process::Command;
use pico_args::Arguments;
mod error;
const CMD: &str = "/mnt/c/Windows/System32/cmd.exe";
const FLAG_PATH: [&str; 2] = [ "-p", "--path" ];
pub fn main() {
let mut args = Arguments::from_env();
let convert_path = args.contains(FLAG_PATH);
if let Ok(Some(target)) = args.subcommand() {
let cmd = Command::new(CMD)
.current_dir("/mnt/c/")
.arg( format!("/C echo %{target}%") )
.output();
if let Ok(output) = cmd {
if let Ok(stdout) = String::from_utf8(output.stdout) {
// trim output
let stdout = stdout.trim_end_matches("\"\r\n");
// catch empty variable case
if stdout == format!("%{target}%") { error::not_found(&target); }
// handle path flag and write
let path =
if convert_path {
stdout
.replace("\\", "/")
.replace("C:/", "/mnt/c/")
} else { stdout.to_owned() };
println!("{path}");
}
}
} else { error::missing_arg(); }
}

2
env-share/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
Cargo.lock

12
env-share/Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "env-share"
version = "0.0.2"
edition = "2021"
[profile.release]
opt-level = 's'
codegen-units = 1
debug = false
lto = true
panic = "abort"
strip = "symbols"

11
env-share/justfile Normal file
View file

@ -0,0 +1,11 @@
alias b := build
alias i := install
build:
cargo build --release
install DIR: build
cp ./target/release/env-share "{{DIR}}/env-share"

View file

@ -0,0 +1,18 @@
# make sure the file exists
$file = $env:ENV_SHARE_FILE
if(-not (Test-Path $file)) {
exit
}
# insert values into env
foreach($line in Get-Content $file) {
$parts = $line -split ' = '
$var = $parts[0]
$value = $parts[1]
Set-Item env:$var -Value $value
}
# delete the file
Remove-Item $file

View file

@ -0,0 +1,19 @@
#!/usr/bin/bash
# make sure file is present
file=$ENV_SHARE_FILE
if [[ ! -r "$file" ]]; then
return
fi
# read lines and set variables
IFS=' = '
while read line; do
var=${line%$IFS*}
value=${line#*$IFS}
export $var=$value
done <$file
# delete file
rm $file

18
env-share/src/error.rs Normal file
View file

@ -0,0 +1,18 @@
use std::process::exit;
pub fn file_unset() {
eprintln!("env-share: ENV_SHARE_FILE is unset");
exit(1);
}
pub fn vars_unset() {
eprintln!("env-share: ENV_SHARE_VARS is unset");
exit(1);
}
pub fn write_fail(file: &String) {
eprintln!("env-share: failed to write to '{file}'");
exit(2);
}

31
env-share/src/main.rs Normal file
View file

@ -0,0 +1,31 @@
use std::{
env,
fs::write
};
mod error;
fn main() {
// try to get share file variable
if let Ok(file) = env::var("ENV_SHARE_FILE") {
if let Ok(var_string) = env::var("ENV_SHARE_VARS") {
// build output
let mut output = String::new();
let vars = var_string.split(':');
for var in vars {
let value = env::var(var).unwrap_or(String::new());
if value.is_empty() { continue; }
output += &format!("{var} = {value}\n");
}
// write to file
let result = write(&file, output);
match result {
Err(_) => error::write_fail(&file),
_ => { }
}
} else { error::vars_unset(); }
} else { error::file_unset(); }
}

2
hug/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
Cargo.lock

13
hug/Cargo.toml Normal file
View file

@ -0,0 +1,13 @@
[package]
name = "hug"
version = "0.0.1"
edition = "2021"
[profile.release]
opt-level = 's'
codegen-units = 1
debug = false
lto = true
panic = "abort"
strip = "symbols"

10
hug/justfile Normal file
View file

@ -0,0 +1,10 @@
alias b := build
alias i := install
build:
cargo build --release
install DIR: build
cp ./target/release/hug "{{DIR}}/hug"

32
hug/src/main.rs Normal file
View file

@ -0,0 +1,32 @@
use std::{
env,
process::{ Command, Stdio }
};
fn main() {
let mut args: Vec<String> = env::args().collect();
args.remove(0);
let target = args.remove(0);
let command = Command::new(target)
.args(args)
.stderr(Stdio::inherit())
.output();
if let Ok(output) = command {
let mut line = String::new();
for byte in output.stdout {
match char::from_u32(byte.into()) {
Some('\n') => {
println!("{line}");
line = String::new();
},
Some('\0') |
None => continue,
Some(c) => line.push(c),
}
}
}
}

22
justfile Normal file
View file

@ -0,0 +1,22 @@
alias b := build
alias i := install
build TARGET:
just {{TARGET}}/build
install TARGET='all' DIR="/usr/local/bin":
#!/usr/bin/bash
if [[ {{TARGET}} == 'all' ]]; then
just install scripts {{DIR}}
just install dos-var {{DIR}}
just install env-share {{DIR}}
just install hug {{DIR}}
just install mkwin {{DIR}}
just install path-convert {{DIR}}
just install qdls {{DIR}}
just install man
else
just {{TARGET}}/install `realpath {{DIR}}`
fi

107
man/cmd.8 Normal file
View file

@ -0,0 +1,107 @@
.Dd $Mdocdate$
.Dt CMD 8
.Os MICROSOFT WINDOWS
.Sh NAME
.Nm cmd
.Nd Windows Command Prompt
.Sh SYNOPSIS
.Nm
.Op Fl DQ
.Op Fl A|U
.Op Oo Fl S Oc Fl C|K Ar command
.Op Fl E Ns = Ns Ar ON|OFF
.Op Fl T Ns = Ns Ar fb
.Op Fl V Ns = Ns Ar ON|OFF
.Sh DESCRIPTION
.Nm
is a Linux wrapper for Windows Command Prompt. Its options are as follows:
.Bl -tag -width Ds
.It Fl ?
Displays a fairly unhelpful and incomplete help text.
.It Fl A
Standard outputs will be redirected in ANSI.
.It Fl C Ar command
Executes the specified command and exits.
.It Fl D
Disables autorun commands. See
.Sx AUTORUN
below.
.It Fl E Ns = Ns Ar ON|OFF
Enable or disable command extensions. See
.Sx COMMAND EXTENSIONS
below.
.It Fl F Ns = Ns Ar ON|OFF
Enable or disable filename completion. See
.Sx FILENAME COMPLETION
below.
.It Fl K Ar command
Executes the specified command, then become interactive.
.It Fl Q
Disables echoing commands for non-interactive modes.
.It Fl S
Modifies input handling. See
.Sx MODIFIED INPUT HANDLING
below.
.It Fl T Ns = Ns Ar fb
Output will use colors as if 'color xx' was called; the first digit sets the foreground color, and the second digit sets the background color.
.It Fl U
Standard outputs will be redirected in Unicode.
.It Fl V Ns = Ns Ar ON|OFF
Enable or disable execution-time environment variable expansion. See
.Sx EXECUTION-TIME ENVIRONMENT VARIABLE EXPANSION
below.
.Sh BEHAVIORS
.Ss AUTORUN
Autorun is enabled by default, and can be disabled with the
.Fl D
flag. If enabled, the program will search registry variables
.Cd HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun
and
.Cd HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
for commands at startup and execute them if present.
.Ss COMMAND EXTENSIONS
Command extensions are enabled by default, and can be disabled by setting
.Fl E Ns = Ns OFF .
Extensions can modify the following commands:
.Pp
.Ic DEL or Ic ERASE ,
.Ic COLOR ,
.Ic CD or Ic CHDIR ,
.Ic MD or Ic MKDIR ,
.Ic PROMPT ,
.Ic PUSHD ,
.Ic POPD ,
.Ic SET ,
.Ic SETLOCAL ,
.Ic ENDLOCAL ,
.Ic IF ,
.Ic FOR ,
.Ic CALL ,
.Ic SHIFT ,
.Ic GOTO ,
.Ic START ,
.Ic ASSOC ,
.Ic FTYPE
.Ss EXECUTION-TIME ENVIRONMENT VARIABLE EXPANSION
Execution-time environment variable expansion is disabled by default, and can be enabled by setting
.Fl V Ns = Ns OFF .
If enabled, enclosing a variable name with '!' characters will substitute the variable's value at command execution time.
.Ss FILENAME COMPLETION
Filename completion is disabled by default, and can be enabled by setting
.Fl F Ns = Ns ON .
If enabled, Ctrl-D and Ctrl-F can be used for directory and file completion respectively.
.Ss MODIFIED INPUT HANDLING
If the
.Fl S
flag is present, the program will strip the leading and trailing quotes from the
.Ar command
supplied to
.Fl C
or
.Fl K
and pass the remaining string literally as if it was typed directly into the prompt, ignoring special characters.
.Sh BUGS
.Nm
lacks escape characters, meaning arguments with special characters
.Em must
be enclosed in quotes.

35
man/dos-var.1 Normal file
View file

@ -0,0 +1,35 @@
.Dd $Mdocdate$
.Dt DOS-VAR 1
.Os WSL
.Sh NAME
.Nm dos-var
.Nd gets DOS environment variables from WSL
.Sh SYNOPSIS
.Nm
.Op Fl p
.Ar variable
.Sh DESCRIPTION
The
.Nm
utility gets a DOS environment variable from within WSL. It can also convert paths to UNIX.
.Bl -tag -width Ds
.It Fl p , Fl -path
The target DOS variable contains a path, and will be converted.
.It Ar variable
The name of the target DOS variable.
.El
.Sh EXIT STATUS
.Bl -tag -width Ds
.It 1
The target variable is empty.
.It 2
No target variable was provided.
.El
.Sh EXAMPLES
Navigate to the Windows user directory:
.Pp
.Dl $ cd `dos-var -p USERPROFILE`
.Pp
.Sh Authors
.An -nosplit
.An Valerie Wolfe Aq Mt sleeplessval@gmail.com

30
man/env-share.1 Normal file
View file

@ -0,0 +1,30 @@
.Dd $Mdocdate$
.Dt ENV-SHARE 1
.Os WSL
.Sh NAME
.Nm env-share
.Nd share environment variables back to Windows from WSL
.Sh SYNOPSIS
.Nm env-share
.Sh DESCRIPTION
The
.Nm
utility writes environment variables to a file to be loaded by a companion script in the target process.
.Sh ENVIRONMENT
.Bl -tag -width Ds
.It Ev ENV_SHARE_FILE
The file to write variables to.
.It Ev ENV_SHARE_VARS
A colon-separated list of variables to copy.
.El
.Sh EXIT STATUS
.Bl -tag -width Ds
.It 1
An environment variable is unset.
.It 2
Failed to write to the file at
.Ev ENV_SHARE_FILE
.El
.Sh AUTHORS
.An -nosplit
.An Valerie Wolfe Aq Mt sleeplessval@gmail.com

25
man/hug.1 Normal file
View file

@ -0,0 +1,25 @@
.Dd $Mdocdate$
.Dt HUG 1
.Os WSL
.Sh NAME
.Nm hug
.Nd wraps processes and converts binary output to text
.Sh SYNOPSIS
.Nm
.Ar target
.Op Ar args...
.Sh DESCRIPTION
The
.Nm
utility runs a process and emits bytes from standard output to text.
.Sh EXAMPLES
WSL's help text is output as binary content, preventing piping to utilities like
.Xr less 1
or
.Xr bat 1 :
.Pp
.Dl $ hug wsl --help | less
.Pp
.Sh Authors
.An -nosplit
.An Valerie Wolfe Aq Mt sleeplessval@gmail.com

7
man/justfile Normal file
View file

@ -0,0 +1,7 @@
alias i := install
install DIR="(unused)":
sudo cp ./*.1 /usr/share/man/man1/
sudo cp ./*.8 /usr/share/man/man8/

71
man/mkwin.1 Normal file
View file

@ -0,0 +1,71 @@
.Dd $Mdocdate$
.Dt MKWIN 1
.Os WSL
.Sh NAME
.Nm mkwin
.Nd generate bash scripts for running Windows programs from WSL
.Sh SYNOPSIS
.Nm mkwin
.Op Fl heEq
.Op Fl -find Ar root
.Op Fl -pc Ar flags
.Ar target
.Op Fl -or Ar alt
.Op Ar --\ args
.Sh DESCRIPTION
The
.Nm
utility generates bash scripts for executing Windows executables from WSL, and prints them to the standard output. The options are as follows:
.Bl -tag -width Ds
.It Ar --\ args
The resulting script will forward the provided arguments.
.It Fl e , Fl -empty
The resulting script will not pass arguments to the target binary.
.It Fl E , Fl -env-share
The resulting script will call the
.Xr env-share 1
utility.
.It Fl -find Ar root
The resulting script will locate the target binary in the given directory using
.Xr find 1 .
.It Fl h , Fl -help
Print a short help message.
.It Fl -or Ar fallback
The resulting script will fall back to the provided argument if the target is not executable.
.It Fl -pc Ar flags
The resulting script will pass the arguments converted with
.Xr path-convert 1 . path-convert will be invoked with the provided flags forwarded (use 'x' to forward no flags).
.It Fl q , Fl -quiet
The resulting script will redirect output to /dev/null and send the target to the background.
.El
.Sh EXIT STATUS
.Bl -tag -width Ds
.It 1
No
.Ar target
was provided.
.It 2
Path canonicalization failed; this typically indicates the
.Ar target
points to a file or directory that does not exist.
.El
.Sh EXAMPLES
Windows Explorer does not accept paths with spaces when executed from WSL. To generate a script to launch Windows Explorer:
.Pp
.Dl $ mkwin --pc=sqq /mnt/c/Windows/System32/explorer.exe > explorer.sh
.Pp
Windows Terminal's executable moves when updated. To generate a script to launch Windows Terminal:
.Pp
.Dl $ mkwin --empty --find='/mnt/c/Program Files/WindowsApps/Microsoft.WindowsTerminal*' WindowsTerminal.exe > wt.sh
.Pp
PowerShell has two versions (Core is user-installed) and doesn't inherit environment variables from WSL. To generate a script to call PowerShell Core with a fallback to Windows PowerShell and shared environment variables:
.Pp
.Dl $ mkwin -E '/mnt/c/Program Files/PowerShell/7/pwsh.exe' --or '/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe'
.Pp
.Sh SEE ALSO
.Xr env-share 1 ,
.Xr find 1 ,
.Xr path-convert 1
.Sh AUTHORS
.An -nosplit
.An Valerie Wolfe Aq Mt sleeplessval@gmail.com .

36
man/path-convert.1 Normal file
View file

@ -0,0 +1,36 @@
.Dd $Mdocdate$
.Dt PATH-CONVERT 1
.Os WSL
.Sh NAME
.Nm path-convert
.Nd canonicalize and convert Unix paths for use with DOS programs
.Sh SYNOPSIS
.Nm path-convert
.Op Fl hnqs
.Ar
.Sh DESCRIPTION
The
.Nm
utility converts UNIX paths to DOS, for command substituting paths when invoking Windows executables from the terminal in WSL.
.Pp
Arguments that fail to canonicalize will be passed through as-is.
.Pp
Its options are as follows:
.Bl -tag -width Ds
.It Fl h , Fl -help
Displays a short help text.
.It Fl n , Fl -network
Adds the WSL network path where appropriate.
.It Fl q , Fl -quotes
Surrounds each converted path with single quotes (-q) or double quotes (-qq).
.It Fl s , Fl -no-space
Uses DOS shortening for directories in the path whose name contains spaces.
.El
.Sh ENVIRONMENT
.Bl -tag -width Ds
.It Ev WSL_DISTRO_NAME
This should be auto-set by WSL, and contains the name of the current distribution.
.El
.Sh AUTHORS
.An -nosplit
.An Valerie Wolfe Aq Mt sleeplessval@gmail.com .

47
man/wt.1 Normal file
View file

@ -0,0 +1,47 @@
.Dd $Mdocdate$
.Dt WT 1
.Os MICROSOFT WINDOWS
.Sh NAME
.Nm wt
.Nd Windows Terminal
.Sh SYNOPSIS
.Nm
.Op Fl hfv
.Op Fl F|M
.Op Fl -pos Ar x,y
.Op Fl -profile Ar name
.Op Fl -size Ar c,r
.Op Ar commandline
.Sh DESCRIPTION
.Nm
is a Linux wrapper for Windows Terminal. Its options are as follows:
.Bl -tag -width Ds
.It Fl h , Fl -help
Opens a dialog displaying help information.
.It Fl e
Launches the program with administrator privileges.
.It Fl f , Fl -focus
Launches the program with no title or tab bar.
.It Fl F , Fl -fullscreen
Launches the program in fullscreen mode. Conflicts with
.Fl -maximized .
.It Fl M , Fl -maximized
Launches the program in a maximized window. Conflicts with
.Fl -fullscreen .
.It Fl -pos Ar x,y
Launches the program at the given screen position.
.It Fl -profile Ar name
Launches the profile with the given
.Ar name
.
.It Fl -size Ar c,r
Launches the program with the given size in columns and rows respectively.
.It Fl v , Fl -version
Opens a dialog displaying version information.
.It Ar commandline
Attempt to run the given Windows command as the command line.
.El
.Sh BUGS
The official documentations (online and via
.Fl h )
contain a variety of errors, including deprecated/unsupported flags, and subcommands, which do not work.

2
mkwin/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
Cargo.lock

16
mkwin/Cargo.toml Normal file
View file

@ -0,0 +1,16 @@
[package]
name = "mkwin"
version = "0.2.0"
edition = "2021"
[dependencies]
pico-args = { version = "0.5.0", features = [ "eq-separator" ] }
[profile.release]
opt-level = 's'
codegen-units = 1
debug = false
lto = true
panic = "abort"
strip = "symbols"

10
mkwin/justfile Normal file
View file

@ -0,0 +1,10 @@
alias b := build
alias i := install
build:
cargo build --release
install DIR: build
cp ./target/release/mkwin "{{DIR}}/mkwin"

16
mkwin/src/error.rs Normal file
View file

@ -0,0 +1,16 @@
//! error handling code
use std::process::exit;
/// no argument for target; code 1
pub fn missing_target() -> ! {
eprintln!("mkwin: missing target");
exit(1);
}
/// failed to canonicalize target path; code 2
pub fn canonicalize_fail(target: String) -> ! {
eprintln!("mkwin: failed to canonicalze '{target}'--does the file exist?");
exit(2);
}

10
mkwin/src/flag.rs Normal file
View file

@ -0,0 +1,10 @@
//! constants for flag arguments
pub const HELP: [&str;2] = ["-h", "--help"];
pub const EMPTY: [&str;2] = ["-e", "--empty"];
pub const ENV_SHARE: [&str;2] = ["-E", "--env-share"];
pub const FIND_BIN: &str = "--find";
pub const OR: &str = "--or";
pub const PATH_CONVERT: &str = "--pc";
pub const QUIET: [&str;2] = ["-q", "--quiet"];

152
mkwin/src/main.rs Normal file
View file

@ -0,0 +1,152 @@
use std::path::Path;
use pico_args::Arguments;
mod error;
mod flag;
pub fn main() {
let mut args = Arguments::from_env();
// build reference string
let mut arg_string = String::new();
let mut arg_vec = args.clone().finish();
for arg in &arg_vec {
arg_string += &format!(" {}", arg.to_str().unwrap());
}
// drain forwarded arguments
let forwarded: String;
if let Some(position) = arg_vec.iter().position(|a| a == "--") {
let mut build = String::new();
for arg in arg_vec.drain(position+1..) {
build = format!("{build} {}", arg.to_str().unwrap());
}
arg_vec.pop();
args = Arguments::from_vec(arg_vec);
forwarded = build;
} else { forwarded = String::new(); }
// consume breaking flags
if args.contains(flag::HELP) {
help_text();
return;
}
// consume path convert flag
let path_convert: bool;
let path_convert_flags: Option<String>;
match args.value_from_str(flag::PATH_CONVERT) {
Ok(flags) => {
path_convert = true;
path_convert_flags = if flags != "x" { Some(flags) } else { None };
},
Err(pico_args::Error::OptionWithoutAValue(_)) => {
path_convert = true;
path_convert_flags = None;
},
_ => {
path_convert = false;
path_convert_flags = None;
}
}
// consume find binary flag
let find_bin: Option<String>;
match args.value_from_str::<&str, String>(flag::FIND_BIN) {
Ok(inner) => find_bin = Some(inner),
_ => find_bin = None
}
// consume simple flags
let empty = args.contains(flag::EMPTY);
let env_share = args.contains(flag::ENV_SHARE);
let quiet = args.contains(flag::QUIET);
// get target executable
let target: String;
if let Ok(Some(arg)) = args.subcommand() {
if let Some(root) = &find_bin { // handle find binary flag
target = format!("`find {root} -name '{arg}'`");
} else { // handle normal path
let path = Path::new(&arg);
if let Ok(path) = path.canonicalize() {
let path: String = path.to_string_lossy().into();
target = format!("'{path}'");
} else { error::canonicalize_fail(arg); }
}
} else { error::missing_target(); }
let exec =
if let Ok(alt) = args.value_from_str::<&str, String>(flag::OR) {
format!("target={target}\nif [ ! -x \"$target\" ]; then\n\ttarget='{alt}'\nfi\n\n\"$target\"")
} else if find_bin.is_some() {
format!("\"{target}\"")
} else { target };
// construct output
println!("#!/usr/bin/bash\n# generated with: mkwin{arg_string}\n");
if env_share { println!("env-share 2> /dev/null\n"); }
print!("{exec}");
// handle forwarded arguments
if !forwarded.is_empty() {
print!("{forwarded}");
}
// handle empty flag
if !empty {
// handle path convert flag
if path_convert {
let flags = if let Some(i) = path_convert_flags { format!(" -{i}") } else { String::new() };
print!(" `path-convert{flags} $@`");
} else {
print!(" $@");
}
}
// handle quiet flag
if quiet {
print!(" > /dev/null 2>&1 &");
}
println!();
}
pub fn help_text() {
println!("mkwin v{}
Valerie Wolfe <sleeplessval@gmail.com>
Quickly make bash scripts to run Windows programs from WSL.
usage: mkwin [flags] <target> [-- args]
args:
<target> The target program the resulting script will run.
[-- args] Arguments forwarded to the target program. These are placed
before any other arguments in the resulting script.
flags:
-h, --help Show this help text and exit.
-e, --empty The resulting script will not pass arguments.
-E, --env-share The resulting script will use the 'env-share' utility to
share environment variables before calling the target
binary.
--find=<root> The resulting script will use the 'find' utility to locate
the target binary in the given directory. The value given by
root is passed verbatim to 'find', unexpanded.
--pc=<flags> The resulting script will use the 'path-convert' tool to
convert arguments from UNIX to DOS, with the provided set of
flags ('x' for no flags).
-q, --quiet The resulting script will run the target program in the
background and redirect all output to '/dev/null'.",
env!("CARGO_PKG_VERSION"));
}

View file

@ -1 +1,2 @@
/target
Cargo.lock

View file

@ -1,6 +1,6 @@
[package]
name = "path-convert"
version = "0.0.4"
version = "0.0.7"
edition = "2021"
[dependencies]

10
path-convert/justfile Normal file
View file

@ -0,0 +1,10 @@
alias b := build
alias i := install
build:
cargo build --release
install DIR: build
cp ./target/release/path-convert "{{DIR}}/path-convert"

View file

@ -2,9 +2,15 @@ use std::path::{ Path, PathBuf };
use pico_args::Arguments;
// - HELPER -
const DRIVE: &str = "/mnt/c/";
// - ENV -
const DISTRO: &str = "WSL_DISTRO_NAME";
// - FLAGS -
const HELP: [&str;2] = [ "-h", "--help" ];
const NET_PATH: [&str;2] = [ "-n", "--network" ];
const NO_SPACES: [&str;2] = [ "-s", "--no-space" ];
const QUOTED: [&str;2] = [ "-q", "--quotes" ];
@ -19,75 +25,82 @@ pub fn main() {
// handle quote flag
let quotes: &str =
if args.contains(QUOTED) {
if args.contains(QUOTED) { "\"" } // -qq -> "..." (output with double quotes)
else { "'" } // -q -> '...' (output with single quotes)
} else { "" }; // _ -> ... (output with no quotes)
if args.contains(QUOTED) {
if args.contains(QUOTED) { "\"" } // -qq -> "..." (output with double quotes)
else { "'" } // -q -> '...' (output with single quotes)
} else { "" }; // _ -> ... (output with no quotes)
// collect no-space flag
// consume simple flags
let no_spaces = args.contains(NO_SPACES);
let network_path = args.contains(NET_PATH);
loop {
let next = args.subcommand().unwrap();
if let Some(arg) = next {
let mut output: String;
// canonicalize; windows doesn't recognize symlinks
let path = Path::new(&arg).canonicalize();
if let Ok(target) = path {
output = target.to_string_lossy().to_string();
let mut targets = args.finish();
// for empty args, just do cwd
if targets.len() == 0 { targets.push(".".into()) ; }
for target in targets {
let target = target.to_string_lossy().to_string();
// canonicalize; windows doesn't recognize symlinks
let path = Path::new(&target).canonicalize();
let mut output: String =
if let Ok(canonical) = path {
canonical.to_string_lossy().to_string()
} else {
output = arg;
}
println!("{quotes}{target}{quotes}");
continue;
};
// handle no-space flag
if no_spaces {
let tmp = output.clone();
let parts = tmp.split('/');
let mut current = PathBuf::new();
current.push("/");
for part in parts {
if part.is_empty() { continue; }
let space = part.chars().position(|c| c == ' ');
let len = part.len();
// if space is found, use short version
if let Some(index) = space {
// find cut point and make slice
let cut = usize::min(len, index).min(6);
let replace = &(part[..cut]);
// handle no-space flag
if no_spaces {
let tmp = output.clone();
let parts = tmp.split('/');
let mut current = PathBuf::new();
current.push("/");
for part in parts {
if part.is_empty() { continue; }
let space = part.chars().position(|c| c == ' ');
let len = part.len();
// if a space is found, use short version
if let Some(index) = space {
// find cut point and slice
let cut = usize::min(len, index).min(6);
let replace = &(part[..cut]);
// determine number for shortening
let mut index = 0;
let children = current.read_dir();
if !children.is_ok() { continue; }
// determine shortened index
let mut index = 0;
let children = current.read_dir();
if !children.is_ok() { continue; }
for child in children.unwrap() {
if let Ok(child) = child {
let name: String = child.file_name().to_string_lossy().into();
// matches increment
if name.to_lowercase().starts_with(&replace.to_lowercase()) { index += 1; }
// ... and break when we hit the target
if name == part { break; }
}
for child in children.unwrap() {
if let Ok(child) = child {
let name: String = child.file_name().to_string_lossy().to_string();
// matching names increment index
if name.to_lowercase().starts_with(&replace.to_lowercase()) { index += 1; }
// ... and break when we hit the target
if name == part { break; }
}
output = output.replacen(part, &format!("{replace}~{index}"), 1);
}
current.push(part);
output = output.replacen(part, &format!("{replace}~{index}"), 1);
}
current.push(part);
}
// simple C-drive substitution
if output.starts_with(DRIVE) {
output = output.replace(DRIVE, "C:\\");
}
// switch out separators
output = output.replace("/", "\\");
// emit to stdout
println!("{quotes}{output}{quotes}");
} else {
break;
}
// very basic C-drive substitution
if output.starts_with(DRIVE) {
output = output.replace(DRIVE, "C:\\");
} else if network_path {
let name = std::env::var(DISTRO);
if let Ok(name) = name {
output = format!("//wsl.localhost/{name}{output}");
}
}
// switch out separators
output = output.replace("/", "\\");
// emit to stdout
println!("{quotes}{output}{quotes}");
}
}
@ -100,12 +113,13 @@ Canonicalize and convert Unix paths for DOS programs.
usage: path-convert [flags] <paths...>
args:
<paths...> one or more paths to convert
<paths...> One or more paths to convert
flags:
-h, --help show this help text
-q, --quotes surround the output strings with quotes (-qq for double quotes)
-s, --no-space don't allow paths to have spaces
-h, --help Show this help text
-n, --network Add the network path where appropriate
-q, --quotes Surround the output strings with quotes (-qq for double quotes)
-s, --no-space Don't allow paths to have spaces
", env!("CARGO_PKG_VERSION"));
}

2
qdls/.gitignore vendored
View file

@ -1,4 +1,4 @@
obj/
bin/
.idea/
qdls.exe

11
qdls/justfile Normal file
View file

@ -0,0 +1,11 @@
alias b := build
alias i := install
build:
dos dotnet warp
install DIR: build
chmod +x qdls.exe
mv qdls.exe {{DIR}}/qdls

4
scripts/charmap.sh Executable file
View file

@ -0,0 +1,4 @@
#!/usr/bin/bash
# generated with: mkwin /mnt/c/Windows/System32/charmap.exe -eq
'/mnt/c/Windows/System32/charmap.exe' $@

21
scripts/cmd.sh Executable file
View file

@ -0,0 +1,21 @@
#!/usr/bin/bash
if [ "$#" -ne 0 ]; then
args=''
for arg in $@; do
if [[ $arg =~ ^-.+$ ]]; then
transform=(${arg//-//})
if [[ $arg =~ ^-.+=.+$ ]]; then
transform=(${transform//=/:})
fi
args="$args $transform"
else
args="$args $arg"
fi
done
/mnt/c/Windows/System32/cmd.exe $args
else
/mnt/c/Windows/System32/cmd.exe
fi

8
scripts/dos.sh Executable file
View file

@ -0,0 +1,8 @@
#!/usr/bin/bash
if [ "$#" -eq 0 ]; then
pwsh
else
pwsh -C "$@"
fi

42
scripts/elevate.sh Executable file
View file

@ -0,0 +1,42 @@
#!/usr/bin/bash
# error if 'pwsh' not in path
if [ ! which pwsh > /dev/null 2>&1 ]; then
echo "no 'pwsh' in \$PATH"
exit 1
fi
# set mode (linux/dos)
if [[ "$1" == "-l" ]]; then
mode='linux'
shift
elif [[ "$1" == "-w" ]]; then
mode='dos'
shift
# error if no target for DOS
if [ "$#" -eq 0 ]; then
echo "elevate: DOS mode requires a target"
exit 3
fi
fi
# consume target based on mode
if [[ "$mode" == "linux" ]]; then
target='wsl.exe'
elif [[ "$mode" == "dos" ]]; then
target="$1"
shift
else
echo "elevate: no mode set; use '-l' or '-w'"
exit 2
fi
# consume remaining arguments
arglist=''
if [ "$#" -ne 0 ]; then
arglist="-ArgumentList '$@'"
fi
# execute
pwsh -C "Start-Process -Verb runas $target $arglist"

View file

@ -1,5 +1,4 @@
#!/usr/bin/bash
# generated with: mkwin /mnt/c/Windows/explorer.exe --pc=s
# launch explorer with converted path(s)
'/mnt/c/Windows/explorer.exe' `path-convert -s $@`

13
scripts/justfile Normal file
View file

@ -0,0 +1,13 @@
alias i := install
install DIR="/usr/local/bin":
cp charmap {{DIR}}/charmap
cp cmd.sh {{DIR}}/cmd
cp dos.sh {{DIR}}/dos
cp elevate.sh {{DIR}}/elevate
cp explorer.sh {{DIR}}/explorer
cp pwsh.sh {{DIR}}/pwsh
cp wsl.sh {{DIR}}/wsl
cp wt.sh {{DIR}}/wt

11
scripts/pwsh.sh Executable file
View file

@ -0,0 +1,11 @@
#!/usr/bin/bash
# generated with: mkwin /mnt/c/Program Files/PowerShell/7/pwsh.exe -E --or /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe
env-share 2> /dev/null
target='/mnt/c/Program Files/PowerShell/7/pwsh.exe'
if [ ! -x "$target" ]; then
target='/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe'
fi
"$target" $@

4
scripts/sqlcmd.sh Executable file
View file

@ -0,0 +1,4 @@
#!/usr/bin/bash
# generated with: mkwin /mnt/c/Program Files/SqlCmd/sqlcmd.exe
'/mnt/c/Program Files/SqlCmd/sqlcmd.exe' $@

7
scripts/wsl.sh Executable file
View file

@ -0,0 +1,7 @@
#!/usr/bin/bash
if [[ ! -t 1 ]]; then
WRAPPER='hug'
fi
$WRAPPER '/mnt/c/Windows/System32/wsl.exe' $@

11
scripts/wt.sh Executable file
View file

@ -0,0 +1,11 @@
#!/usr/bin/bash
if [[ "$1" == "-e" ]]; then
elevate -l wt
exit
fi
cd '/mnt/c/Program Files/WindowsApps/'
target=`find Microsoft.WindowsTerminal* -name 'WindowsTerminal.exe'`
dos "$target" $@