Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 12.88.0 #405

Merged
merged 5 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .scripts/packages.list
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* + mathutil
L + netutil
* + options
* + pager
* + passwd
* + path
* + pid
Expand All @@ -53,7 +54,8 @@ L - system/process
* - system/procname
L + system/sensors
* - terminal
* ! terminal/window
* ! terminal/tty
* - terminal/window
* + timeutil
* + tmp
* + usage
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
## Changelog

### 12.88.0

* `[pager]` Added new package for pager (`less`/`more`) setup
* `[terminal/tty]` Added new package for working with TTY
* `[fmtc]` Added method `IsColorsSupported`

### 12.87.0

* `[fmtc]` Added tag for italic text (`{&}`)
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ If you are using SublimeText 4 (`4075+`), we strongly recommend that you install
* [`mathutil`](https://kaos.sh/g/ek.v12/mathutil) — Package provides some additional math methods
* [`netutil`](https://kaos.sh/g/ek.v12/netutil) — Package provides methods for working with network
* [`options`](https://kaos.sh/g/ek.v12/options) — Package provides methods for working with command-line options
* [`pager`](https://kaos.sh/g/ek.v12/pager) — Package provides methods for pager setup (more/less)
* [`passwd`](https://kaos.sh/g/ek.v12/passwd) — Package contains methods for working with passwords
* [`path`](https://kaos.sh/g/ek.v12/path) — Package for working with paths (fully compatible with base path package)
* [`pid`](https://kaos.sh/g/ek.v12/pid) — Package for working with PID files
Expand All @@ -99,7 +100,7 @@ If you are using SublimeText 4 (`4075+`), we strongly recommend that you install
* [`system/sensors`](https://kaos.sh/g/ek.v12/system/sensors) — Package provide methods for collecting sensors information
* [`system`](https://kaos.sh/g/ek.v12/system) — Package provides methods for working with system data (metrics/users)
* [`terminal`](https://kaos.sh/g/ek.v12/terminal) — Package provides methods for working with user input
* [`terminal/window`](https://kaos.sh/g/ek.v12/terminal/window) — Package provides methods for working terminal window
* [`terminal/tty`](https://kaos.sh/g/ek.v12/terminal/tty) — Package provides methods for working with TTY
* [`timeutil`](https://kaos.sh/g/ek.v12/timeutil) — Package provides methods for working with time and date
* [`tmp`](https://kaos.sh/g/ek.v12/tmp) — Package provides methods for working with temporary data
* [`usage`](https://kaos.sh/g/ek.v12/usage) — Package usage provides methods and structs for generating usage info for command-line tools
Expand Down
2 changes: 1 addition & 1 deletion ek.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
// ////////////////////////////////////////////////////////////////////////////////// //

// VERSION is current ek package version
const VERSION = "12.87.0"
const VERSION = "12.88.0"

// ////////////////////////////////////////////////////////////////////////////////// //

Expand Down
4 changes: 4 additions & 0 deletions fmtc/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,10 @@ func ExampleClean() {
// Output: Text
}

func ExampleIsColorsSupported() {
fmt.Printf("16 Colors Supported: %t\n", IsColorsSupported())
}

func ExampleIs256ColorsSupported() {
fmt.Printf("256 Colors Supported: %t\n", Is256ColorsSupported())
}
Expand Down
23 changes: 21 additions & 2 deletions fmtc/fmtc.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@ var DisableColors = os.Getenv("NO_COLOR") != ""

// ////////////////////////////////////////////////////////////////////////////////// //

var colors256Supported bool
var colorsTCSupported bool
var colorsSupported bool // 16 colors support
var colors256Supported bool // 256 colors support
var colorsTCSupported bool // 24bit (TrueColor) colors support
var colorsSupportChecked bool

var colorsMap *sync.Map
Expand Down Expand Up @@ -328,6 +329,17 @@ func Bell() {
fmt.Print(_CODE_BELL)
}

// IsColorsSupported returns true if 16 colors is supported by terminal
func IsColorsSupported() bool {
if colorsSupportChecked {
return colorsSupported
}

checkForColorsSupport()

return colorsSupported
}

// Is256ColorsSupported returns true if 256 colors is supported by terminal
func Is256ColorsSupported() bool {
if colorsSupportChecked {
Expand Down Expand Up @@ -644,6 +656,13 @@ func isValidNamedTag(tag string) bool {
}

func checkForColorsSupport() {
switch {
case strings.Contains(term, "xterm"),
strings.Contains(term, "color"),
term == "screen":
colorsSupported = true
}

if strings.Contains(term, "256color") {
colors256Supported = true
}
Expand Down
1 change: 1 addition & 0 deletions fmtc/fmtc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ func (s *FormatSuite) Test24BitColors(c *C) {

c.Assert(IsTrueColorSupported(), Equals, true)
c.Assert(Is256ColorsSupported(), Equals, true)
c.Assert(IsColorsSupported(), Equals, true)

colorsSupportChecked = false
colors256Supported = false
Expand Down
20 changes: 20 additions & 0 deletions pager/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package pager

// ////////////////////////////////////////////////////////////////////////////////// //
// //
// Copyright (c) 2023 ESSENTIAL KAOS //
// Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0> //
// //
// ////////////////////////////////////////////////////////////////////////////////// //

func ExampleSetup() {
// Use pager from PAGER env var or default (more)
Setup("")

// Or provide specific command.
Setup("less -MQR")

// Complete must be called at the end of the program work. You can call it with defer
// in your main function.
defer Complete()
}
95 changes: 95 additions & 0 deletions pager/pager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Package pager provides methods for pager setup (more/less)
package pager

// ////////////////////////////////////////////////////////////////////////////////// //
// //
// Copyright (c) 2023 ESSENTIAL KAOS //
// Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0> //
// //
// ////////////////////////////////////////////////////////////////////////////////// //

import (
"errors"
"os"
"os/exec"
"strings"
)

// ////////////////////////////////////////////////////////////////////////////////// //

// DEFAULT is default pager command
const DEFAULT = "more"

// ////////////////////////////////////////////////////////////////////////////////// //

var pagerCmd *exec.Cmd
var pagerOut *os.File

var stdout *os.File
var stderr *os.File

// ////////////////////////////////////////////////////////////////////////////////// //

var ErrAlreadySet = errors.New("Pager already set")

// ////////////////////////////////////////////////////////////////////////////////// //

// Setup set up pager for work. After calling this method, any data sent to Stdout and
// Stderr (using fmt, fmtc, or terminal packages) will go to the pager.
func Setup(pager string) error {
if pagerCmd != nil {
return ErrAlreadySet
}

pagerCmd = getPagerCommand(pager)

pagerCmd.Stdout, stdout = os.Stdout, os.Stdout
pagerCmd.Stderr, stderr = os.Stderr, os.Stderr

w, err := pagerCmd.StdinPipe()

if err != nil {
return err
}

pagerOut = w.(*os.File)
os.Stdout = pagerOut

return pagerCmd.Start()
}

// Complete finishes pager work
func Complete() {
if pagerOut != nil {
pagerOut.Close()
pagerOut = nil
}

if pagerCmd != nil {
pagerCmd.Wait()
pagerCmd = nil
}

os.Stdout = stdout
os.Stderr = stderr
}

// ////////////////////////////////////////////////////////////////////////////////// //

// getPagerCommand creates command for pager
func getPagerCommand(pager string) *exec.Cmd {
if pager == "" {
pager = os.Getenv("PAGER")
}

if pager == "" {
pager = DEFAULT
}

if strings.Contains(pager, " ") {
cmdSlice := strings.Fields(pager)
return exec.Command(cmdSlice[0], cmdSlice[1:]...)
}

return exec.Command(pager)
}
55 changes: 55 additions & 0 deletions pager/pager_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package pager

// ////////////////////////////////////////////////////////////////////////////////// //
// //
// Copyright (c) 2023 ESSENTIAL KAOS //
// Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0> //
// //
// ////////////////////////////////////////////////////////////////////////////////// //

import (
"os"
"testing"

. "github.com/essentialkaos/check"
)

// ////////////////////////////////////////////////////////////////////////////////// //

func Test(t *testing.T) { TestingT(t) }

type PagerSuite struct{}

// ////////////////////////////////////////////////////////////////////////////////// //

var _ = Suite(&PagerSuite{})

// ////////////////////////////////////////////////////////////////////////////////// //

func (s *PagerSuite) TearDownSuite(c *C) {
Complete()
}

func (s *PagerSuite) TestPager(c *C) {
c.Assert(Setup("cat"), IsNil)
c.Assert(Setup("cat"), NotNil)

Complete()

c.Assert(pagerCmd, IsNil)
c.Assert(pagerOut, IsNil)
}

func (s *PagerSuite) TestPagerSearch(c *C) {
os.Setenv("PAGER", "")

cmd := getPagerCommand("cat")
c.Assert(cmd.Args, DeepEquals, []string{"cat"})

cmd = getPagerCommand("")
c.Assert(cmd.Args, DeepEquals, []string{"more"})

os.Setenv("PAGER", "less -MQR")
cmd = getPagerCommand("")
c.Assert(cmd.Args, DeepEquals, []string{"less", "-MQR"})
}
33 changes: 33 additions & 0 deletions pager/pager_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Package pager provides methods for pager setup (more/less)
package pager

// ////////////////////////////////////////////////////////////////////////////////// //
// //
// Copyright (c) 2023 ESSENTIAL KAOS //
// Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0> //
// //
// ////////////////////////////////////////////////////////////////////////////////// //

import "errors"

// ////////////////////////////////////////////////////////////////////////////////// //

// DEFAULT is default pager command
const DEFAULT = "more"

// ////////////////////////////////////////////////////////////////////////////////// //

var ErrAlreadySet = errors.New("Pager already set")

// ////////////////////////////////////////////////////////////////////////////////// //

// ❗ Setup set up pager for work. After calling this method, any data sent to Stdout and
// Stderr (using fmt, fmtc, or terminal packages) will go to the pager.
func Setup(pager string) error {
return nil
}

// ❗ Complete finishes pager work
func Complete() {
return
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package window
package tty

// ////////////////////////////////////////////////////////////////////////////////// //
// //
Expand Down
64 changes: 64 additions & 0 deletions terminal/tty/size_posix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//go:build !windows
// +build !windows

package tty

// ////////////////////////////////////////////////////////////////////////////////// //
// //
// Copyright (c) 2023 ESSENTIAL KAOS //
// Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0> //
// //
// ////////////////////////////////////////////////////////////////////////////////// //

import (
"os"
"syscall"
"unsafe"
)

// ////////////////////////////////////////////////////////////////////////////////// //

type winsize struct {
rows uint16
cols uint16
xpixels uint16
ypixels uint16
}

// ////////////////////////////////////////////////////////////////////////////////// //

// tty is a path to TTY device file
var tty = "/dev/tty"

// ////////////////////////////////////////////////////////////////////////////////// //

// GetSize returns window width and height
func GetSize() (int, int) {
t, err := os.OpenFile(tty, syscall.O_RDONLY, 0)

if err != nil {
return -1, -1
}

var sz winsize

_, _, _ = syscall.Syscall(
syscall.SYS_IOCTL, t.Fd(),
uintptr(syscall.TIOCGWINSZ),
uintptr(unsafe.Pointer(&sz)),
)

return int(sz.cols), int(sz.rows)
}

// GetWidth returns window width
func GetWidth() int {
w, _ := GetSize()
return w
}

// GetHeight returns window height
func GetHeight() int {
_, h := GetSize()
return h
}
Loading