Gists from console
Problem
As developers, we often find ourselves needing a quick and easy way to save code snippets or entire scripts for future reference. GitHub Gists provide a convenient way to store and share these snippets. However, manually creating a Gist through the GitHub interface can be time-consuming, especially when you want to save snippets directly from your terminal.
Idea
To streamline the process of saving code snippets as Gists, I wanted to create a Fish shell function that could take a file, description, and visibility setting as arguments, and automatically create a Gist. This way, I could quickly push snippets to GitHub without leaving the terminal.
Stack
To implement this solution, I used:
-
Fish Shell: A smart and user-friendly command line shell.
-
cURL: A command line tool for transferring data with URLs.
-
GitHub API: The interface for creating Gists programmatically.
-
Python: To handle JSON string processing.
Solutions
Proposed Solution
The solution involves creating a Fish shell function that:
-
Takes a filename, description, and visibility setting as inputs.
-
Reads the file content, processes it for safe JSON transfer, and constructs a JSON payload.
-
Sends the payload to GitHub's API to create a new Gist with the provided details.
Token Creation
Before you can use this function, you'll need a GitHub token with gists
permissions. Here’s how to create it:
-
Go to GitHub: Log in to your GitHub account and navigate to Settings.
-
Generate Token: Under "Developer settings," click on "Personal access tokens" and generate a new token.
-
Set Permissions: Ensure the token has the
gists
scope enabled. This allows the token to create and manage Gists. -
Store the Token: Once generated, store the token securely in an environment variable, like
GITHUB_TOKEN
.
Exporting the Token as an Environment Variable
To make sure your Fish shell function can access your GitHub token, you'll need to export it as an environment variable. Here’s how you can do it:
-
Open your terminal.
-
Run the following command to export the token as an environment variable:
fish set -Ux GITHUB_TOKEN your_token_here
Replace your_token_here
with the actual token you generated from GitHub.
-
This command makes the
GITHUB_TOKEN
available globally in your Fish shell sessions. -
If you want this token to persist across sessions, add the command to your
config.fish
file, usually located in~/.config/fish/
.
Fish Function
Here's the Fish function to create a Gist:
function new_gist
# Check if the required arguments are provided
if test (count $argv) -lt 3
echo "Usage: new_gist <filename> <description> <visible>"
return 1
end
set filename $argv[1]
set description $argv[2]
set visible $argv[3]
# Convert the "visible" argument to a boolean value
if test "$visible" = "True"
set public true
else if test "$visible" = "False"
set public false
else
echo "The 'visible' argument must be either 'True' or 'False'."
return 1
end
# Read the file content, escape necessary characters, and handle newlines
set filecontent (cat $filename | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')
# Construct the JSON payload using the output from Python
set payload '{"description": "'$description'", "public": '$public', "files": {"'$filename'": {"content": '$filecontent'}}}'
# Make the request to create the gist
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/gists \
-d "$payload"
end
Explanation
-
Argument Handling: The function expects three arguments: the file name, description, and visibility. If the visibility is not
True
orFalse
, it will prompt the user to correct it. -
Visibility Handling: The visibility argument controls whether the Gist will be public or private. It converts the string "True" or "False" into a boolean value that the GitHub API can process.
-
File Content Processing: Fish shell and JSON processing can be tricky due to special characters and newlines. This function uses Python to safely encode the file content into a JSON-compatible format.
-
Payload Construction: The JSON payload is built using the provided arguments and processed content, ensuring it is correctly formatted for the GitHub API.
-
cURL Command: The function uses cURL to send the request to GitHub, leveraging the personal access token for authentication.
The curl
Command
The curl
command is used to send an HTTP request to the GitHub API to create
a new Gist. Below is a breakdown of each line and the flags used:
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/gists \
-d "$payload"
-
curl -L \
:curl
: The command-line tool used to transfer data to or from a server.-L
: This flag tellscurl
to follow any redirects. This is useful if the URL provided might redirect to another URL (like fromhttp
tohttps
), ensuring that the request reaches its destination.
-
-X POST \
:-X
: Specifies the HTTP method to use.POST
: This indicates that we're making a POST request, which is typically used to send data to the server, such as creating a new resource.
-
-H "Accept: application/vnd.github+json" \
:-H
: Adds a header to the request."Accept: application/vnd.github+json"
: This header tells the server that the client expects a response in JSON format specific to GitHub's API.
-
-H "Authorization: Bearer $GITHUB_TOKEN" \
:"Authorization: Bearer $GITHUB_TOKEN"
: This header provides the authorization token required to authenticate the request. TheBearer
keyword is followed by the token stored in theGITHUB_TOKEN
environment variable.
-
-H "X-GitHub-Api-Version: 2022-11-28" \
:"X-GitHub-Api-Version: 2022-11-28"
: This custom header specifies the version of the GitHub API to use. It ensures that the request is handled according to the API version specified, maintaining compatibility with any changes GitHub might make in future versions.
-
https://api.github.com/gists \
:- This is the URL to which the request is sent. It points to the GitHub API endpoint for creating new Gists.
-
-d "$payload"
:-d
: This flag indicates that the following string is the data to be sent in the request body."$payload"
: This variable contains the JSON-formatted data that includes the Gist's description, visibility setting, and file content. This payload is sent as the body of the POST request.
How to Use the Function
- Navigate to the directory containing the file you want to save as a Gist.
- Run the command:
new_gist <file.ext> <description> <visible>
. - For example:
new_gist myscript.py "My Python Script" True
. - Check GitHub: Your new Gist should now be available in your GitHub account, either as a public or private Gist, depending on the visibility you set.
Conclusions
This Fish shell function significantly simplifies the process of saving code snippets to GitHub Gists, making it quick and convenient to store and share code directly from the terminal. The flexibility to set the visibility of the Gist ensures you can control who has access to your snippets, whether they are public or private.