Skip to content

Commit 5e1fd30

Browse files
committed
Checkin the first stab at this.
1 parent e6821ff commit 5e1fd30

File tree

8 files changed

+168
-2
lines changed

8 files changed

+168
-2
lines changed

.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*.cr]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
indent_style = space
8+
indent_size = 2
9+
trim_trailing_whitespace = true

.github/workflows/ci.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: define.cr CI
2+
3+
on:
4+
schedule:
5+
- cron: '0 3 * * *'
6+
push:
7+
branches: [ main ]
8+
pull_request:
9+
branches: [ main ]
10+
11+
jobs:
12+
build:
13+
runs-on: ubuntu-latest
14+
15+
container:
16+
image: crystallang/crystal
17+
18+
steps:
19+
- uses: actions/checkout@v2
20+
- name: Install dependencies
21+
run: shards install
22+
- name: Run tests
23+
run: crystal spec -t -s
24+
- name: Run Ameba
25+
run: bin/ameba
26+
- name: Build docs
27+
run: crystal docs
28+
- name: Deploy
29+
uses: peaceiris/actions-gh-pages@v3
30+
with:
31+
github_token: ${{ secrets.GITHUB_TOKEN }}
32+
publish_dir: ./docs

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/docs/
2+
/lib/
3+
/bin/
4+
/.shards/
5+
*.dwarf
6+
7+
# Libraries don't need dependency lock
8+
# Dependencies will be locked in applications that use them
9+
/shard.lock

README.md

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,54 @@
1-
# defined.cr
2-
This is a very small shard that just provides a macro that can be used to see if a given type/constant is defined. The main use case would be for a library that might choose to do different things depending on whether another, optional library has been required or not.
1+
# defined
2+
3+
![Defined.cr CI](https://img.shields.io/github/workflow/status/wyhaines/defined.cr/defined.cr%20CI?style=for-the-badge&logo=GitHub)
4+
[![GitHub release](https://img.shields.io/github/release/wyhaines/defined.cr.svg?style=for-the-badge)](https://github.com/wyhaines/defined.cr/releases)
5+
![GitHub commits since latest release (by SemVer)](https://img.shields.io/github/commits-since/wyhaines/defined.cr/latest?style=for-the-badge)
6+
7+
This is a very small shard that provides a single macro, *defined?()*, which returns *VALUE*/*false* depending on whether the argument provided points to an existing constant. All lookups start at the top level and descend from there.
8+
9+
## Installation
10+
11+
1. Add the dependency to your `shard.yml`:
12+
13+
```yaml
14+
dependencies:
15+
defined:
16+
github: wyhaines/defined
17+
```
18+
19+
2. Run `shards install`
20+
21+
## Usage
22+
23+
```crystal
24+
require "defined"
25+
```
26+
27+
```crystal
28+
if defined?("OptionalFeature")
29+
# The OptionalFeature library has been included into the code, so use it.
30+
else
31+
# It's not there.
32+
end
33+
34+
stuff = defined?("My::Stuff::Library") || Array(String)
35+
```
36+
37+
## Development
38+
39+
TODO: Write development instructions here
40+
41+
## Contributing
42+
43+
1. Fork it (<https://github.com/wyhaines/defined/fork>)
44+
2. Create your feature branch (`git checkout -b my-new-feature`)
45+
3. Commit your changes (`git commit -am 'Add some feature'`)
46+
4. Push to the branch (`git push origin my-new-feature`)
47+
5. Create a new Pull Request
48+
49+
## Contributors
50+
51+
- [Kirk Haines](https://github.com/wyhaines) - creator and maintainer
52+
53+
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/wyhaines/defined.cr?style=for-the-badge)
54+
![GitHub issues](https://img.shields.io/github/issues/wyhaines/defined.cr?style=for-the-badge)

shard.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: defined
2+
version: 0.1.0
3+
4+
authors:
5+
- Kirk Haines <[email protected]>
6+
7+
crystal: "*"
8+
9+
license: MIT
10+
11+
development_dependencies:
12+
ameba:
13+
github: crystal-ameba/ameba
14+
version: ~> 0.14

spec/defined_spec.cr

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
require "./spec_helper"
2+
3+
describe Defined do
4+
it "can find an existing constant, specified with a Symbol" do
5+
defined?(:String).should be_truthy
6+
end
7+
8+
it "can find an existing constant, specified with a String" do
9+
defined?("Int::Primitive").should be_truthy
10+
end
11+
12+
it "returns false when something isn't defined" do
13+
defined?("This::Thing::Does::Not::Exist").should be_false
14+
end
15+
16+
it "deals with a :: at the start of the constant name" do
17+
defined?("::Foo::Bar").should be_false
18+
defined?("::Hash").should be_truthy
19+
end
20+
end

spec/spec_helper.cr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
require "spec"
2+
require "../src/defined"

src/defined.cr

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
module Defined
2+
VERSION = "0.1.0"
3+
end
4+
5+
# This macro accepts a string or a symbol of a fully qualified constant name.
6+
# It validates whether the constant is defined, starting at the top level. The value
7+
# of the constant will be returned if it is defined. If it is not defined, `false` is
8+
# returned.
9+
macro defined?(const)
10+
{%
11+
parts = [] of String
12+
position = @type
13+
const.id.gsub(/^::/,"").split("::").all? do |part|
14+
clean_part = part.tr(":","").id
15+
parts << clean_part
16+
if position && position.has_constant?(clean_part.id)
17+
position = position.constant(clean_part.id)
18+
else
19+
position = false
20+
end
21+
end
22+
%}
23+
{% if position %}
24+
{{ parts.join("::").id }}
25+
{% else %}
26+
false
27+
{% end %}
28+
end

0 commit comments

Comments
 (0)