This commit is contained in:
mingyang 2020-12-14 15:18:34 +08:00
parent 5a0dba9ea6
commit fddb7800f7
2 changed files with 194 additions and 1 deletions

View File

@ -1,3 +1,20 @@
# Watch-On-Windows # Watch-On-Windows
Since "watch" command on windows requires Cygwin and some people like me do not want to install such an package, i wrote a naive one. Watch command is frequently used on linux while there is no such things on windows. To use watch command on windows, one might need to install Cygwin or something similar, which is not acceptable for some users like me. To use this command on windows, I wrote a naive watch command.
## How to compile this
Just run the following command. (GCC is required, or you can us visual studio)
```bat
g++ -Wall -O2 -static watch.cpp -o watch.exe
```
## How to use
Only the basic functionality is implenmented. The command line arguments are as follows:
```bat
watch <interval> <your exe>
```
Here are some examples:
```bat
watch 0.1 nvidia-smi
watch 1 nvidia-smi -q -d CLOCK
```

176
watch.cpp Normal file
View File

@ -0,0 +1,176 @@
#include <cstdio>
#include <cstdlib>
#include <Windows.h>
#include <iostream>
#include <vector>
#include <ctime>
#include <ratio>
#include <chrono>
using hclock = std::chrono::high_resolution_clock;
using duration = std::chrono::duration<double>;
int execmd(char* cmd,char* result) {
char buffer[512];
FILE* pipe = _popen(cmd, "r");
if (!pipe)
return 0;
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe)){
strcat(result,buffer);
}
}
_pclose(pipe);
return 0;
}
std::string GetCommandOutput(std::string command)
{
std::string result("");
char buffer[1024];
FILE* pipe = _popen(command.c_str(), "r");
if (!pipe) return 0;
while (!feof(pipe))
{
if (fgets(buffer, 1024, pipe)) {
result += buffer;
}
}
return result;
}
std::vector<std::string> split(std::string& str, std::string delemeter)
{
std::vector<std::string> strs;
size_t delsize = delemeter.size();
while (str.size() > 0) {
size_t delpos = str.find(delemeter);
if (delpos == std::string::npos) {
strs.push_back(str);
} else {
strs.push_back(str.substr(0, delpos));
str = str.substr(delpos + delsize);
}
}
return strs;
}
struct ConsoleSize {
size_t w = 0;
size_t h = 0;
};
ConsoleSize get_console_size(std::string& content)
{
std::vector<std::string> strs = split(content, "\n");
ConsoleSize sz;
sz.h = strs.size();
for (size_t i = 0; i < strs.size(); i++) {
if (strs[i].size() > sz.w) {
sz.w = strs[i].size();
}
}
return sz;
}
void Trimmedoutput(std::string& content, size_t max_w, size_t max_h)
{
std::vector<std::string> strs = split(content, "\n");
size_t lines = max_h > strs.size()?strs.size():max_h;
for (size_t i = 0; i < lines; i++) {
std::string str = strs[i];
if (str.size() > max_w) {
str = str.substr(0, max_w);
}
else if (str.size() < max_w) {
str += std::string(max_w - str.size(), ' ');
}
std::cout<<str<<"\n";
}
if (lines < max_h) {
std::string empty = std::string(max_w, ' ');
for (size_t i = 0; i < max_h - lines; i++) {
std::cout<<empty<<std::endl;
}
}
}
int main(int argc, char const *argv[])
{
// lets parse arguments first.
if (argc < 3) {
std::cerr<<"Params not understood, usage: watch interval:float command:str"<<std::endl;
return 1;
}
double interval = std::stod(argv[1]);
std::string command("");
for (int i = 2; i < argc; i++) {
command += argv[i];
command += " ";
}
HANDLE hOutput;
COORD coord={0,0};
hOutput=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cci;
cci.bVisible = 0;
cci.dwSize = 1;
SetConsoleCursorInfo(hOutput, &cci);
// std::string command = "ipconfig";
std::string output = GetCommandOutput(command);
ConsoleSize sz = get_console_size(output);
if (sz.w < 10) {
sz.w = 10;
}
if (sz.h < 5) {
sz.h = 5;
}
SMALL_RECT rc;
rc.Left = 0;
rc.Top = 0;
rc.Right = sz.w;
rc.Bottom = sz.h;
SetConsoleWindowInfo(hOutput, TRUE, &rc);
size_t prev_w = sz.w;
size_t prev_h = sz.h;
while (1)
{
hclock::time_point t1 = hclock::now();
SetConsoleCursorPosition(hOutput, coord);
CONSOLE_CURSOR_INFO cci;
cci.bVisible = 0;
cci.dwSize = 1;
SetConsoleCursorInfo(hOutput, &cci);
std::string output = GetCommandOutput(command);
size_t w = 0;
size_t h = 0;
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
w = csbi.srWindow.Right - csbi.srWindow.Left;
h = csbi.srWindow.Bottom - csbi.srWindow.Top;
if (w != prev_w or h != prev_h) {
system("cls");
prev_w = w;
prev_h = h;
}
Trimmedoutput(output, w, h);
hclock::time_point t2 = hclock::now();
double elasped = std::chrono::duration_cast<duration>(t2 - t1).count();
double remeaning = interval - elasped;
if (remeaning > 0) {
Sleep(int(remeaning * 1000));
}
}
return 0;
}