cheat.sh
cheat.sh copied to clipboard
JSON output from site?
I feel like I must be missing something, but I can't find any mention of it: Is there no way to get data in JSON or another structured format from the site? It would make it much easier to cleanly present individual entries in clients.
Yes, it would be possible.
What exactly information would you encode in JSON?
Well, I only just discovered this project, and I don't fully grok its organization, so I will probably leave some things out. But how about this for starters:
- Programming language
- Subdirectory
- Comments
- Source code
- URL to view in browser
- Special page name when applicable
- Original source (i.e. StackOverflow, etc)
Yes, it is an interesting idea. Actually, we have all of this either in the URL of the query or in the output (bottom line), but the idea seems to be really interesting.
It would be much easier to implement a client without having to parse this out manually. In Python, if the data is well-organized, it could be as easy as serializing a list of dicts to JSON.
I would love to get the output as a JSON too.... this is the closest I could get so far.... still not being able to parse languages or special use cases like :help (mainly because the huge ammount of things to escape):
#!/usr/bin/env bash
###############################################
# Change the cheat sheet you want to search for
search_for="kubectl"
###############################################
result=$(/usr/bin/curl -s "cheat.sh/${search_for}?qT")
previous_line=""
json_array=""
command_buffer=""
SAVEIFS=$IFS # Save current IFS (Internal Field Separator)
IFS=$'\n' # Change IFS to newline char
for line in $result; do
# Escape chars like double quotes
line="${line//\"/\\\"}"
# Check if the line is a comment
if [[ "${line:0:1}" == '#' ]]; then
# It whe have commands on buffer
if [[ -n "${command_buffer}" ]]; then
# output to json array
new_element="{\"title\":\"$previous_line\",\"command\":\"${command_buffer}\"}"
if [[ -z "${json_array}" ]]; then
# Initialize the array
json_array=$new_element
else
# Append to the end of the array
json_array="${json_array},${new_element}"
fi
fi
# clear command buffer
command_buffer=""
previous_line=$line
else
# Puts the line on the buffer
if [[ -z "${command_buffer}" ]]; then
command_buffer="${line}"
else
command_buffer="${command_buffer}\n${line}"
fi
fi
done
# It whe still have commands on buffer
if [[ -n "${command_buffer}" ]]; then
# output to json array
new_element="{\"title\":\"$previous_line\",\"command\":\"${command_buffer}\"}"
if [[ -z "${json_array}" ]]; then
# Initialize the array
json_array=$new_element
else
# Append to the end of the array
json_array="${json_array},${new_element}"
fi
fi
# Append to the end of the array
json_array="{\"item\": \"$search_for\",\"cheat_sheets\": [${json_array}]}"
echo "$json_array" | /usr/local/bin/jq
IFS=$SAVEIFS # Restore original IFS
Example result:
{
"item": "kubectl",
"cheat_sheets": [
{
"title": "# Display list of all available commands",
"command": "kubectl -h"
},
{
"title": "# Display an explanation of a specific command",
"command": "kubectl command_name -h"
},
{
"title": "# Display complete list of supported resources",
"command": "kubectl api-resources"
},
{
"title": "# Display an explanation of a specific reource",
"command": "kubectl explain resource_name"
},
{
"title": "# Display an explanation of a specific field of resource",
"command": "kubectl explain resource_name.field_name"
},
{
"title": "# Display list of global command-line options",
"command": "kubectl options"
},
{
"title": "# Setup Kubectl autocomplete in bash(to use press Tab)",
"command": "source <(kubectl completion bash"
},
{
"title": "# Display all resources in all namespaces",
"command": "kubectl get all -A"
},
{
"title": "# List all information about a resource with more details:",
"command": "kubectl get pod|service|deployment|ingress|... -o "
},
{
"title": "# Update specified pod with the label 'unhealthy' and the value 'true':",
"command": "kubectl label pods name unhealthy=true"
},
{
"title": "# List all resources with different types:",
"command": "kubectl get all"
},
{
"title": "# Display resource (CPU/Memory/Storage) usage of nodes or pods:",
"command": "kubectl top pod|node"
},
{
"title": "# Print the address of the master and cluster services:",
"command": "kubectl cluster-info"
},
{
"title": "# Display an explanation of a specific field:",
"command": "kubectl explain pods.spec.containers"
},
{
"title": "# Print the logs for a container in a pod or specified resource:",
"command": "kubectl logs pod_name"
},
{
"title": "# Run command in an existing pod:",
"command": "kubectl exec pod_name -- ls /"
}
]
}
The JSON output is desired for me because of this project: https://github.com/gohoyer/Alfred-Cheat.sh
Looks like the formatting part is already there.
https://github.com/chubin/cheat.sh/blob/46d1a5f73c6b88da15d809154245dbf234e9479e/lib/cheat_wrapper.py#L119-L120
But the web server doesn't contain the logic to select it.
https://github.com/chubin/cheat.sh/blob/46d1a5f73c6b88da15d809154245dbf234e9479e/bin/app.py#L290-L293
I also support this, json output would enable a lot of extra tools to work with it.
@chrisgrieser support like financially, with code, or just +1?
The latter 😅
@gohoyer It is a cool project. I like it a lot, and I think it is worth to add its input format as a standard output for for cheat.sh.
Maybe something like format=alfred.
Let's define the exact format, and then it could be easily implemented on the server side.
Does your example above contain all possible elements, or more elements are possible?
{
"item": "kubectl",
"cheat_sheets": [
{
"title": "# Display list of all available commands",
"command": "kubectl -h"
},
{
"title": "# Display an explanation of a specific command",
"command": "kubectl command_name -h"
}
}
}
@chubin, here`s the official JSON Format for an Alfred Script Filter: https://www.alfredapp.com/help/workflows/inputs/script-filter/json/
{"items": [
{
"uid": "desktop",
"type": "file",
"title": "Desktop",
"subtitle": "~/Desktop",
"arg": "~/Desktop",
"autocomplete": "Desktop",
"icon": {
"type": "fileicon",
"path": "~/Desktop"
}
}
]}
The format I`m currently using on the project is:
{"items": [
{
"title": "comments/command title",
"subtitle": "commmand",
"text": {
"copy": "command",
"largetype": "comments/command title"
},
"arg": "command",
"autocomplete": "comments/command title"
},
{
"title": "comments/command title",
"subtitle": "commmand",
"text": {
"copy": "command",
"largetype": "comments/command title"
},
"arg": "command",
"autocomplete": "comments/command title"
},
]
}
Here`s the script that do this trick: https://github.com/gohoyer/Alfred-Cheat.sh/blob/main/get_details.sh
Real example of 7z details:
{
"items": [
{
"title": "# Encrypt an existing archive (including headers):",
"subtitle": "7z a encrypted.7z -ppassword -mhe=on archived.7z",
"text": {
"copy": "7z a encrypted.7z -ppassword -mhe=on archived.7z",
"largetype": "# Encrypt an existing archive (including headers):"
},
"arg": "7z a encrypted.7z -ppassword -mhe=on archived.7z",
"autocomplete": "# Encrypt an existing archive (including headers):"
},
{
"title": "# Extract an existing 7z file with original directory structure:",
"subtitle": "7z x archived.7z",
"text": {
"copy": "7z x archived.7z",
"largetype": "# Extract an existing 7z file with original directory structure:"
},
"arg": "7z x archived.7z",
"autocomplete": "# Extract an existing 7z file with original directory structure:"
},
{
"title": "# Extract an archive with user-defined output path:",
"subtitle": "7z x archived.7z -opath/to/output",
"text": {
"copy": "7z x archived.7z -opath/to/output",
"largetype": "# Extract an archive with user-defined output path:"
},
"arg": "7z x archived.7z -opath/to/output",
"autocomplete": "# Extract an archive with user-defined output path:"
},
{
"title": "# Extract an archive to stdout:",
"subtitle": "7z x archived.7z -so",
"text": {
"copy": "7z x archived.7z -so",
"largetype": "# Extract an archive to stdout:"
},
"arg": "7z x archived.7z -so",
"autocomplete": "# Extract an archive to stdout:"
},
{
"title": "# Archive using a specific archive type:",
"subtitle": "7z a -tzip|gzip|bzip2|tar archived.7z path/to/file_or_directory",
"text": {
"copy": "7z a -tzip|gzip|bzip2|tar archived.7z path/to/file_or_directory",
"largetype": "# Archive using a specific archive type:"
},
"arg": "7z a -tzip|gzip|bzip2|tar archived.7z path/to/file_or_directory",
"autocomplete": "# Archive using a specific archive type:"
},
{
"title": "# List available archive types:",
"subtitle": "7z i",
"text": {
"copy": "7z i",
"largetype": "# List available archive types:"
},
"arg": "7z i",
"autocomplete": "# List available archive types:"
},
{
"title": "# List the contents of an archive file:",
"subtitle": "7z l archived.7z",
"text": {
"copy": "7z l archived.7z",
"largetype": "# List the contents of an archive file:"
},
"arg": "7z l archived.7z",
"autocomplete": "# List the contents of an archive file:"
}
]
}
As you can see, I only use the title and the command itself duplicating in different fields to control Alfred behaviour.
I shoud warn you about the current limitations:
"The main workflow doesn't support cheat sheets for programming languages or special pages like :help from cheat.sh (mainly because of the huge ammount of things that must be escaped to properly load as json)."