Compare commits

..

56 commits
just ... main

Author SHA1 Message Date
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
40 changed files with 814 additions and 98 deletions

View file

@ -1,7 +1,21 @@
# 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`
@ -18,14 +32,26 @@ 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.
- `terminal.sh`: Launch Windows Terminal.
- `pwsh.sh`: Launch PowerShell Core.
- `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

2
dos-var/.gitignore vendored Normal file
View file

@ -0,0 +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),
}
}
}
}

View file

@ -5,13 +5,17 @@ alias i := install
build TARGET:
just {{TARGET}}/build
install TARGET='all' DIR="~/.bin/":
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.

View file

@ -1,6 +1,6 @@
[package]
name = "mkwin"
version = "0.0.3"
version = "0.2.0"
edition = "2021"
[dependencies]

View file

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

View file

@ -1,7 +1,10 @@
//! constants for flag arguments
pub const HELP: [&str;2] = ["-h", "--help"];
pub const EMPTY: &str = "--empty";
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"];

View file

@ -51,27 +51,45 @@ pub fn main() {
}
}
// 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 quiet = args.contains(flag::QUIET);
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() {
let path = Path::new(&arg);
if let Ok(path) = path.canonicalize() {
target = path.to_string_lossy().into();
} else {
error::canonicalize_fail(arg);
return;
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();
return;
}
} 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
print!("#!/usr/bin/bash\n# generated with: mkwin{arg_string}\n\n'{target}'");
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() {
@ -113,7 +131,15 @@ args:
flags:
-h, --help Show this help text and exit.
--empty The resulting script will not pass arguments.
-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

View file

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

View file

@ -25,81 +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)
// 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:\\");
} 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}");
} 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}");
}
}

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

View file

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

View file

@ -13,12 +13,11 @@ if [[ "$1" == "-l" ]]; then
elif [[ "$1" == "-w" ]]; then
mode='dos'
shift
fi
# error if no target
if [ "$#" -eq 0 ]; then
echo "elevate: no target"
exit 3
# 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

View file

@ -1,9 +1,13 @@
alias i := install
install DIR="~/.bin":
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 terminal.sh {{DIR}}/terminal
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" $@

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' $@

View file

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